From 1c06c06816b952710eff48c222fea19d30676121 Mon Sep 17 00:00:00 2001 From: Tleety Date: Thu, 3 Dec 2015 18:14:52 +0100 Subject: [PATCH] Added a ScreenCoords class with some util functions to clean up the Renderer class. --- include/Engine/Rendering/IRenderer.h | 1 + include/Engine/Rendering/Renderer.h | 8 +-- include/Engine/Rendering/Util/ScreenCoords.h | 29 +++++++++++ src/Engine/Rendering/Renderer.cpp | 51 ++------------------ src/Engine/Rendering/Util/ScreenCoords.cpp | 50 +++++++++++++++++++ 5 files changed, 85 insertions(+), 54 deletions(-) create mode 100644 include/Engine/Rendering/Util/ScreenCoords.h create mode 100644 src/Engine/Rendering/Util/ScreenCoords.cpp diff --git a/include/Engine/Rendering/IRenderer.h b/include/Engine/Rendering/IRenderer.h index 1b6d945c..1acb2454 100644 --- a/include/Engine/Rendering/IRenderer.h +++ b/include/Engine/Rendering/IRenderer.h @@ -5,6 +5,7 @@ #include "../OpenGL.h" #include "../GLM.h" #include "../Core/Util/Rectangle.h" +#include "Util/ScreenCoords.h" #include "Camera.h" #include "RenderQueue.h" #include "Model.h" diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index 6fb0b10f..24dcb74b 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -44,19 +44,15 @@ private: void InitializeShaders(); void InitializeTextures(); void InitializeFrameBuffers(); - //TODO: Render: Remove ModelsToDraw from Renderer. + //TODO: Renderer: Remove ModelsToDraw from Renderer. void ModelsToDraw(); + //TODO: Renderer: Get EnqueueModel and InputUpdate out of renderer void EnqueueModel(Model* model); void InputUpdate(double dt); void PickingPass(); void DrawScreenQuad(GLuint textureToDraw); - glm::vec3 GetClickedPixelData(float x, float y); void DrawScene(RenderQueueCollection& rq); - //--------------------Utility functions----------------// - glm::vec3 ScreenCoordsToWorldPos(glm::vec2 screenCoord, float depth); - //EntityID ScreenCoordsToEntityID(glm::vec2 screenCoord, float depth); - //--------------------ShaderPrograms-------------------// ShaderProgram m_BasicForwardProgram; ShaderProgram m_PickingProgram; diff --git a/include/Engine/Rendering/Util/ScreenCoords.h b/include/Engine/Rendering/Util/ScreenCoords.h new file mode 100644 index 00000000..51ad1051 --- /dev/null +++ b/include/Engine/Rendering/Util/ScreenCoords.h @@ -0,0 +1,29 @@ +#ifndef ScreenCoords_h__ +#define ScreenCoords_h__ + +#include "../../Common.h" +#include "../../OpenGL.h" +#include "../../GLM.h" +#include "../../Core/Util/Rectangle.h" + +class ScreenCoords +{ +public: + ScreenCoords() = delete; + //Return world position from given screenspace coordinates and depth value in viewspace. + static glm::vec3 ToWorldPos(glm::vec2 screenCoord, float depth, Rectangle resolution, glm::mat4 cameraProjectionMat, glm::mat4 cameraViewMat); + static glm::vec3 ToWorldPos(float x, float y, float depth, Rectangle resolution, glm::mat4 cameraProjectionMat, glm::mat4 cameraViewMat); + static glm::vec3 ToWorldPos(glm::vec2 screenCoord, float depth, float screenWidth, float screenHeight, glm::mat4 cameraProjectionMat, glm::mat4 cameraViewMat); + static glm::vec3 ToWorldPos(float x, float y, float depth, float screenWidth, float screenHeight, glm::mat4 cameraProjectionMat, glm::mat4 cameraViewMat); + //Return data from the given buffers at the coordinates given in screenspace. Buffer should probably have a texture that covers the screen. + //Data is given as R = x, B = y, and + static glm::vec3 ToPixelData(glm::vec2 screenCoord, GLuint PickDataBuffer, GLuint DepthBuffer); + static glm::vec3 ToPixelData(float x, float y, GLuint PickDataBuffer, GLuint DepthBuffer); + //Return EntityID of the clicked coordinate in given screenspace coordinates. + //EntityID ScreenCoordsToEntityID(glm::vec2 screenCoord, float depth); + +private: + +}; + +#endif \ No newline at end of file diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index bbaab41e..5a9fcba3 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -161,16 +161,15 @@ void Renderer::InputUpdate(double dt) static double mousePosX, mousePosY; glfwGetCursorPos(m_Window, &mousePosX, &mousePosY); if (glfwGetMouseButton(m_Window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS) { - glm::vec3 data = GetClickedPixelData(mousePosX, m_Resolution.Height - mousePosY); + glm::vec3 data = ScreenCoords::ToPixelData(mousePosX, m_Resolution.Height - mousePosY, m_PickingBuffer, m_DepthBuffer); glm::vec2 color = glm::vec2(data); float depth = data.z; - glm::vec3 viewPos = ScreenCoordsToWorldPos(glm::vec2(mousePosX, m_Resolution.Height - mousePosY), depth); + glm::vec3 viewPos = ScreenCoords::ToWorldPos(mousePosX, m_Resolution.Height - mousePosY, depth, m_Resolution, m_Camera->ProjectionMatrix(), m_Camera->ViewMatrix()); // glm::vec3 worldPos = glm::vec3(glm::inverse(m_Camera->ViewMatrix()) * glm::vec4(viewPos, 1.f)); //printf("R: %f, G: %f, Depth: %f\n", color.r, color.g, depth); - printf("view: x: %f, y: %f z: %f, Length: %f\n", viewPos.x, viewPos.y, viewPos.z, glm::length(viewPos)); - + //printf("view: x: %f, y: %f z: %f, Length: %f\n\n", viewPos.x, viewPos.y, viewPos.z, glm::length(viewPos)); if (color != glm::vec2(0, 0)) { const Model* pickModel = m_PickingColorsToModels[color]; @@ -200,33 +199,6 @@ void Renderer::InputUpdate(double dt) m_Camera->SetPosition(m_Position); } - -// Utility functions should be moved to a better place -glm::vec3 Renderer::ScreenCoordsToWorldPos(glm::vec2 screenCoord, float depth) -{ - glm::vec4 pos; - float near = m_Camera->NearClip(); - float far = m_Camera->FarClip(); - - glm::vec3 ndc; - ndc.x = screenCoord.x / m_Resolution.Width; - ndc.y = screenCoord.y / m_Resolution.Height; - glm::vec4 clipSpace = glm::vec4(glm::vec2(ndc.x, ndc.y) * 2.0f - 1.0f, (depth) * 2.0f - 1.0f, 1.0f); - - glm::vec4 EyeSpace = glm::inverse(m_Camera->ProjectionMatrix()) * clipSpace; - glm::vec4 WorldSpace = glm::inverse(m_Camera->ViewMatrix()) * EyeSpace; - WorldSpace = glm::vec4(glm::vec3(WorldSpace) / WorldSpace.w, 1.f); - - return glm::vec3(WorldSpace); - -} - - -//EntityID Renderer::ScreenCoordsToEntityID(glm::vec2 screenCoord, float depth) -//{ -// -//} - void Renderer::Update(double dt) { InputUpdate(dt); @@ -352,23 +324,6 @@ void Renderer::DrawScreenQuad(GLuint textureToDraw) } - -// Will return a vec3 where RG is the PickColor and B is the Depth -glm::vec3 Renderer::GetClickedPixelData(float x, float y) -{ - glBindFramebuffer(GL_FRAMEBUFFER, m_PickingBuffer); - glm::vec2 pixelData; - glReadPixels(x, y, 1, 1, GL_RG, GL_FLOAT, &pixelData); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - glBindFramebuffer(GL_FRAMEBUFFER, m_DepthBuffer); - float depthData; - glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depthData); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - return glm::vec3(pixelData, depthData); -} - void Renderer::InitializeTextures() { m_ErrorTexture=ResourceManager::Load("Textures/Core/ErrorTexture.png"); diff --git a/src/Engine/Rendering/Util/ScreenCoords.cpp b/src/Engine/Rendering/Util/ScreenCoords.cpp new file mode 100644 index 00000000..103e576c --- /dev/null +++ b/src/Engine/Rendering/Util/ScreenCoords.cpp @@ -0,0 +1,50 @@ +#include "Rendering/Util/ScreenCoords.h" + +glm::vec3 ScreenCoords::ToWorldPos(float x, float y, float depth, float screenWidth, float screenHeight, glm::mat4 cameraProjectionMat, glm::mat4 cameraViewMat) +{ + glm::vec3 ndc; + ndc.x = (x / screenWidth)*2.f - 1.f; + ndc.y = (y / screenHeight)*2.f - 1.f; + ndc.z = depth*2.f - 1.f; + glm::vec4 clipSpace = glm::vec4(ndc, 1.0f); + glm::vec4 EyeSpace = glm::inverse(cameraProjectionMat) * clipSpace; + glm::vec4 WorldSpace = glm::inverse(cameraViewMat) * EyeSpace; + WorldSpace = glm::vec4(glm::vec3(WorldSpace) / WorldSpace.w, 1.f); + + return glm::vec3(WorldSpace); +} + +glm::vec3 ScreenCoords::ToWorldPos(glm::vec2 screenCoord, float depth, Rectangle resolution, glm::mat4 cameraProjectionMat, glm::mat4 cameraViewMat) +{ + return ToWorldPos(screenCoord.x, screenCoord.y, depth, resolution.Width, resolution.Height, cameraProjectionMat, cameraViewMat); +} + +glm::vec3 ScreenCoords::ToWorldPos(float x, float y, float depth, Rectangle resolution, glm::mat4 cameraProjectionMat, glm::mat4 cameraViewMat) +{ + return ToWorldPos(x, y, depth, resolution.Width, resolution.Height, cameraProjectionMat, cameraViewMat); +} + +glm::vec3 ScreenCoords::ToWorldPos(glm::vec2 screenCoord, float depth, float screenWidth, float screenHeight, glm::mat4 cameraProjectionMat, glm::mat4 cameraViewMat) +{ + return ToWorldPos(screenCoord.x, screenCoord.y, depth, screenWidth, screenHeight, cameraProjectionMat, cameraViewMat); +} + +glm::vec3 ScreenCoords::ToPixelData(float x, float y, GLuint PickDataBuffer, GLuint DepthBuffer) +{ + glBindFramebuffer(GL_FRAMEBUFFER, PickDataBuffer); + glm::vec2 pixelData; + glReadPixels(x, y, 1, 1, GL_RG, GL_FLOAT, &pixelData); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glBindFramebuffer(GL_FRAMEBUFFER, DepthBuffer); + float depthData; + glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depthData); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + return glm::vec3(pixelData, depthData); +} + +glm::vec3 ScreenCoords::ToPixelData(glm::vec2 screenCoord, GLuint PickDataBuffer, GLuint DepthBuffer) +{ + return ToPixelData(screenCoord.x, screenCoord.y, PickDataBuffer, DepthBuffer); +}