Browse Source

gamma correction, scaling renderbuffer

master
alistair 1 year ago
parent
commit
88b6975eea
  1. 13
      CMakeLists.txt
  2. 19
      README.md
  3. 21
      assets/shaders/screen.frag
  4. 162
      source/main.cpp
  5. 6
      source/window.cpp

13
CMakeLists.txt

@ -17,8 +17,8 @@ set(CMAKE_CXX_COMPILER "zig" c++ ${compile-target}) @@ -17,8 +17,8 @@ set(CMAKE_CXX_COMPILER "zig" c++ ${compile-target})
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(OpenGL_GL_PREFERENCE "GLVND")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -g ")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -g")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g ")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
project(
@ -94,9 +94,12 @@ CPMAddPackage("gh:g-truc/glm#0.9.9.8") @@ -94,9 +94,12 @@ CPMAddPackage("gh:g-truc/glm#0.9.9.8")
FetchContent_Declare(SDL2
GIT_REPOSITORY https://github.com/libsdl-org/SDL
GIT_TAG release-2.26.4
OVERRIDE_FIND_PACKAGE
)
FetchContent_MakeAvailable(SDL2)
find_package(SDL2 REQUIRED)
FetchContent_Declare(
glad
GIT_REPOSITORY https://github.com/Dav1dde/glad
@ -111,6 +114,7 @@ if(NOT glad_POPULATED) @@ -111,6 +114,7 @@ if(NOT glad_POPULATED)
add_subdirectory(${glad_SOURCE_DIR} ${glad_BINARY_DIR})
endif()
# https://github.com/cpm-cmake/CPM.cmake/issues/368
add_library(imgui STATIC
${imgui_SOURCE_DIR}/imgui.cpp
@ -124,8 +128,7 @@ add_library(imgui STATIC @@ -124,8 +128,7 @@ add_library(imgui STATIC
)
target_include_directories(imgui PUBLIC ${imgui_SOURCE_DIR})
target_compile_definitions(imgui PUBLIC -DIMGUI_DISABLE_OBSOLETE_FUNCTIONS) # optional imgui setting
set_target_properties(imgui PROPERTIES FOLDER third-party) # optoinal IDE dir
target_link_libraries(imgui PRIVATE SDL2-static)
target_link_libraries(imgui PRIVATE SDL2)
# ---- Declare executable ----
@ -161,7 +164,7 @@ target_link_libraries(enttge_exe PRIVATE enttge_lib @@ -161,7 +164,7 @@ target_link_libraries(enttge_exe PRIVATE enttge_lib
glm::glm
glad
refl-cpp
SDL2-static
SDL2
spdlog
imgui
assimp)

19
README.md

@ -24,10 +24,15 @@ cmake . -B build -Dcompile-target=aarch64-linux-gnu @@ -24,10 +24,15 @@ cmake . -B build -Dcompile-target=aarch64-linux-gnu
---
- https://sketchfab.com/3d-models/maple-tree-4b27adcf92f644bdabf8ecc6c5bef399#download
- https://sketchfab.com/3d-models/trees-low-poly-1d2dcca2ccb1496c85b7cc5789a2a261
- https://sketchfab.com/3d-models/grass-patches-7b65ce8bc0514c75b4243c5251cd5984
- https://sketchfab.com/3d-models/grass-c44c1f99f1f0403fb2a52a441d8af7be#download
- https://sketchfab.com/3d-models/birch-tree-low-poly-3ef00a7105c54d37b3a0e528e1466b0b#download
- https://sketchfab.com/3d-models/fern-515ff7eff08144e3be70a89eedbcbcc7#download
- https://sketchfab.com/3d-models/purple-lilies-a73ee85609bf48ef98eb08b29590e40f#download
```
- "Xenia The Linux Mascot" (https://skfb.ly/oGJ8U) by nickisdoge is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
- "Dry grass" (https://skfb.ly/oCWJT) by Pixel-bit is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
- "Grass" (https://skfb.ly/oGoz6) by Luis Gustavo is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
- "Dead Trees Demo" (https://skfb.ly/ouL8q) by Quadra3D is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
- "Purple lilies" (https://skfb.ly/oFxXE) by MyVisoin is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
- "Low Poly: Dead Tree" (https://skfb.ly/orGPV) by ClintonAbbott.Art is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
- "Grass" (https://skfb.ly/oFZNX) by Luis Gustavo is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
- "Trees Low Poly" (https://skfb.ly/6YpAS) by Igor_K. is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
- "Dead Tree - PS1 Low Poly" (https://skfb.ly/oFnOT) by Wersaus33 is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
- "Pine Tree - PS1 Low Poly" (https://skfb.ly/oFnRn) by Wersaus33 is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
```

21
assets/shaders/screen.frag

@ -5,8 +5,9 @@ in vec2 TexCoords; @@ -5,8 +5,9 @@ in vec2 TexCoords;
uniform sampler2D screenTexture;
const float gamma = 2.2;
uniform float exposure = 0.8;
uniform float gamma = 2.2;
uniform float exposure = 1.0;
uniform bool use_hdr = false;
layout (std140) uniform material_properties
{
@ -26,11 +27,15 @@ layout (std140) uniform material_properties @@ -26,11 +27,15 @@ layout (std140) uniform material_properties
void main()
{
vec3 hdrcol = texture(screenTexture, TexCoords).rgb;
//vec3 mapped = vec3(1.0) - exp((-hdrcol) * exposure);
vec3 mapped = hdrcol / (hdrcol + vec3(1.0));
// gamma correction
mapped = pow(mapped, vec3(1.0 / gamma));
FragColor = vec4(mapped, 1.0);
if (use_hdr) {
vec3 mapped = vec3(1.0) - exp((-hdrcol) * exposure);
//vec3 mapped = hdrcol / (hdrcol + vec3(1.0));
// gamma correction
mapped = pow(mapped, vec3(1.0 / gamma));
FragColor = vec4(mapped, 1.0);
}
else {
FragColor = vec4(hdrcol, 1.0);
}
}

162
source/main.cpp

@ -151,10 +151,10 @@ struct g_buffer { @@ -151,10 +151,10 @@ struct g_buffer {
/*
* The output textures of the G fragment shader.
*/
GLuint attachments[3] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
GLuint attachments[3] = {GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 };
g_buffer(int width, int height) : g_buffer(width, height, 1) { }
g_buffer(int width, int height, int scaling) : screen_width(width), screen_height(height), logical_width(width), logical_height(height) { }
g_buffer(int width, int height, float scaling) : screen_width(width), screen_height(height), logical_width(width*scaling), logical_height(height*scaling) { }
void create_buffers() {
@ -193,7 +193,7 @@ struct g_buffer { @@ -193,7 +193,7 @@ struct g_buffer {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, screen_x, screen_y, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, g_position, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, attachments[0], GL_TEXTURE_2D, g_position, 0);
// - normal color buffer
glGenTextures(1, &g_normal);
@ -201,7 +201,7 @@ struct g_buffer { @@ -201,7 +201,7 @@ struct g_buffer {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, screen_x, screen_y, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, g_normal, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, attachments[1], GL_TEXTURE_2D, g_normal, 0);
// - color + specular color buffer
glGenTextures(1, &g_albedo_specular);
@ -209,10 +209,10 @@ struct g_buffer { @@ -209,10 +209,10 @@ struct g_buffer {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screen_x, screen_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, g_albedo_specular, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, attachments[2], GL_TEXTURE_2D, g_albedo_specular, 0);
// - tell OpenGL which color attachments we'll use (of this framebuffer) for rendering
unsigned int attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
//unsigned int attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, attachments);
glCheckError();
@ -224,20 +224,20 @@ struct g_buffer { @@ -224,20 +224,20 @@ struct g_buffer {
}
void bind_textures() {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, g_position);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, g_normal);
glBindTexture(GL_TEXTURE_2D, g_position);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, g_normal);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, g_albedo_specular);
}
void present(std::shared_ptr<shader_handle> deferred_lighting, GLuint quad_vao) {
bind_textures();
deferred_lighting->set("gPosition", 0);
deferred_lighting->set("gNormal", 1);
deferred_lighting->set("gAlbedoSpec", 2);
deferred_lighting->set("gPosition", 1);
deferred_lighting->set("gNormal", 2);
deferred_lighting->set("gAlbedoSpec", 3);
deferred_lighting->use();
glDisable(GL_DEPTH_TEST);
@ -245,6 +245,7 @@ struct g_buffer { @@ -245,6 +245,7 @@ struct g_buffer {
//glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
//glBlitFramebuffer(0, 0, logical_width, logical_height, 0, 0, screen_width, screen_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glBindVertexArray(quad_vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
glCheckError();
@ -253,116 +254,6 @@ struct g_buffer { @@ -253,116 +254,6 @@ struct g_buffer {
};
struct g_buffer_multisampled {
GLuint fbo;
int width, height;
// texture ids
GLuint g_position, g_normal, g_albedo_specular;
GLuint stencil_depth;
g_buffer g_buffer_out;
/*
* The output textures of the G fragment shader.
*/
GLuint attachments[3] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
g_buffer_multisampled(int width, int height) : width(width), height(height), g_buffer_out(width, height) { }
void create_out_buffers() {
g_buffer_out.create_buffers();
}
void create_buffers() {
GLuint samples = 2;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
int screen_x = width;
int screen_y = height;
// bind to the existing framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// depth test and stencil texture
glGenTextures(1, &stencil_depth);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, stencil_depth);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,
samples,
GL_DEPTH24_STENCIL8,
width,
height,
0);
glCheckError();
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_DEPTH_STENCIL_ATTACHMENT,
GL_TEXTURE_2D_MULTISAMPLE,
stencil_depth,
0);
glCheckError();
// - position color buffer
glGenTextures(1, &g_position);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, g_position);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA16F, screen_x, screen_y, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, g_position, 0);
glCheckError();
// - normal color buffer
glGenTextures(1, &g_normal);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, g_normal);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA16F, screen_x, screen_y, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, g_normal, 0);
glCheckError();
// - color + specular color buffer
glGenTextures(1, &g_albedo_specular);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, g_albedo_specular);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, screen_x, screen_y, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D_MULTISAMPLE, g_albedo_specular, 0);
glCheckError();
// - tell OpenGL which color attachments we'll use (of this framebuffer) for rendering
unsigned int attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, attachments);
glCheckError();
create_out_buffers();
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
throw std::runtime_error("Error creating G buffer.");
}
glBindTexture(GL_TEXTURE_2D, 0);
}
void bind() {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, g_position);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, g_normal);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, g_albedo_specular);
}
void present(std::shared_ptr<shader_handle> deferred_lighting, GLuint quad_vao) {
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, g_buffer_out.fbo);
glBlitFramebuffer(0,0,width, height, 0,0,width,height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
g_buffer_out.bind_textures();
g_buffer_out.present(deferred_lighting, quad_vao);
}
};
void move_player(game_state &g, glm::vec3 walking_state, float time_delta) {
@ -422,6 +313,12 @@ int main_loop(game_state& g) @@ -422,6 +313,12 @@ int main_loop(game_state& g)
SDL_Event e;
bool quit = false;
struct {
float exposure = 1.0;
float gamma = 2.2;
bool use_hdr = false;
} tone_mapping;
glCheckError();
glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
glDisable(GL_CULL_FACE);
@ -439,7 +336,8 @@ int main_loop(game_state& g) @@ -439,7 +336,8 @@ int main_loop(game_state& g)
g.asset_dir / "shaders" / "g_frag.gl");
auto forward_pass_shader = g_shader;
struct g_buffer G {g.render_target->width, g.render_target->height};
// set scaling
struct g_buffer G {g.render_target->width, g.render_target->height, 1.0f}; // scaling 1x
glCheckError();
G.create_buffers();
glCheckError();
@ -586,12 +484,13 @@ int main_loop(game_state& g) @@ -586,12 +484,13 @@ int main_loop(game_state& g)
if (deferred) {
glBindFramebuffer(GL_FRAMEBUFFER, G.fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, G.fbo);
glViewport(0,0,G.logical_width, G.logical_height);
G.bind_textures();
forward_pass_shader = g_shader;
} else {
forward_pass_shader = forward_lighting;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
g.render_target->bind();
}
forward_pass_shader->use();
@ -658,7 +557,7 @@ int main_loop(game_state& g) @@ -658,7 +557,7 @@ int main_loop(game_state& g)
xenia_transform = glm::translate(xenia_transform, parent_transform.position);
xenia_transform = glm::translate(xenia_transform, glm::vec3(0, -8, 0));
xenia_transform = glm::rotate(xenia_transform, (float)M_PI, glm::vec3(1,0,0));
xenia_transform = glm::rotate(xenia_transform, (float)M_PI/2 - (glm::radians(cam.euler_angles[0] * walking_state.z) - glm::radians(90 * walking_state.x)), glm::vec3(0,1,0));
xenia_transform = glm::rotate(xenia_transform, (float)M_PI/2 - (glm::radians(cam.euler_angles[0] * walking_state.z) - glm::radians((cam.euler_angles[0] + 90) * walking_state.x)), glm::vec3(0,1,0));
xenia_transform = glm::scale(xenia_transform, glm::vec3(0.5));
xenia.draw(mat_ubo, model_ubo, forward_pass_shader, xenia_transform);
@ -696,10 +595,10 @@ int main_loop(game_state& g) @@ -696,10 +595,10 @@ int main_loop(game_state& g)
glCheckError();
if (deferred) {
g.render_target->bind();
// now draw the g buffer into the final buffer
//g.render_target->present(g.screen_shader);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_DEPTH_TEST);
//glBindFramebuffer(GL_FRAMEBUFFER, 0);
//g.screen_shader->use();
// now execute deferred lighting shader
deferred_lighting->use();
@ -709,6 +608,7 @@ int main_loop(game_state& g) @@ -709,6 +608,7 @@ int main_loop(game_state& g)
G.present(deferred_lighting, g.platonic_shapes.quad_vao);
}
g.render_target->present(g.screen_shader);
// forward render imgui on top of the scene
ImGui::Begin("Trees");
ImGui::SliderInt("Num Lights", &num_lights, 1, max_lights);
@ -718,6 +618,9 @@ int main_loop(game_state& g) @@ -718,6 +618,9 @@ int main_loop(game_state& g)
ImGui::Checkbox("Enable fog", (bool *)&fog_enabled);
ImGui::Checkbox("Move lights", (bool *)&move_lights);
ImGui::Checkbox("Deferred Shading", (bool *)&deferred);
ImGui::Checkbox("HDR", (bool *)&tone_mapping.use_hdr);
ImGui::SliderFloat("Exposure", &tone_mapping.exposure, 0, 3.0);
ImGui::SliderFloat("Gamma", &tone_mapping.gamma, 0, 4.0);
ImGui::Combo("Debug shader", &debug_shader, debug_shaders, IM_ARRAYSIZE(debug_shaders));
ImGui::End();
ImGui::Render();
@ -725,6 +628,9 @@ int main_loop(game_state& g) @@ -725,6 +628,9 @@ int main_loop(game_state& g)
SDL_GL_SwapWindow(g.window);
mat_ubo->current_lights(num_lights);
mat_ubo->enable_fog(fog_enabled);
g.screen_shader->set("gamma", tone_mapping.gamma);
g.screen_shader->set("exposure", tone_mapping.exposure);
g.screen_shader->set("use_hdr", tone_mapping.use_hdr);
while (SDL_PollEvent(&e) != 0) {
ImGui_ImplSDL2_ProcessEvent(&e);

6
source/window.cpp

@ -129,7 +129,7 @@ void game_state::init_renderbuffer() @@ -129,7 +129,7 @@ void game_state::init_renderbuffer()
std::make_shared<shader_handle>(asset_dir / "shaders" / "screen.vert",
asset_dir / "shaders" / "screen.frag");
screen_shader->use();
screen_shader->set("screenTexture", 0);
screen_shader->set("screenTexture", 4);
glCheckError();
}
@ -137,12 +137,14 @@ void game_state::init_renderbuffer() @@ -137,12 +137,14 @@ void game_state::init_renderbuffer()
void framebuffer_render_context::bind() const
{
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0,0, width, height);
glCheckError();
}
void framebuffer_render_context::unbind() const
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0,0, width, height);
glCheckError();
}
@ -167,9 +169,11 @@ void framebuffer_render_context::clear() @@ -167,9 +169,11 @@ void framebuffer_render_context::clear()
void framebuffer_render_context::present(std::shared_ptr<shader_handle>& shader)
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_DEPTH_TEST);
shader->use();
glBindVertexArray(quad_vao);
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, colour);
glDrawArrays(GL_TRIANGLES, 0, 6);
glCheckError();

Loading…
Cancel
Save