Cambios en el renderer para facilitar el uso de ImGui por ahí, fuera del propio renderer.

Implimentado un sistema de cámara y la consiguiente conversión entre WorldCoords y ScreenCoords.
This commit is contained in:
2022-01-31 20:59:07 +01:00
parent 92f743edf2
commit 77d78db774
5 changed files with 119 additions and 74 deletions
+37 -40
View File
@@ -28,10 +28,10 @@ namespace UE
} }
//Configuramos los parámetros de la ventana de SDL. //Configuramos los parámetros de la ventana de SDL.
SDL_WindowFlags windowFlags = (SDL_WindowFlags)(SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE); Uint32 windowFlags = (SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE);
//Creamos la ventana de SDL. //Creamos la ventana de SDL.
_window = SDL_CreateWindow("UberGame1", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, windowFlags); _window = SDL_CreateWindow("UberGame1", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screenSize.x, screenSize.y, windowFlags);
if (_window == NULL) if (_window == NULL)
{ {
UE_LOG_CRITICAL("No se ha podido crear la ventana de SDL con OpenGL y esas mierdas: {0}", SDL_GetError()); UE_LOG_CRITICAL("No se ha podido crear la ventana de SDL con OpenGL y esas mierdas: {0}", SDL_GetError());
@@ -85,14 +85,13 @@ namespace UE
void Renderer::RenderFrame() void Renderer::RenderFrame()
{ {
StartRender(); NewFrame();
RenderQueue(); RenderData();
RenderIMGUI(); EndFrame();
FinishRender();
} }
void Renderer::StartRender() void Renderer::NewFrame()
{ {
SDL_RenderClear(main_Renderer); SDL_RenderClear(main_Renderer);
@@ -100,9 +99,11 @@ namespace UE
ImGui_ImplSDL2_NewFrame(); ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame(); ImGui::NewFrame();
//Quizás deberíamos limpiar la cola y las Layers aquí para eliminar residuos...
} }
void Renderer::RenderQueue() void Renderer::RenderData()
{ {
//Add items to their layer. //Add items to their layer.
for (int i = 0; i < renderQueue.size(); i++) for (int i = 0; i < renderQueue.size(); i++)
@@ -112,7 +113,7 @@ namespace UE
//Add item i to layer number i.layer. //Add item i to layer number i.layer.
if (item.layer > LAYER_AMOUNT) if (item.layer > LAYER_AMOUNT)
{ {
std::cout << "Layer out of range\n"; UE_LOG_ERROR("Error rendering data: Can't render item to Layer {0} -> out of range\n", item.layer);
return; return;
} }
renderLayers.at(item.layer).push_back(item); renderLayers.at(item.layer).push_back(item);
@@ -135,15 +136,8 @@ namespace UE
} }
void Renderer::RenderIMGUI()
{
bool show = true;
ImGui::ShowDemoWindow(&show);
} void Renderer::EndFrame()
void Renderer::FinishRender()
{ {
//SDL_UpdateWindowSurface(window); //SDL_UpdateWindowSurface(window);
//SDL_RenderPresent(main_Renderer); //SDL_RenderPresent(main_Renderer);
@@ -161,14 +155,24 @@ namespace UE
void Renderer::SetScreenSize(Sint32 newWidth, Sint32 newHeight) void Renderer::SetScreenSize(int newWidth, int newHeight)
{ {
SCREEN_WIDTH = newWidth; screenSize.x = newWidth;
SCREEN_HEIGHT = newHeight; screenSize.y = newHeight;
SDL_SetWindowSize(_window, newWidth, newHeight); SDL_SetWindowSize(_window, newWidth, newHeight);
glViewport(0, 0, newWidth, newHeight); glViewport(0, 0, newWidth, newHeight);
UE_LOG_TRACE("Screen size chaged to: {0}x{1}", newWidth, newHeight);
} }
void Renderer::SetCamPosition(int posX, int posY)
{
camPosition.x = posX;
camPosition.y = posY;
UE_LOG_TRACE("Cam position chaged to: {0}x{1}", posX, posY);
}
//¿Deberíamos operar la posición para que tenga en cuenta la cámara?
void Renderer::DrawObject(SDL_Rect* position, SDL_Rect* texture_pos, SDL_Texture* texture) void Renderer::DrawObject(SDL_Rect* position, SDL_Rect* texture_pos, SDL_Texture* texture)
{ {
SDL_RenderCopy(main_Renderer, texture, texture_pos, position); SDL_RenderCopy(main_Renderer, texture, texture_pos, position);
@@ -181,9 +185,19 @@ namespace UE
//Add item i to layer number i.layer. //Add item i to layer number i.layer.
if (drawCall.layer > LAYER_AMOUNT) if (drawCall.layer > LAYER_AMOUNT)
{ {
std::cout << "Layer out of range\n"; UE_LOG_ERROR("Can't add DrawCall to Layer {0} -> out of range\n", drawCall.layer);
return; return;
} }
//Convertimos la posición del objeto de WorldCoords y ScreenCoords relativas a la camPosition.
//Únicamente cambiamos las coords. Se podría añadir un modificador para el tamaño en relación al tamaño de la cam o algo así.
//WorldCoords = ScreenPos + CamPos -> ScreenPos = WorldCoords - CamPos;
glm::ivec2 oPos{ drawCall.pos_rect.x, drawCall.pos_rect.y };
glm::ivec2 fPos = oPos - camPosition;
drawCall.pos_rect.x = fPos.x;
drawCall.pos_rect.y = fPos.y;
renderLayers.at(drawCall.layer).push_back(drawCall); renderLayers.at(drawCall.layer).push_back(drawCall);
//renderQueue.push_back(drawCall); //renderQueue.push_back(drawCall);
@@ -192,31 +206,14 @@ namespace UE
void Renderer::QueueDrawCall(int layer, SDL_Rect& position, SDL_Texture* texture, SDL_Rect& texture_position) void Renderer::QueueDrawCall(int layer, SDL_Rect& position, SDL_Texture* texture, SDL_Rect& texture_position)
{ {
DrawCall dc = DrawCall(layer, position, texture, texture_position); DrawCall dc = DrawCall(layer, position, texture, texture_position);
QueueDrawCall(dc);
//Add item i to layer number i.layer.
if (layer > LAYER_AMOUNT)
{
std::cout << "Layer out of range\n";
return;
}
renderLayers.at(layer).push_back(dc);
//renderQueue.push_back(dc);
} }
void Renderer::QueueDrawCall(int layer, SDL_Rect & position, SDL_Texture* texture) void Renderer::QueueDrawCall(int layer, SDL_Rect & position, SDL_Texture* texture)
{ {
//std::cout << "Drawable added to queue"; //std::cout << "Drawable added to queue";
DrawCall dc = DrawCall(layer, position, texture); DrawCall dc = DrawCall(layer, position, texture);
QueueDrawCall(dc);
if (layer >= LAYER_AMOUNT)
{
std::cout << "Layer out of range\n";
return;
}
renderLayers.at(layer).push_back(dc);
//renderQueue.push_back(dc);
} }
void Renderer::Render(Drawable& drawable) void Renderer::Render(Drawable& drawable)
+32 -24
View File
@@ -13,7 +13,7 @@
// TODO: // TODO:
// - Optimizar RenderDraw moviendo la ordenación por capas a Queue, quitando renderQueue. // - Optimizar RenderDraw moviendo la ordenación por capas a Queue, quitando renderQueue.
// - Limpiar las funciones moviendo código a otras funciones. // - Limpiar las funciones moviendo código a otras funciones.
// // - ¿Podría moverse todo a static? De esta forma, ya no harían falta instancias.
// //
@@ -31,8 +31,10 @@ namespace UE
int windowHeight, int windowHeight,
int renderingLayers = 10) int renderingLayers = 10)
: SCREEN_WIDTH(windowWidth), SCREEN_HEIGHT(windowHeight), LAYER_AMOUNT(renderingLayers) : LAYER_AMOUNT(renderingLayers)
{ {
screenSize.x = windowWidth;
screenSize.y = windowHeight;
//UE_LOG_INFO("Game Renderer Created."); //UE_LOG_INFO("Game Renderer Created.");
} }
@@ -49,9 +51,18 @@ namespace UE
void CleanRenderer(); void CleanRenderer();
//Realizar RenderClear(), RenderDraw() y RenderUpdate();
//Es decir, todo lo necesario para renderizar un frame.
void RenderFrame(); //Hace el SDL_RenderClear() para limpiar el buffer al principio de un nuevo frame.
void NewFrame();
//Ordena por layer todos los objetos de la renderQueue y los dibuja en orden.
//Se puede mover el proceso de ordenado a otra función, con el objeto de ir vaciando la Queue.
void RenderData();
//Hace el swap del render buffer (tras dibujar todos los objetos). Termina el renderizado.
void EndFrame();
//Añade un DrawCall al renderQueue. //Añade un DrawCall al renderQueue.
@@ -59,35 +70,29 @@ namespace UE
void QueueDrawCall(int layer, SDL_Rect& position, SDL_Texture* texture, SDL_Rect& texture_position); void QueueDrawCall(int layer, SDL_Rect& position, SDL_Texture* texture, SDL_Rect& texture_position);
void QueueDrawCall(int layer, SDL_Rect & position, SDL_Texture* texture); void QueueDrawCall(int layer, SDL_Rect & position, SDL_Texture* texture);
//Le pasamos el este renderer al Drawable para que haga lo que quiera. //Le pasamos este renderer al Drawable para que haga lo que quiera.
//Como si quiere usar el SDL_Renderer, es libre. //Como si quiere usar el SDL_Renderer, es libre.
void Render(Drawable& drawable); void Render(Drawable& drawable);
/* Get SDL Renderer. */ /* Get SDL Renderer. */
SDL_Renderer* GetSDLRenderer() { return main_Renderer; } SDL_Renderer* GetSDLRenderer() { return main_Renderer; }
inline glm::ivec2 GetScreenSize() { return glm::ivec2(SCREEN_WIDTH, SCREEN_HEIGHT); } inline glm::ivec2 GetScreenSize() { return screenSize; }
void SetScreenSize(Sint32 newWidth, Sint32 newHeight); void SetScreenSize(int newWidth, int newHeight);
inline glm::ivec2 GetCamPosition() { return camPosition; }
void SetCamPosition(int posX, int posY);
//DEBUG //DEBUG
//Función para renderizar un objeto un objeto en concreto. //Función para renderizar un objeto un objeto en concreto directamente en el SDL_Renderer.
void DrawObject(SDL_Rect* position, SDL_Rect* texture_pos, SDL_Texture* texture); void DrawObject(SDL_Rect* position, SDL_Rect* texture_pos, SDL_Texture* texture);
private: private:
//Hace el SDL_RenderClear() para limpiar el buffer al principio de un nuevo frame. //Realizar RenderClear(), RenderDraw() y RenderUpdate();
void StartRender(); //Es decir, todo lo necesario para renderizar un frame.
void RenderFrame();
//Ordena por layer todos los objetos de la renderQueue y los dibuja en orden.
//Se puede mover el proceso de ordenado a otra función, con el objeto de ir vaciando la Queue.
void RenderQueue();
void RenderIMGUI();
//Hace el swap del render buffer (tras dibujar todos los objetos). Termina el renderizado.
void FinishRender();
private: private:
@@ -108,8 +113,11 @@ namespace UE
std::vector<std::vector<DrawCall>> renderLayers; std::vector<std::vector<DrawCall>> renderLayers;
int SCREEN_WIDTH = 640; //int screenWidth = 640;
int SCREEN_HEIGHT = 480; //int screenHeight = 480;
glm::ivec2 screenSize{ 640,480 };
glm::ivec2 camPosition{ 0,0 };
}; };
@@ -124,7 +132,7 @@ namespace UE
SDL_Texture* texture, SDL_Texture* texture,
SDL_Rect texture_position = SDL_Rect()) SDL_Rect texture_position = SDL_Rect())
: layer(layer), tx(texture), tx_rect(texture_position), pos_rect(position) : layer(layer), tx(texture), tx_rect(texture_position), pos_rect(position)
{} {}
int layer; int layer;
+2 -1
View File
@@ -5,7 +5,7 @@
/// ///
/// TODO: /// TODO:
/// - Scene debería ser serializable y cargable desde archivos, al menos para las clases derivadas. /// - Scene debería ser serializable y cargable desde archivos, al menos para las clases derivadas. ( o quizás no....)
/// ///
/// ///
@@ -33,6 +33,7 @@ namespace UE
/* Funciones que habrán de sobrecargar las escenas del usuario. */ /* Funciones que habrán de sobrecargar las escenas del usuario. */
virtual void SceneLoad() { std::cout << "EMPTY SCENE CREATED" << std::endl; } virtual void SceneLoad() { std::cout << "EMPTY SCENE CREATED" << std::endl; }
virtual void SceneRender() { std::cout << "EMPTY SCENE IS BEING RENDERED" << std::endl; }
virtual void SceneUpdate() {} virtual void SceneUpdate() {}
virtual void SceneUnload() { std::cout << "EMPTY SCENE DESCARGADA" << std::endl; } virtual void SceneUnload() { std::cout << "EMPTY SCENE DESCARGADA" << std::endl; }
+40 -5
View File
@@ -96,8 +96,9 @@ void Loop()
{ {
_quit = true; _quit = true;
} }
if (eventHandler.type == SDL_WINDOWEVENT_RESIZED) if (eventHandler.type == SDL_WINDOWEVENT && eventHandler.window.event == SDL_WINDOWEVENT_RESIZED)
{ {
//GAME_LOG_CRITICAL("Window Size chaged {0}x{1}", eventHandler.window.data1, eventHandler.window.data2);
Game::GetRenderer()->SetScreenSize(eventHandler.window.data1, eventHandler.window.data2); Game::GetRenderer()->SetScreenSize(eventHandler.window.data1, eventHandler.window.data2);
} }
if (eventHandler.type == SDL_KEYDOWN) if (eventHandler.type == SDL_KEYDOWN)
@@ -125,12 +126,33 @@ void Loop()
{ {
GAME_LOG_TRACE("FPS: {0} / dT: {1}", 60, UE::Time::deltaTime); GAME_LOG_TRACE("FPS: {0} / dT: {1}", 60, UE::Time::deltaTime);
} }
if (keyStates[SDL_SCANCODE_1])
if (keyStates[SDL_SCANCODE_W])
{ {
glm::ivec2 camPos = Game::GetRenderer()->GetCamPosition();
camPos.y -= 5;
Game::GetRenderer()->SetCamPosition(camPos.x, camPos.y);
} }
if (keyStates[SDL_SCANCODE_2]) if (keyStates[SDL_SCANCODE_S])
{ {
glm::ivec2 camPos = Game::GetRenderer()->GetCamPosition();
camPos.y += 5;
Game::GetRenderer()->SetCamPosition(camPos.x, camPos.y);
} }
if (keyStates[SDL_SCANCODE_D])
{
glm::ivec2 camPos = Game::GetRenderer()->GetCamPosition();
camPos.x += 5;
Game::GetRenderer()->SetCamPosition(camPos.x, camPos.y);
}
if (keyStates[SDL_SCANCODE_A])
{
glm::ivec2 camPos = Game::GetRenderer()->GetCamPosition();
camPos.x -= 5;
Game::GetRenderer()->SetCamPosition(camPos.x, camPos.y);
}
Game::GetSceneManager()->GetActiveScenePtr()->SceneUpdate();
//Game::GetRenderer()->QueueDrawCall(4, DestR2, test1); //Game::GetRenderer()->QueueDrawCall(4, DestR2, test1);
//Game::GetRenderer()->QueueDrawCall(1, DestR, background); //Game::GetRenderer()->QueueDrawCall(1, DestR, background);
@@ -139,9 +161,22 @@ void Loop()
//sp2.Draw(renderer); //sp2.Draw(renderer);
//sp3.Draw(Game::GetRenderer()); //sp3.Draw(Game::GetRenderer());
// //
Game::GetSceneManager()->GetActiveScenePtr()->SceneUpdate();
Game::GetRenderer()->RenderFrame(); //Iniciamos un nuevo Frame.
Game::GetRenderer()->NewFrame();
//Renderiza la escena.
Game::GetSceneManager()->GetActiveScenePtr()->SceneRender();
//Así podemos renderizar cosas de ImGui cuando estemos entre NewFrame y EndFrame.
bool show = true;
ImGui::ShowDemoWindow(&show);
//Dibuja las cosas del Renderer.
Game::GetRenderer()->RenderData();
//Terminamos el Frame.
Game::GetRenderer()->EndFrame();
UE::Time::EndFrame(); UE::Time::EndFrame();
+8 -4
View File
@@ -42,7 +42,7 @@ public:
void SceneUpdate() override void SceneUpdate() override
{ {
UE_LOG_INFO("Escena {0} UPDATE", _sceneName); //UE_LOG_INFO("Escena {0} UPDATE", _sceneName);
UE::Renderer* renderer; UE::Renderer* renderer;
renderer = Game::GetRenderer(); renderer = Game::GetRenderer();
@@ -51,18 +51,22 @@ public:
UE::Sprite& sp1 = sprites.at(0); UE::Sprite& sp1 = sprites.at(0);
glm::vec2 pos = sp1.GetPosition(); glm::vec2 pos = sp1.GetPosition();
if (pos.x > screenSize.x) { pos.x -= 1000; } if (pos.x > screenSize.x) { pos.x = 0; }
else { pos.x += 200 * UE::Time::deltaTime; } else { pos.x += 200 * UE::Time::deltaTime; }
sp1.SetPosition(pos); sp1.SetPosition(pos);
}
void SceneRender() override
{
UE::Renderer* renderer;
renderer = Game::GetRenderer();
for (UE::Sprite sp : sprites) for (UE::Sprite sp : sprites)
{ {
renderer->Render(sp); renderer->Render(sp);
} }
} }
void SceneUnload() override void SceneUnload() override