Optimised Renderer
This commit is contained in:
parent
d7a0ca53c8
commit
10c5096604
54
imgui.ini
54
imgui.ini
@ -10,24 +10,24 @@ Collapsed=1
|
||||
|
||||
[Window][WindowOverViewport_11111111]
|
||||
Pos=0,19
|
||||
Size=1920,1158
|
||||
Size=32,32
|
||||
Collapsed=0
|
||||
|
||||
[Window][Inspector]
|
||||
Pos=0,644
|
||||
Size=385,533
|
||||
Pos=0,42
|
||||
Size=15,9
|
||||
Collapsed=0
|
||||
DockId=0x0000000A,0
|
||||
|
||||
[Window][Scene Tree]
|
||||
Pos=0,19
|
||||
Size=385,623
|
||||
Size=15,21
|
||||
Collapsed=0
|
||||
DockId=0x00000009,0
|
||||
|
||||
[Window][Viewport]
|
||||
Pos=387,19
|
||||
Size=1533,442
|
||||
Pos=17,19
|
||||
Size=15,15
|
||||
Collapsed=0
|
||||
DockId=0x00000007,0
|
||||
|
||||
@ -36,14 +36,14 @@ Size=1280,19
|
||||
Collapsed=0
|
||||
|
||||
[Window][Performance Info]
|
||||
Pos=1672,463
|
||||
Size=248,470
|
||||
Pos=30,36
|
||||
Size=4,7
|
||||
Collapsed=0
|
||||
DockId=0x00000003,0
|
||||
|
||||
[Window][Console]
|
||||
Pos=387,926
|
||||
Size=1283,251
|
||||
Pos=17,44
|
||||
Size=11,7
|
||||
Collapsed=0
|
||||
DockId=0x0000000C,0
|
||||
|
||||
@ -54,8 +54,8 @@ Collapsed=0
|
||||
DockId=0x00000007,1
|
||||
|
||||
[Window][Profiler]
|
||||
Pos=387,463
|
||||
Size=1283,461
|
||||
Pos=17,36
|
||||
Size=11,6
|
||||
Collapsed=0
|
||||
DockId=0x0000000B,0
|
||||
|
||||
@ -78,23 +78,23 @@ Collapsed=0
|
||||
DockId=0x0000000B,1
|
||||
|
||||
[Window][Color Correction]
|
||||
Pos=1672,935
|
||||
Size=248,242
|
||||
Pos=30,45
|
||||
Size=4,6
|
||||
Collapsed=0
|
||||
DockId=0x00000004,0
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1920,1158 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x11111111 SizeRef=385,701 Split=Y Selected=0x12EF0F59
|
||||
DockNode ID=0x00000009 Parent=0x00000001 SizeRef=385,623 HiddenTabBar=1 Selected=0x12EF0F59
|
||||
DockNode ID=0x0000000A Parent=0x00000001 SizeRef=385,533 HiddenTabBar=1 Selected=0x36DC96AB
|
||||
DockNode ID=0x00000002 Parent=0x11111111 SizeRef=1533,701 Split=Y Selected=0xC450F867
|
||||
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,442 CentralNode=1 HiddenTabBar=1 Selected=0xC450F867
|
||||
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,714 Split=X Selected=0x9B5D3198
|
||||
DockNode ID=0x00000005 Parent=0x00000008 SizeRef=1283,481 Split=Y Selected=0x9B5D3198
|
||||
DockNode ID=0x0000000B Parent=0x00000005 SizeRef=1283,461 HiddenTabBar=1 Selected=0x9B5D3198
|
||||
DockNode ID=0x0000000C Parent=0x00000005 SizeRef=1283,251 HiddenTabBar=1 Selected=0xEA83D666
|
||||
DockNode ID=0x00000006 Parent=0x00000008 SizeRef=248,481 Split=Y Selected=0x3FC1A724
|
||||
DockNode ID=0x00000003 Parent=0x00000006 SizeRef=226,470 HiddenTabBar=1 Selected=0x3FC1A724
|
||||
DockNode ID=0x00000004 Parent=0x00000006 SizeRef=226,242 HiddenTabBar=1 Selected=0xA873C17F
|
||||
DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=32,32 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x11111111 SizeRef=333,701 Split=Y Selected=0x12EF0F59
|
||||
DockNode ID=0x00000009 Parent=0x00000001 SizeRef=385,797 HiddenTabBar=1 Selected=0x12EF0F59
|
||||
DockNode ID=0x0000000A Parent=0x00000001 SizeRef=385,359 HiddenTabBar=1 Selected=0x36DC96AB
|
||||
DockNode ID=0x00000002 Parent=0x11111111 SizeRef=1249,701 Split=Y Selected=0xC450F867
|
||||
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,664 CentralNode=1 HiddenTabBar=1 Selected=0xC450F867
|
||||
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,492 Split=X Selected=0x9B5D3198
|
||||
DockNode ID=0x00000005 Parent=0x00000008 SizeRef=1053,481 Split=Y Selected=0x9B5D3198
|
||||
DockNode ID=0x0000000B Parent=0x00000005 SizeRef=1283,242 HiddenTabBar=1 Selected=0x9B5D3198
|
||||
DockNode ID=0x0000000C Parent=0x00000005 SizeRef=1283,248 HiddenTabBar=1 Selected=0xEA83D666
|
||||
DockNode ID=0x00000006 Parent=0x00000008 SizeRef=194,481 Split=Y Selected=0x3FC1A724
|
||||
DockNode ID=0x00000003 Parent=0x00000006 SizeRef=226,273 HiddenTabBar=1 Selected=0x3FC1A724
|
||||
DockNode ID=0x00000004 Parent=0x00000006 SizeRef=226,217 HiddenTabBar=1 Selected=0xA873C17F
|
||||
|
||||
|
14514
profile_export.json
14514
profile_export.json
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,2 @@
|
||||
[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\Components\ScriptComponent.cpp -o src\build\Components\ScriptComponent.o
|
||||
[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\Renderer.cpp -o src\build\Renderer.o
|
||||
[LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\CameraComponent.o src\build\Components\LightComponent.o src\build\Components\PhysicsComponent.o src\build\Components\ScriptComponent.o src\build\Components\SpriteComponent.o src\build\Components\TextComonent.o src\build\Components\TilemapComponent.o src\build\Entitys\Object.o src\build\utils\EngineConfig.o src\build\utils\ExceptionHandler.o src\build\utils\FileDialog.o src\build\utils\GameObjectsList.o src\build\utils\Logging.o src\build\utils\Profiler.o src\build\utils\Shader.o src\build\utils\UID.o src\build\utils\utils.o src\build\lapi.o src\build\lauxlib.o src\build\lbaselib.o src\build\lcode.o src\build\lcorolib.o src\build\lctype.o src\build\ldblib.o src\build\ldebug.o src\build\ldo.o src\build\ldump.o src\build\lfunc.o src\build\lgc.o src\build\linit.o src\build\liolib.o src\build\llex.o src\build\lmathlib.o src\build\lmem.o src\build\loadlib.o src\build\lobject.o src\build\lopcodes.o src\build\loslib.o src\build\lparser.o src\build\lstate.o src\build\lstring.o src\build\lstrlib.o src\build\ltable.o src\build\ltablib.o src\build\ltm.o src\build\lua.o src\build\luac.o src\build\lundump.o src\build\lutf8lib.o src\build\lvm.o src\build\lzio.o src\build\imgui.o src\build\imgui_demo.o src\build\imgui_draw.o src\build\imgui_impl_glfw.o src\build\imgui_impl_opengl3.o src\build\imgui_tables.o src\build\imgui_widgets.o src\build\aabb.o src\build\arena_allocator.o src\build\array.o src\build\bitset.o src\build\body.o src\build\broad_phase.o src\build\constraint_graph.o src\build\contact.o src\build\contact_solver.o src\build\core.o src\build\distance.o src\build\distance_joint.o src\build\dynamic_tree.o src\build\geometry.o src\build\hull.o src\build\id_pool.o src\build\island.o src\build\joint.o src\build\manifold.o src\build\math_functions.o src\build\motor_joint.o src\build\mouse_joint.o src\build\mover.o src\build\prismatic_joint.o src\build\revolute_joint.o src\build\sensor.o src\build\shape.o src\build\solver.o src\build\solver_set.o src\build\table.o src\build\timer.o src\build\types.o src\build\weld_joint.o src\build\wheel_joint.o src\build\world.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto
|
||||
[RUN] Executed app.exe successfully.
|
||||
|
62
src/assets/lua/fireflyes.lua
Normal file
62
src/assets/lua/fireflyes.lua
Normal file
@ -0,0 +1,62 @@
|
||||
Engine.DebugLua(true)
|
||||
|
||||
local Objects = {}
|
||||
local Velocities = {}
|
||||
|
||||
-- new border extents
|
||||
local MinX, MinY = 0, 0
|
||||
local MaxX, MaxY = 5096, 5096
|
||||
local Speed = 1000 -- units per second
|
||||
|
||||
-- simple clamp
|
||||
local function clamp(v, lo, hi)
|
||||
if v < lo then return lo end
|
||||
if v > hi then return hi end
|
||||
return v
|
||||
end
|
||||
|
||||
function OnInit()
|
||||
math.randomseed(os.time())
|
||||
for i = 0, 99 do
|
||||
local tag = "Light_" .. i
|
||||
local obj = Engine.GetObjectByTag(tag)
|
||||
if obj then
|
||||
table.insert(Objects, obj)
|
||||
-- random direction
|
||||
local ang = math.random() * 2 * math.pi
|
||||
local vx = math.cos(ang) * Speed
|
||||
local vy = math.sin(ang) * Speed
|
||||
-- store velocity in plain table
|
||||
Velocities[obj] = { x = vx, y = vy }
|
||||
else
|
||||
Engine.LogError("Object '" .. tag .. "' not found!")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function OnUpdate(dt)
|
||||
for _, obj in ipairs(Objects) do
|
||||
local vel = Velocities[obj]
|
||||
local pos = obj:GetPosition()
|
||||
|
||||
-- integrate
|
||||
local nx = pos.x + vel.x * dt
|
||||
local ny = pos.y + vel.y * dt
|
||||
|
||||
-- bounce X against [MinX,MaxX]
|
||||
if nx < MinX or nx > MaxX then
|
||||
vel.x = -vel.x
|
||||
nx = clamp(nx, MinX, MaxX)
|
||||
end
|
||||
|
||||
-- bounce Y against [MinY,MaxY]
|
||||
if ny < MinY or ny > MaxY then
|
||||
vel.y = -vel.y
|
||||
ny = clamp(ny, MinY, MaxY)
|
||||
end
|
||||
|
||||
-- store back and apply
|
||||
Velocities[obj] = vel
|
||||
obj:SetPosition(Vector2(nx, ny))
|
||||
end
|
||||
end
|
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,6 @@
|
||||
#include "../utils/Profiler.h"
|
||||
#include "../utils/utils.h"
|
||||
|
||||
|
||||
#include <lua.hpp>
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
@ -218,14 +217,13 @@ static int Lua_GetObjectByTag(lua_State *L)
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int Lua_Vector2_New(lua_State *L)
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("Vector2()");
|
||||
LuaVector2 *vec = static_cast<LuaVector2 *>(lua_newuserdata(L, sizeof(LuaVector2)));
|
||||
int nargs = lua_gettop(L);
|
||||
vec->x = nargs >= 1 ? (float)lua_tonumber(L, 1) : 0.0f;
|
||||
vec->y = nargs >= 2 ? (float)lua_tonumber(L, 2) : 0.0f;
|
||||
vec->x = nargs >= 1 ? static_cast<float>(lua_tonumber(L, 1)) : 0.0f;
|
||||
vec->y = nargs >= 2 ? static_cast<float>(lua_tonumber(L, 2)) : 0.0f;
|
||||
luaL_setmetatable(L, LUA_VECTOR2_MT);
|
||||
return 1;
|
||||
}
|
||||
@ -233,39 +231,56 @@ static int Lua_Vector2_New(lua_State *L)
|
||||
static int Lua_Vector2_Index(lua_State *L)
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("Vector2::index");
|
||||
auto *vec = (LuaVector2 *)luaL_checkudata(L, 1, LUA_VECTOR2_MT);
|
||||
const char *key = luaL_checkstring(L, 2);
|
||||
if (strcmp(key, "x") == 0)
|
||||
auto *vec = static_cast<LuaVector2 *>(luaL_checkudata(L, 1, LUA_VECTOR2_MT));
|
||||
const char *key = lua_tostring(L, 2); // safer and faster than luaL_checkstring for profiling edge cases
|
||||
|
||||
// Fast string comparison
|
||||
if (key[0] == 'x' && key[1] == '\0')
|
||||
{
|
||||
lua_pushnumber(L, vec->x);
|
||||
else if (strcmp(key, "y") == 0)
|
||||
}
|
||||
else if (key[0] == 'y' && key[1] == '\0')
|
||||
{
|
||||
lua_pushnumber(L, vec->y);
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_pushnil(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int Lua_Vector2_NewIndex(lua_State *L)
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("Vector2::newindex");
|
||||
auto *vec = (LuaVector2 *)luaL_checkudata(L, 1, LUA_VECTOR2_MT);
|
||||
const char *key = luaL_checkstring(L, 2);
|
||||
float value = (float)luaL_checknumber(L, 3);
|
||||
if (strcmp(key, "x") == 0)
|
||||
auto *vec = static_cast<LuaVector2 *>(luaL_checkudata(L, 1, LUA_VECTOR2_MT));
|
||||
const char *key = lua_tostring(L, 2);
|
||||
float value = static_cast<float>(luaL_checknumber(L, 3));
|
||||
|
||||
if (key[0] == 'x' && key[1] == '\0')
|
||||
{
|
||||
vec->x = value;
|
||||
else if (strcmp(key, "y") == 0)
|
||||
}
|
||||
else if (key[0] == 'y' && key[1] == '\0')
|
||||
{
|
||||
vec->y = value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RegisterVector2Type(lua_State *L)
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("RegisterVector2Type");
|
||||
|
||||
luaL_newmetatable(L, LUA_VECTOR2_MT);
|
||||
lua_pushcfunction(L, Lua_Vector2_Index);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, Lua_Vector2_NewIndex);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_pop(L, 1); // Pop metatable
|
||||
|
||||
lua_pushcfunction(L, Lua_Vector2_New);
|
||||
lua_setglobal(L, "Vector2");
|
||||
}
|
||||
|
@ -386,11 +386,11 @@ void Engine::Init()
|
||||
//{
|
||||
// std::random_device rd;
|
||||
// std::mt19937 rng(rd());
|
||||
// std::uniform_real_distribution<float> lightRadius(1000.0f, 2000.0f);
|
||||
// std::uniform_real_distribution<float> lightIntensity(1.0f, 3.0f);
|
||||
// std::uniform_real_distribution<float> lightRadius(200.0f, 1000.0f);
|
||||
// std::uniform_real_distribution<float> lightIntensity(0.5f, 1.0f);
|
||||
// std::uniform_real_distribution<float> hueDist(0.0f, 1.0f);
|
||||
//
|
||||
// const float tileSize = 1024.0f; // approximate texture size
|
||||
// const float tileSize = 2048.0f; // approximate texture size
|
||||
// const int gridSize = 10;
|
||||
//
|
||||
// // 10x10 grid of pebble sprites
|
||||
@ -746,7 +746,6 @@ void Engine::Run()
|
||||
}
|
||||
|
||||
profiler.BeginEngineSection("glfwPollEvents");
|
||||
|
||||
glfwPollEvents();
|
||||
profiler.EndEngineSection();
|
||||
|
||||
@ -1014,9 +1013,9 @@ void Engine::Run()
|
||||
m_scriptUpdates.clear();
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.BeginEngineSection("Draw Editor Grid");
|
||||
Renderer::DrawEditorGrid(cameraPos, cameraZoom);
|
||||
profiler.EndEngineSection();
|
||||
//profiler.BeginEngineSection("Draw Editor Grid");
|
||||
//Renderer::DrawEditorGrid(cameraPos, cameraZoom);
|
||||
//profiler.EndEngineSection();
|
||||
|
||||
// Collect Objects
|
||||
profiler.BeginEngineSection("Collect Objects");
|
||||
@ -1077,9 +1076,7 @@ void Engine::Run()
|
||||
profiler.EndFrame();
|
||||
|
||||
// End renderer
|
||||
profiler.BeginEngineSection("Renderer::End");
|
||||
Renderer::End();
|
||||
profiler.EndEngineSection();
|
||||
|
||||
// Display render target texture
|
||||
GLuint texID = Renderer::GetFinalTexture();
|
||||
|
@ -50,30 +50,49 @@ int Renderer::s_ClusterRows = 0;
|
||||
GLuint Renderer::bloomFBO = 0;
|
||||
GLuint Renderer::bloomTexture = 0;
|
||||
|
||||
struct CachedLightUniforms {
|
||||
struct CachedLightUniforms
|
||||
{
|
||||
std::string posName;
|
||||
std::string colorName;
|
||||
std::string intensityName;
|
||||
std::string radiusName;
|
||||
};
|
||||
|
||||
struct BatchedSprite
|
||||
{
|
||||
glm::vec2 screenPos;
|
||||
glm::vec2 size;
|
||||
float rotationRad;
|
||||
glm::vec4 texCoords; // optional, if you support atlases
|
||||
GLuint textureID;
|
||||
GLuint normalMapID;
|
||||
SpriteComponent::RenderType renderType;
|
||||
SpriteComponent *sprite; // optional: to access lighting per sprite if needed
|
||||
};
|
||||
|
||||
struct SortedDrawEntry
|
||||
{
|
||||
BatchedSprite sprite;
|
||||
Shader *shader;
|
||||
bool useLighting;
|
||||
};
|
||||
|
||||
std::vector<CachedLightUniforms> s_LightUniforms;
|
||||
|
||||
void InitLightUniforms(int maxLights) {
|
||||
void InitLightUniforms(int maxLights)
|
||||
{
|
||||
s_LightUniforms.clear();
|
||||
s_LightUniforms.reserve(maxLights);
|
||||
for (int i = 0; i < maxLights; ++i) {
|
||||
s_LightUniforms.push_back({
|
||||
"uLightPos[" + std::to_string(i) + "]",
|
||||
"uLightColor[" + std::to_string(i) + "]",
|
||||
"uLightIntensity[" + std::to_string(i) + "]",
|
||||
"uLightRadius[" + std::to_string(i) + "]"
|
||||
});
|
||||
for (int i = 0; i < maxLights; ++i)
|
||||
{
|
||||
s_LightUniforms.push_back({"uLightPos[" + std::to_string(i) + "]",
|
||||
"uLightColor[" + std::to_string(i) + "]",
|
||||
"uLightIntensity[" + std::to_string(i) + "]",
|
||||
"uLightRadius[" + std::to_string(i) + "]"});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<SortedDrawEntry> sortedDrawList;
|
||||
|
||||
void Renderer::InitQuad()
|
||||
{
|
||||
@ -195,51 +214,108 @@ void Renderer::Init()
|
||||
s_DrawCalls = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Renderer::UpdateClusterLights()
|
||||
{
|
||||
PROFILE_ENGINE_SCOPE("Renderer::UpdateClusterLights");
|
||||
|
||||
s_ClusterCols = (width + CLUSTER_SIZE - 1) / CLUSTER_SIZE;
|
||||
s_ClusterRows = (height + CLUSTER_SIZE - 1) / CLUSTER_SIZE;
|
||||
int totalClusters = s_ClusterCols * s_ClusterRows;
|
||||
const int totalClusters = s_ClusterCols * s_ClusterRows;
|
||||
|
||||
static int lastCols = 0, lastRows = 0;
|
||||
if (lastCols != s_ClusterCols || lastRows != s_ClusterRows) {
|
||||
lastCols = s_ClusterCols;
|
||||
lastRows = s_ClusterRows;
|
||||
s_Clusters.clear();
|
||||
s_Clusters.resize(totalClusters);
|
||||
for (auto &c : s_Clusters)
|
||||
c.lightIndices.reserve(MAX_LIGHTS_PER_CLUSTER);
|
||||
}
|
||||
|
||||
s_Clusters.resize(totalClusters);
|
||||
for (auto &c : s_Clusters)
|
||||
c.lightIndices.clear();
|
||||
|
||||
for (int i = 0; i < s_Lights.size(); ++i)
|
||||
const float invCluster = 1.0f / float(CLUSTER_SIZE);
|
||||
const int maxCol = s_ClusterCols - 1;
|
||||
const int maxRow = s_ClusterRows - 1;
|
||||
|
||||
for (int i = 0, n = int(s_Lights.size()); i < n; ++i)
|
||||
{
|
||||
const Light &light = s_Lights[i];
|
||||
glm::vec2 min = light.screenPos - glm::vec2(light.radius);
|
||||
glm::vec2 max = light.screenPos + glm::vec2(light.radius);
|
||||
PROFILE_ENGINE_SCOPE("L" + std::to_string(i));
|
||||
|
||||
int minX = glm::clamp(int(min.x) / CLUSTER_SIZE, 0, s_ClusterCols - 1);
|
||||
int maxX = glm::clamp(int(max.x) / CLUSTER_SIZE, 0, s_ClusterCols - 1);
|
||||
int minY = glm::clamp(int(min.y) / CLUSTER_SIZE, 0, s_ClusterRows - 1);
|
||||
int maxY = glm::clamp(int(max.y) / CLUSTER_SIZE, 0, s_ClusterRows - 1);
|
||||
const Light& light = s_Lights[i];
|
||||
glm::vec2 lo = light.screenPos - glm::vec2(light.radius);
|
||||
glm::vec2 hi = light.screenPos + glm::vec2(light.radius);
|
||||
|
||||
for (int y = minY; y <= maxY; ++y)
|
||||
for (int x = minX; x <= maxX; ++x)
|
||||
{
|
||||
Cluster &cluster = s_Clusters[y * s_ClusterCols + x];
|
||||
if (cluster.lightIndices.size() < MAX_LIGHTS_PER_CLUSTER)
|
||||
cluster.lightIndices.push_back(i);
|
||||
int minX = std::max(int(lo.x * invCluster), 0);
|
||||
int maxX = std::min(int(hi.x * invCluster), maxCol);
|
||||
int minY = std::max(int(lo.y * invCluster), 0);
|
||||
int maxY = std::min(int(hi.y * invCluster), maxRow);
|
||||
|
||||
for (int y = minY; y <= maxY; ++y) {
|
||||
for (int x = minX; x <= maxX; ++x) {
|
||||
auto &cell = s_Clusters[y * s_ClusterCols + x].lightIndices;
|
||||
if (int(cell.size()) < MAX_LIGHTS_PER_CLUSTER)
|
||||
cell.emplace_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int> packed;
|
||||
packed.resize(totalClusters * MAX_LIGHTS_PER_CLUSTER, -1);
|
||||
for (int i = 0; i < totalClusters; ++i)
|
||||
{
|
||||
for (int j = 0; j < s_Clusters[i].lightIndices.size(); ++j)
|
||||
packed[i * MAX_LIGHTS_PER_CLUSTER + j] = s_Clusters[i].lightIndices[j];
|
||||
static std::vector<int> packed;
|
||||
static size_t gpuBufferBytes = 0;
|
||||
const size_t packCount = size_t(totalClusters) * MAX_LIGHTS_PER_CLUSTER;
|
||||
const size_t byteSize = packCount * sizeof(int);
|
||||
|
||||
packed.assign(packCount, -1);
|
||||
for (int c = 0; c < totalClusters; ++c) {
|
||||
auto &src = s_Clusters[c].lightIndices;
|
||||
std::copy(src.begin(), src.end(), packed.begin() + c * MAX_LIGHTS_PER_CLUSTER);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, s_ClusterSSBO);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, packed.size() * sizeof(int), packed.data(), GL_DYNAMIC_DRAW);
|
||||
if (byteSize != gpuBufferBytes) {
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, byteSize, packed.data(), GL_DYNAMIC_DRAW);
|
||||
gpuBufferBytes = byteSize;
|
||||
} else {
|
||||
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, byteSize, packed.data());
|
||||
}
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, s_ClusterSSBO);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Renderer::Resize(int w, int h)
|
||||
{
|
||||
if (w == width && h == height)
|
||||
@ -288,9 +364,8 @@ void Renderer::Begin()
|
||||
void Renderer::End()
|
||||
{
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
PROFILE_ENGINE_SCOPE("Renderer::End");
|
||||
FlushSprites();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
@ -373,117 +448,104 @@ void Renderer::DrawSprite(SpriteComponent *sprite, const glm::vec2 &pos, float z
|
||||
PROFILE_DEEP_SCOPE("DrawSprite");
|
||||
|
||||
if (!sprite->HasTexture())
|
||||
{
|
||||
static bool warned = false;
|
||||
if (!warned)
|
||||
{
|
||||
Logger::LogWarning("Tried to draw sprite with no texture");
|
||||
warned = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Shader *shader = &unlitShader;
|
||||
bool useLighting = false;
|
||||
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("ShaderSelect");
|
||||
if (g_engineConfig.settings.lighting_enabled && sprite->GetRenderType() == SpriteComponent::RenderType::Lit)
|
||||
{
|
||||
shader = &spriteShader;
|
||||
useLighting = true;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("ShaderUse");
|
||||
shader->Use();
|
||||
}
|
||||
|
||||
glm::vec2 size = sprite->GetSize();
|
||||
glm::vec2 screenPos = (pos - CameraPos) * zoom + glm::vec2(width, height) * 0.5f - (size * zoom * 0.5f);
|
||||
float rotationDeg = sprite->GetOwner()->GetWorldRotation();
|
||||
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("SetUniforms");
|
||||
BatchedSprite entry;
|
||||
entry.screenPos = screenPos;
|
||||
entry.size = size * zoom;
|
||||
entry.rotationRad = glm::radians(rotationDeg);
|
||||
entry.textureID = sprite->GetTextureID();
|
||||
entry.normalMapID = sprite->GetNormalMapID();
|
||||
entry.renderType = sprite->GetRenderType();
|
||||
entry.sprite = sprite;
|
||||
|
||||
SortedDrawEntry drawEntry;
|
||||
drawEntry.sprite = entry;
|
||||
drawEntry.shader = (g_engineConfig.settings.lighting_enabled && entry.renderType == SpriteComponent::RenderType::Lit)
|
||||
? &spriteShader
|
||||
: &unlitShader;
|
||||
drawEntry.useLighting = (drawEntry.shader == &spriteShader);
|
||||
|
||||
sortedDrawList.push_back(drawEntry);
|
||||
}
|
||||
|
||||
void Renderer::FlushSprites()
|
||||
{
|
||||
PROFILE_ENGINE_SCOPE("Renderer::FlushSprites");
|
||||
|
||||
if (sortedDrawList.empty())
|
||||
return;
|
||||
|
||||
glBindVertexArray(quadVAO);
|
||||
|
||||
Shader *currentShader = nullptr;
|
||||
bool currentLighting = false;
|
||||
|
||||
for (const auto &entry : sortedDrawList)
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("DrawSprite");
|
||||
|
||||
if (entry.shader != currentShader || entry.useLighting != currentLighting)
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("Transform");
|
||||
shader->SetVec2("uPos", screenPos);
|
||||
shader->SetVec2("uSize", size * zoom);
|
||||
shader->SetVec2("uScreen", glm::vec2(width, height));
|
||||
shader->SetFloat("uRotation", glm::radians(rotationDeg));
|
||||
currentShader = entry.shader;
|
||||
currentLighting = entry.useLighting;
|
||||
|
||||
currentShader->Use();
|
||||
currentShader->SetVec2("uScreen", glm::vec2(width, height));
|
||||
|
||||
if (currentLighting)
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("LightingSetup");
|
||||
s_ColorCorrection->Upload(*currentShader);
|
||||
currentShader->SetInt("uClusterWidth", CLUSTER_SIZE);
|
||||
currentShader->SetInt("uClusterHeight", CLUSTER_SIZE);
|
||||
currentShader->SetInt("uClusterCols", s_ClusterCols);
|
||||
currentShader->SetInt("uMaxLightsPerCluster", MAX_LIGHTS_PER_CLUSTER);
|
||||
currentShader->SetInt("uLightCount", static_cast<int>(s_Lights.size()));
|
||||
|
||||
for (int i = 0; i < s_Lights.size(); ++i)
|
||||
{
|
||||
const auto &u = s_LightUniforms[i];
|
||||
currentShader->SetVec2(u.posName.c_str(), s_Lights[i].screenPos);
|
||||
currentShader->SetVec3(u.colorName.c_str(), s_Lights[i].color);
|
||||
currentShader->SetFloat(u.intensityName.c_str(), s_Lights[i].intensity);
|
||||
currentShader->SetFloat(u.radiusName.c_str(), s_Lights[i].radius);
|
||||
}
|
||||
|
||||
currentShader->SetInt("uNormalMap", 1);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, s_ClusterSSBO);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("TexSlot");
|
||||
shader->SetInt("uTex", 0);
|
||||
}
|
||||
}
|
||||
// Uniforms
|
||||
currentShader->SetVec2("uPos", entry.sprite.screenPos);
|
||||
currentShader->SetVec2("uSize", entry.sprite.size);
|
||||
currentShader->SetFloat("uRotation", entry.sprite.rotationRad);
|
||||
currentShader->SetInt("uTex", 0);
|
||||
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("BindTex");
|
||||
// Textures
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, sprite->GetTextureID());
|
||||
}
|
||||
|
||||
if (useLighting)
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("Lighting");
|
||||
glBindTexture(GL_TEXTURE_2D, entry.sprite.textureID);
|
||||
|
||||
if (entry.useLighting)
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("ColorCorrection");
|
||||
s_ColorCorrection->Upload(*shader);
|
||||
}
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("SetLightParams");
|
||||
|
||||
shader->SetInt("uLightCount", static_cast<int>(s_Lights.size()));
|
||||
shader->SetInt("uClusterWidth", CLUSTER_SIZE);
|
||||
shader->SetInt("uClusterHeight", CLUSTER_SIZE);
|
||||
shader->SetInt("uClusterCols", s_ClusterCols);
|
||||
shader->SetInt("uMaxLightsPerCluster", MAX_LIGHTS_PER_CLUSTER);
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < s_Lights.size(); ++i) {
|
||||
PROFILE_DEEP_SCOPE(("L" + std::to_string(i)).c_str());
|
||||
|
||||
const auto& u = s_LightUniforms[i];
|
||||
shader->SetVec2(u.posName.c_str(), s_Lights[i].screenPos);
|
||||
shader->SetVec3(u.colorName.c_str(), s_Lights[i].color);
|
||||
shader->SetFloat(u.intensityName.c_str(), s_Lights[i].intensity);
|
||||
shader->SetFloat(u.radiusName.c_str(), s_Lights[i].radius);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("BindNorm");
|
||||
shader->SetInt("uNormalMap", 1);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, sprite->GetNormalMapID() ? sprite->GetNormalMapID() : defaultNormalMap);
|
||||
}
|
||||
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, s_ClusterSSBO);
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("Draw");
|
||||
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("VAO Bind");
|
||||
glBindVertexArray(quadVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, entry.sprite.normalMapID ? entry.sprite.normalMapID : defaultNormalMap);
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("GL Draw");
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
++s_DrawCalls;
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
++s_DrawCalls;
|
||||
glBindVertexArray(0);
|
||||
sortedDrawList.clear();
|
||||
}
|
||||
|
||||
int Renderer::GetDrawCallCount()
|
||||
@ -498,6 +560,7 @@ int Renderer::GetLightsCount()
|
||||
|
||||
void Renderer::DrawEditorGrid(const glm::vec2 &cameraPos, float zoom)
|
||||
{
|
||||
return; // This is stupid
|
||||
glUseProgram(0);
|
||||
glColor4f(0.5f, 0.5f, 0.5f, 0.25f);
|
||||
glLineWidth(1.0f);
|
||||
|
@ -68,6 +68,8 @@ public:
|
||||
|
||||
// Clustered lighting
|
||||
static void UpdateClusterLights(); // Call once per frame after all lights added
|
||||
static void FlushSprites();
|
||||
|
||||
|
||||
private:
|
||||
static std::vector<Light> s_Lights;
|
||||
|
Loading…
Reference in New Issue
Block a user