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.
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.
_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)
{
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()
{
StartRender();
RenderQueue();
RenderIMGUI();
FinishRender();
NewFrame();
RenderData();
EndFrame();
}
void Renderer::StartRender()
void Renderer::NewFrame()
{
SDL_RenderClear(main_Renderer);
@@ -100,9 +99,11 @@ namespace UE
ImGui_ImplSDL2_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.
for (int i = 0; i < renderQueue.size(); i++)
@@ -112,7 +113,7 @@ namespace UE
//Add item i to layer number i.layer.
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;
}
renderLayers.at(item.layer).push_back(item);
@@ -135,15 +136,8 @@ namespace UE
}
void Renderer::RenderIMGUI()
{
bool show = true;
ImGui::ShowDemoWindow(&show);
}
void Renderer::FinishRender()
void Renderer::EndFrame()
{
//SDL_UpdateWindowSurface(window);
//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;
SCREEN_HEIGHT = newHeight;
screenSize.x = newWidth;
screenSize.y = newHeight;
SDL_SetWindowSize(_window, 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)
{
SDL_RenderCopy(main_Renderer, texture, texture_pos, position);
@@ -181,9 +185,19 @@ namespace UE
//Add item i to layer number i.layer.
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;
}
//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);
//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)
{
DrawCall dc = DrawCall(layer, position, texture, texture_position);
//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);
QueueDrawCall(dc);
}
void Renderer::QueueDrawCall(int layer, SDL_Rect & position, SDL_Texture* texture)
{
//std::cout << "Drawable added to queue";
DrawCall dc = DrawCall(layer, position, texture);
if (layer >= LAYER_AMOUNT)
{
std::cout << "Layer out of range\n";
return;
}
renderLayers.at(layer).push_back(dc);
//renderQueue.push_back(dc);
QueueDrawCall(dc);
}
void Renderer::Render(Drawable& drawable)
+32 -24
View File
@@ -13,7 +13,7 @@
// TODO:
// - Optimizar RenderDraw moviendo la ordenación por capas a Queue, quitando renderQueue.
// - 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 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.");
}
@@ -49,9 +51,18 @@ namespace UE
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.
@@ -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);
//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.
void Render(Drawable& drawable);
/* Get SDL Renderer. */
SDL_Renderer* GetSDLRenderer() { return main_Renderer; }
inline glm::ivec2 GetScreenSize() { return glm::ivec2(SCREEN_WIDTH, SCREEN_HEIGHT); }
void SetScreenSize(Sint32 newWidth, Sint32 newHeight);
inline glm::ivec2 GetScreenSize() { return screenSize; }
void SetScreenSize(int newWidth, int newHeight);
inline glm::ivec2 GetCamPosition() { return camPosition; }
void SetCamPosition(int posX, int posY);
//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);
private:
//Hace el SDL_RenderClear() para limpiar el buffer al principio de un nuevo frame.
void StartRender();
//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();
//Realizar RenderClear(), RenderDraw() y RenderUpdate();
//Es decir, todo lo necesario para renderizar un frame.
void RenderFrame();
private:
@@ -108,8 +113,11 @@ namespace UE
std::vector<std::vector<DrawCall>> renderLayers;
int SCREEN_WIDTH = 640;
int SCREEN_HEIGHT = 480;
//int screenWidth = 640;
//int screenHeight = 480;
glm::ivec2 screenSize{ 640,480 };
glm::ivec2 camPosition{ 0,0 };
};
@@ -124,7 +132,7 @@ namespace UE
SDL_Texture* texture,
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;
+2 -1
View File
@@ -5,7 +5,7 @@
///
/// 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. */
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 SceneUnload() { std::cout << "EMPTY SCENE DESCARGADA" << std::endl; }
+40 -5
View File
@@ -96,8 +96,9 @@ void Loop()
{
_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);
}
if (eventHandler.type == SDL_KEYDOWN)
@@ -125,12 +126,33 @@ void Loop()
{
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(1, DestR, background);
@@ -139,9 +161,22 @@ void Loop()
//sp2.Draw(renderer);
//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();
+8 -4
View File
@@ -42,7 +42,7 @@ public:
void SceneUpdate() override
{
UE_LOG_INFO("Escena {0} UPDATE", _sceneName);
//UE_LOG_INFO("Escena {0} UPDATE", _sceneName);
UE::Renderer* renderer;
renderer = Game::GetRenderer();
@@ -51,18 +51,22 @@ public:
UE::Sprite& sp1 = sprites.at(0);
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; }
sp1.SetPosition(pos);
}
void SceneRender() override
{
UE::Renderer* renderer;
renderer = Game::GetRenderer();
for (UE::Sprite sp : sprites)
{
renderer->Render(sp);
}
}
void SceneUnload() override