Rendering of perspective linearized depth map kind of works now

simple_math_single_header
Martin Felis 2018-03-11 22:05:42 +01:00
parent fb3e1e7432
commit 0810224356
7 changed files with 338 additions and 189 deletions

View File

@ -4,13 +4,19 @@ in vec2 ioUV;
out vec3 outColor; out vec3 outColor;
uniform sampler2D uTexture; uniform sampler2D uDepthTexture;
uniform float uIsOrthographic;
uniform float uNear; uniform float uNear;
uniform float uFar; uniform float uFar;
void main() { void main() {
float z = texture(uTexture, ioUV).r; float z = texture(uDepthTexture, ioUV).r;
float c = (z - uNear) / (uFar - uNear); float c;
if (uIsOrthographic == 1.0) {
c = (z - uNear) / (uFar - uNear);
} else {
c = (2.0 * uNear) / (uFar + uNear - z * (uFar - uNear));
}
outColor = vec3(c); outColor = vec3(c);
} }

View File

@ -0,0 +1,32 @@
#version 150 core
uniform vec4 uColor;
uniform vec3 uLightDirection;
uniform vec3 uViewPosition;
smooth in vec4 ioFragColor;
in vec3 ioNormal;
in vec3 ioFragPosition;
out vec4 outColor;
void main() {
// ambient lighting
float ambient_strength = 0.1;
vec4 ambient = ambient_strength * ioFragColor;
// diffuse lighting
vec3 normal_dir = normalize(ioNormal);
vec3 light_dir = normalize(uLightDirection);
float diff = max(dot(normal_dir, light_dir), 0.0);
vec4 diffuse = diff * ioFragColor;
// specular lighting
vec3 view_dir = normalize(uViewPosition - ioFragPosition);
vec3 halfway_dir = normalize(light_dir + view_dir);
float spec = pow(max(dot(normal_dir, halfway_dir), 0.0), 32);
vec4 specular = spec * vec4(0.5);
outColor = ambient + diffuse + specular;
}

View File

@ -0,0 +1,25 @@
#version 150 core
#extension GL_ARB_explicit_attrib_location : require
in vec4 inCoord;
in vec3 inNormal;
in vec2 inUV;
in vec4 inColor;
uniform mat4 uModelMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uProjectionMatrix;
uniform mat3 uNormalMatrix;
uniform vec3 uLightDirection;
uniform vec3 uViewPosition;
smooth out vec4 ioFragColor;
out vec3 ioNormal;
out vec3 ioFragPosition;
void main() {
gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * inCoord;
ioFragColor = inColor;
ioNormal = uNormalMatrix * inNormal;
ioFragPosition = (uModelMatrix * inCoord).xyz;
}

View File

@ -154,36 +154,30 @@ const struct module_api MODULE_API = {
// void Light::Initialize() {
// Camera gLog("Initializing light");
// mShadowMapProgram = RenderProgram("data/shaders/vs_shadowmap.vert", "data/shaders/fs_shadowmap.frag");
void Camera::UpdateMatrices() {
mViewMatrix = LookAt(mEye, mPoi, mUp);
if (mIsOrthographic) { bool load_result = mShadowMapProgram.Load();
mProjectionMatrix = Ortho(-1.0f, 1.0f, -1.0f, 1.0f, mNear, mFar); mShadowMapProgram.RegisterFileModification();
} else { assert(load_result);
mProjectionMatrix = Perspective(mFov, mWidth / mHeight, mNear, mFar);
} gLog("Initializing light render target size: %d, %d", mShadowMapSize, mShadowMapSize);
mShadowMapTarget.Initialize(mShadowMapSize, mShadowMapSize,
RenderTarget::EnableColor
| RenderTarget::EnableDepthTexture
| RenderTarget::EnableLinearizedDepthTexture);
glBindFramebuffer(GL_FRAMEBUFFER, mShadowMapTarget.mFrameBufferId);
gLog("Framebuffer of light has id: %d", mShadowMapTarget.mFrameBufferId);
gLog("Initializing light done");
} }
void Camera::DrawGui() { void Light::UpdateMatrices() {
ImGui::Text("Width %3.4f, Height %3.4f", mWidth, mHeight); mLightProjection = Ortho (-mBBoxSize * 0.5f, mBBoxSize * 0.5f, -mBBoxSize * 0.5f, mBBoxSize * 0.5f, mNear, mFar);
mLightView = LookAt(mDirection * mBBoxSize * 0.5f, Vector3f (0.0f, 0.0f, 0.0f), Vector3f (0.0f, 1.0f, 0.0f));
ImGui::InputFloat3("Eye", mEye.data(), -10.0f, 10.0f); mLightSpaceMatrix = mLightProjection * mLightView;
ImGui::SliderFloat3("EyeS", mEye.data(), -10.0f, 10.0f);
ImGui::InputFloat3("Poi", mPoi.data(), -10.0f, 10.0f);
ImGui::InputFloat3("Up", mUp.data(), -10.0f, 10.0f);
ImGui::Checkbox("Orthographic", &mIsOrthographic);
ImGui::SliderFloat("Fov", &mFov, 5, 160);
ImGui::SliderFloat("Near", &mNear, -10, 10);
ImGui::SliderFloat("Far", &mFar, -20, 50);
if (ImGui::Button("Reset")) {
*this = Camera();
} }
}
// //
// Renderer // Renderer
@ -300,20 +294,6 @@ void Renderer::Initialize(int width, int height) {
mDefaultProgram.RegisterFileModification(); mDefaultProgram.RegisterFileModification();
assert(load_result); assert(load_result);
// Render Target
mRenderTarget = RenderTarget (width, height,
RenderTarget::EnableColor
| RenderTarget::EnableDepthTexture
| RenderTarget::EnableLinearizedDepthTexture);
// Render Target Quad
glGenVertexArrays(1, &mRenderQuadVertexArrayId);
glBindVertexArray(mRenderQuadVertexArrayId);
glGenBuffers(1, &mRenderQuadVertexBufferId);
glBindBuffer(GL_ARRAY_BUFFER, mRenderQuadVertexBufferId);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW);
// Program for color texture rendering // Program for color texture rendering
mRenderQuadProgramColor = RenderProgram("data/shaders/vs_passthrough.glsl", "data/shaders/fs_simpletexture.glsl"); mRenderQuadProgramColor = RenderProgram("data/shaders/vs_passthrough.glsl", "data/shaders/fs_simpletexture.glsl");
load_result = mRenderQuadProgramColor.Load(); load_result = mRenderQuadProgramColor.Load();
@ -333,6 +313,27 @@ void Renderer::Initialize(int width, int height) {
muRenderQuadDepthNear = mRenderQuadProgramDepth.GetUniformLocation("uNear"); muRenderQuadDepthNear = mRenderQuadProgramDepth.GetUniformLocation("uNear");
muRenderQuadDepthFar = mRenderQuadProgramDepth.GetUniformLocation("uFar"); muRenderQuadDepthFar = mRenderQuadProgramDepth.GetUniformLocation("uFar");
// Render Target
gLog("Initializing main render target size: %d,%d", width, height);
mRenderTarget.Initialize(width, height,
RenderTarget::EnableColor
| RenderTarget::EnableDepthTexture
| RenderTarget::EnableLinearizedDepthTexture);
// Render Target Quad
glGenVertexArrays(1, &mRenderQuadVertexArrayId);
glBindVertexArray(mRenderQuadVertexArrayId);
glGenBuffers(1, &mRenderQuadVertexBufferId);
glBindBuffer(GL_ARRAY_BUFFER, mRenderQuadVertexBufferId);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW);
mRenderTarget.mQuadVertexArray = mRenderQuadVertexArrayId;
mRenderTarget.mQuadVertexBuffer = mRenderQuadVertexBufferId;
mRenderTarget.mLinearizeDepthProgram = mRenderQuadProgramDepth;
// Light
mLight.Initialize();
} }
void Renderer::Shutdown() { void Renderer::Shutdown() {
@ -348,14 +349,25 @@ void Renderer::RenderGl() {
mCamera.mHeight = mSceneAreaHeight; mCamera.mHeight = mSceneAreaHeight;
} }
glViewport(0, 0, mCamera.mWidth, mCamera.mHeight); // Shadow Map
mCamera.UpdateMatrices(); glViewport(0, 0, mLight.mShadowMapSize, mLight.mShadowMapSize);
mLight.mShadowMapTarget.Bind();
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glUseProgram(mLight.mShadowMapProgram.mProgramId);
RenderScene(mLight.mShadowMapProgram);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// TODO: render linearized depth for the light
// mLight.mShadowMapTarget.RenderToLinearizedDepth(mCamera);
// Regular rendering
glEnable(GL_LINE_SMOOTH); glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glEnable(GL_MULTISAMPLE); glEnable(GL_MULTISAMPLE);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glViewport(0, 0, mCamera.mWidth, mCamera.mHeight);
mCamera.UpdateMatrices();
Matrix44f model_matrix = TranslateMat44(0.0f, 0.0f, 0.0f); Matrix44f model_matrix = TranslateMat44(0.0f, 0.0f, 0.0f);
Matrix44f model_view_projection = Matrix44f model_view_projection =
model_matrix model_matrix
@ -373,7 +385,7 @@ void Renderer::RenderGl() {
// clear color and depth // clear color and depth
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glUseProgram(mSimpleProgram.mProgramId); glUseProgram(mSimpleProgram.mProgramId);
mSimpleProgram.SetMat44("uModelViewProj", model_view_projection); mSimpleProgram.SetMat44("uModelViewProj", model_view_projection);
@ -399,65 +411,38 @@ void Renderer::RenderGl() {
gVertexArray.Bind(); gVertexArray.Bind();
gXZPlaneMesh.Draw(GL_LINES); gXZPlaneMesh.Draw(GL_LINES);
// Unit cube // Scene
glUseProgram(mDefaultProgram.mProgramId); glUseProgram(mDefaultProgram.mProgramId);
gVertexArray.Bind(); glBindTexture(GL_TEXTURE_2D, mLight.mShadowMapTarget.mDepthTexture);
glEnable(GL_DEPTH_TEST);
model_matrix = TranslateMat44(3.0f, 0.0f, 1.0f); RenderScene(mDefaultProgram);
Matrix33f normal_matrix = model_matrix.block<3,3>(0,0).transpose();
normal_matrix = normal_matrix.inverse();
mDefaultProgram.SetMat44("uModelMatrix", model_matrix);
mDefaultProgram.SetMat44("uViewMatrix", mCamera.mViewMatrix);
mDefaultProgram.SetMat44("uProjectionMatrix", mCamera.mProjectionMatrix);
mDefaultProgram.SetMat33("uNormalMatrix", normal_matrix);
mDefaultProgram.SetVec4("uColor", Vector4f (1.0f, 0.0f, 0.0f, 1.0f));
mDefaultProgram.SetVec3("uLightDirection", mLight.mDirection);
mDefaultProgram.SetVec3("uViewPosition", mCamera.mEye);
gVertexArray.Bind();
gUnitCubeMesh.Draw(GL_TRIANGLES);
if (mSettings->DrawDepth) { if (mSettings->DrawDepth) {
mRenderTarget.RenderToLinearizedDepth(true); mRenderTarget.RenderToLinearizedDepth(mCamera);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
Matrix44f model_view_projection = Matrix44f::Identity();
// render depth texture
glUseProgram(mRenderQuadProgramDepth.mProgramId);
glUniformMatrix4fv(muRenderQuadModelViewProj, 1, GL_FALSE, model_view_projection.data());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mRenderTarget.mDepthTexture);
glUniform1i(muRenderQuadTexture, 0);
// TODO: adjust for perspective
glUniform1f(muRenderQuadDepthNear, mCamera.mNear);
// TODO: why do I have to divide by depth range?
glUniform1f(muRenderQuadDepthFar, mCamera.mFar / (mCamera.mFar - mCamera.mNear));
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, mRenderQuadVertexBufferId);
glVertexAttribPointer(
0, // attribute 0
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // offset
);
glDrawArrays(GL_TRIANGLES, 0, 6); // starting from vertex 0; 3 vertices total
mRenderTarget.RenderToLinearizedDepth(false);
} }
glDisableVertexAttribArray(0); glDisableVertexAttribArray(0);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
} }
void Renderer::RenderScene(RenderProgram &program) {
Matrix44f model_matrix = TranslateMat44(3.0f, 0.0f, 1.0f);
Matrix33f normal_matrix = model_matrix.block<3,3>(0,0).transpose();
normal_matrix = normal_matrix.inverse();
program.SetMat44("uModelMatrix", model_matrix);
program.SetMat44("uViewMatrix", mCamera.mViewMatrix);
program.SetMat44("uProjectionMatrix", mCamera.mProjectionMatrix);
program.SetMat33("uNormalMatrix", normal_matrix);
program.SetVec4("uColor", Vector4f (1.0f, 0.0f, 0.0f, 1.0f));
program.SetVec3("uLightDirection", mLight.mDirection);
program.SetVec3("uViewPosition", mCamera.mEye);
gVertexArray.Bind();
gUnitCubeMesh.Draw(GL_TRIANGLES);
}
void Renderer::RenderGui() { void Renderer::RenderGui() {
if (ImGui::BeginDock("Scene")) { if (ImGui::BeginDock("Scene")) {
ImGui::Checkbox("Draw Depth", &mSettings->DrawDepth); ImGui::Checkbox("Draw Depth", &mSettings->DrawDepth);
@ -486,11 +471,17 @@ void Renderer::RenderGui() {
if (ImGui::BeginDock("Render Settings")) { if (ImGui::BeginDock("Render Settings")) {
ImGui::Text("Light"); ImGui::Text("Light");
ImGui::SliderFloat3("Direction", mLight.mDirection.data(), -10.0f, 10.0f); ImGui::SliderFloat3("Direction", mLight.mDirection.data(), -10.0f, 10.0f);
ImVec2 content_avail = ImGui::GetContentRegionAvail();
ImGui::Image((void*) mLight.mShadowMapTarget.mLinearizedDepthTexture,
ImVec2(content_avail.x, content_avail.x),
ImVec2(0.0f, 1.0f),
ImVec2(1.0f, 0.0f)
);
ImGui::Text("Camera"); ImGui::Text("Camera");
mCamera.DrawGui(); mCamera.DrawGui();
ImGui::Text("Default Texture"); ImGui::Text("Default Texture");
const ImVec2 content_avail = ImGui::GetContentRegionAvail(); content_avail = ImGui::GetContentRegionAvail();
ImGui::Image((void*) mDefaultTexture.mTextureId, ImGui::Image((void*) mDefaultTexture.mTextureId,
ImVec2(content_avail.x, content_avail.x), ImVec2(content_avail.x, content_avail.x),
ImVec2(0.0f, 1.0f), ImVec2(0.0f, 1.0f),

View File

@ -14,94 +14,40 @@
#include "Globals.h" #include "Globals.h"
#include "RenderUtils.h" #include "RenderUtils.h"
struct Camera {
Vector3f mEye;
Vector3f mPoi;
Vector3f mUp;
float mNear;
float mFar;
float mFov;
bool mIsOrthographic;
float mWidth;
float mHeight;
Matrix44f mProjectionMatrix;
Matrix44f mViewMatrix;
Camera() :
mEye {5.f, 4.f, 5.f},
mPoi {0.f, 2.f, 0.f},
mUp {0.f, 1.f, 0.f},
mNear (0.1f),
mFar (150.f),
mFov (60.f),
mIsOrthographic (false),
mWidth (-1.f),
mHeight (-1.f),
mProjectionMatrix (
1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f),
mViewMatrix (
1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f)
{}
void UpdateMatrices();
void DrawGui();
};
struct Light { struct Light {
Vector3f mPosition; Vector3f mPosition;
Vector3f mDirection; Vector3f mDirection;
float mViewMatrix[16]; RenderTarget mShadowMapTarget;
float mProjectionMatrix[16]; RenderProgram mShadowMapProgram;
float mtxLight[16];
float mtxShadow[16];
float shadowMapBias; float mShadowMapBias;
uint16_t shadowMapSize; uint16_t mShadowMapSize;
bool enabled; float mNear;
float near; float mFar;
float far; float mBBoxSize;
float area;
Matrix44f mLightProjection;
Matrix44f mLightView;
Matrix44f mLightSpaceMatrix;
Light() : Light() :
mPosition (Vector3f(0.f, 10.f, 10.f)), mPosition (Vector3f(0.f, 10.f, 10.f)),
mDirection (Vector3f(-1.f, -1.f, -1.f)), mDirection (Vector3f(-1.f, -1.f, -1.f)),
mViewMatrix { mShadowMapBias (0.004f),
1.f, 0.f, 0.f, 0.f, mShadowMapSize (1024),
0.f, 1.f, 0.f, 0.f, mNear (0.1f),
0.f, 0.f, 1.f, 0.f, mFar (100.f),
0.f, 0.f, 0.f, 1.f mBBoxSize (10.f),
}, mLightProjection(Matrix44f::Identity()),
mProjectionMatrix { mLightView(Matrix44f::Identity()),
1.f, 0.f, 0.f, 0.f, mLightSpaceMatrix(Matrix44f::Identity())
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f
},
mtxShadow {
1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f
},
shadowMapBias (0.004f),
shadowMapSize (2048),
near (0.1f),
far (100.f),
area (10.f),
enabled (false)
{ {
} }
void Initialize();
void UpdateMatrices();
}; };
struct RendererSettings; struct RendererSettings;
@ -151,5 +97,6 @@ struct Renderer {
void Initialize(int width, int height); void Initialize(int width, int height);
void Shutdown(); void Shutdown();
void RenderGl(); void RenderGl();
void RenderScene(RenderProgram &program);
void RenderGui(); void RenderGui();
}; };

View File

@ -9,11 +9,46 @@
#include "Globals.h" #include "Globals.h"
#include "FileModificationObserver.h" #include "FileModificationObserver.h"
#include "imgui/imgui.h"
#include "imgui_dock.h"
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include "stb/stb_image.h" #include "stb/stb_image.h"
using namespace SimpleMath; using namespace SimpleMath;
using namespace SimpleMath::GL;
//
// Camera
//
void Camera::UpdateMatrices() {
mViewMatrix = LookAt(mEye, mPoi, mUp);
if (mIsOrthographic) {
mProjectionMatrix = Ortho(-1.0f, 1.0f, -1.0f, 1.0f, mNear, mFar);
} else {
mProjectionMatrix = Perspective(mFov, mWidth / mHeight, mNear, mFar);
}
}
void Camera::DrawGui() {
ImGui::Text("Width %3.4f, Height %3.4f", mWidth, mHeight);
ImGui::InputFloat3("Eye", mEye.data(), -10.0f, 10.0f);
ImGui::SliderFloat3("EyeS", mEye.data(), -10.0f, 10.0f);
ImGui::InputFloat3("Poi", mPoi.data(), -10.0f, 10.0f);
ImGui::InputFloat3("Up", mUp.data(), -10.0f, 10.0f);
ImGui::Checkbox("Orthographic", &mIsOrthographic);
ImGui::SliderFloat("Fov", &mFov, 5, 160);
ImGui::SliderFloat("Near", &mNear, -10, 10);
ImGui::SliderFloat("Far", &mFar, -20, 50);
if (ImGui::Button("Reset")) {
*this = Camera();
}
}
// //
// RenderProgram // RenderProgram
@ -230,15 +265,21 @@ bool RenderProgram::OnFileChanged(const std::string& filename) {
// //
// RenderTarget // RenderTarget
// //
RenderTarget::RenderTarget(int width, int height, int flags) { RenderTarget::~RenderTarget() {
Cleanup();
}
void RenderTarget::Initialize(int width, int height, int flags) {
Cleanup();
mFlags = flags; mFlags = flags;
Cleanup();
Resize(width, height); Resize(width, height);
} }
RenderTarget::~RenderTarget() { void RenderTarget::Bind() {
Cleanup(); assert(glIsFramebuffer(mFrameBufferId));
glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferId);
} }
void RenderTarget::Cleanup() { void RenderTarget::Cleanup() {
@ -277,7 +318,7 @@ void RenderTarget::Resize(int width, int height) {
Cleanup(); Cleanup();
gLog("Resizing RenderTarget"); gLog("Resizing RenderTarget to %d,%d", width, height);
mWidth = width; mWidth = width;
mHeight = height; mHeight = height;
@ -294,7 +335,7 @@ void RenderTarget::Resize(int width, int height) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mColorTexture, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mColorTexture, 0);
} }
if (mFlags & EnableDepthTexture) { if (mFlags & EnableDepthTexture) {
@ -310,7 +351,7 @@ void RenderTarget::Resize(int width, int height) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mDepthTexture, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, mDepthTexture, 0);
if (mFlags & EnableLinearizedDepthTexture) { if (mFlags & EnableLinearizedDepthTexture) {
glGenTextures(1, &mLinearizedDepthTexture); glGenTextures(1, &mLinearizedDepthTexture);
@ -329,15 +370,64 @@ void RenderTarget::Resize(int width, int height) {
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, mWidth, mHeight); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, mWidth, mHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthBuffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthBuffer);
} }
GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (result != GL_FRAMEBUFFER_COMPLETE) {
switch (result) {
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: gLog("Error: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
break;
case GL_FRAMEBUFFER_UNDEFINED: gLog("Error: GL_FRAMEBUFFER_UNDEFINED");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: gLog("Error: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
break;
default: gLog("Error when creating Framebuffer: %d", result);
}
} }
void RenderTarget::RenderToLinearizedDepth(bool render_to_depth) { assert(result == GL_FRAMEBUFFER_COMPLETE);
if (render_to_depth) {
assert(mFlags & EnableLinearizedDepthTexture);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mLinearizedDepthTexture, 0);
} else {
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mColorTexture, 0);
} }
void RenderTarget::RenderToLinearizedDepth(const Camera& camera) {
assert(mFlags & EnableLinearizedDepthTexture);
assert(mLinearizedDepthTexture != -1);
assert(mQuadVertexArray != -1);
assert(mQuadVertexBuffer != -1);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mLinearizedDepthTexture, 0);
glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferId);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
Matrix44f model_view_projection = Matrix44f::Identity();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mDepthTexture);
// render depth texture
glUseProgram(mLinearizeDepthProgram.mProgramId);
mLinearizeDepthProgram.SetMat44("uModelViewProj", model_view_projection);
mLinearizeDepthProgram.SetFloat("uNear", camera.mNear);
mLinearizeDepthProgram.SetFloat("uFar", camera.mFar);
mLinearizeDepthProgram.SetFloat("uIsOrthographic", camera.mIsOrthographic ? 1.0f : 0.0f);
mLinearizeDepthProgram.SetInt("uDepthTexture", 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexBuffer);
glVertexAttribPointer(
0, // attribute 0
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // offset
);
glDrawArrays(GL_TRIANGLES, 0, 6); // starting from vertex 0; 3 vertices total
if (mFlags & EnableColor)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mColorTexture, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
} }
// //

View File

@ -129,6 +129,50 @@ struct Transform {
} }
}; };
struct Camera {
Vector3f mEye;
Vector3f mPoi;
Vector3f mUp;
float mNear;
float mFar;
float mFov;
bool mIsOrthographic;
float mWidth;
float mHeight;
Matrix44f mProjectionMatrix;
Matrix44f mViewMatrix;
Camera() :
mEye {5.f, 4.f, 5.f},
mPoi {0.f, 2.f, 0.f},
mUp {0.f, 1.f, 0.f},
mNear (0.1f),
mFar (150.f),
mFov (60.f),
mIsOrthographic (false),
mWidth (-1.f),
mHeight (-1.f),
mProjectionMatrix (
1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f),
mViewMatrix (
1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f)
{}
void UpdateMatrices();
void DrawGui();
};
struct RenderProgram : AFileModificationListener { struct RenderProgram : AFileModificationListener {
std::string mVertexShaderFilename; std::string mVertexShaderFilename;
std::string mFragmentShaderFilename; std::string mFragmentShaderFilename;
@ -153,6 +197,14 @@ struct RenderProgram : AFileModificationListener {
GLuint CompileFragmentShader(); GLuint CompileFragmentShader();
GLuint LinkProgram(GLuint vertex_shader, GLuint fragment_shader); GLuint LinkProgram(GLuint vertex_shader, GLuint fragment_shader);
void SetInt(const char* name, const GLint& val) {
GLint location = glGetUniformLocation(mProgramId, name);
glUniform1i(location, val);
}
void SetFloat(const char* name, const float& val) {
GLint location = glGetUniformLocation(mProgramId, name);
glUniform1f(location, val);
}
void SetVec3(const char* name, const Vector3f& vec) { void SetVec3(const char* name, const Vector3f& vec) {
GLint location = glGetUniformLocation(mProgramId, name); GLint location = glGetUniformLocation(mProgramId, name);
glUniform3fv(location, 1, vec.data()); glUniform3fv(location, 1, vec.data());
@ -179,7 +231,7 @@ struct RenderProgram : AFileModificationListener {
}; };
struct RenderSettings; struct RenderSettings;
struct RenderProgram;
struct RenderTarget { struct RenderTarget {
int mWidth = 0; int mWidth = 0;
@ -199,13 +251,19 @@ struct RenderTarget {
int mFlags = 0; int mFlags = 0;
RenderProgram mLinearizeDepthProgram;
GLuint mQuadVertexArray = -1;
GLuint mQuadVertexBuffer = -1;
RenderTarget() {}; RenderTarget() {};
RenderTarget(int width, int height, int flags);
~RenderTarget(); ~RenderTarget();
void Initialize(int width, int height, int flags);
void Bind();
void Cleanup(); void Cleanup();
void Resize(int width, int height); void Resize(int width, int height);
void RenderToLinearizedDepth(bool render_to_depth);
void RenderToLinearizedDepth(const Camera &camera);
}; };
struct Texture { struct Texture {