Skip to content

Commit

Permalink
Merge pull request #1876 from zenustech/fix-reverse-z
Browse files Browse the repository at this point in the history
improve reverse z use float depht buffer and inf z
  • Loading branch information
zhxx1987 authored Apr 10, 2024
2 parents 910db82 + 8ace538 commit 710471b
Show file tree
Hide file tree
Showing 12 changed files with 236 additions and 21 deletions.
7 changes: 1 addition & 6 deletions ui/zenoedit/viewport/displaywidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1289,12 +1289,7 @@ void DisplayWidget::onNodeSelected(const QModelIndex &subgIdx, const QModelIndex
auto fov = scene->camera->m_fov;
auto cz = glm::length(scene->camera->m_lodcenter);
if (depth != 0) {
// depth = depth * 2 - 1;
// cz = 2 * _near * _far / ((_far + _near) - depth * (_far - _near));
glm::vec4 ndc = {0, 0, depth, 1};
glm::vec4 clip_c = glm::inverse(scene->camera->m_proj) * ndc;
clip_c /= clip_c.w;
cz = -clip_c.z;
cz = scene->camera->m_near / depth;
}
auto w = scene->camera->m_nx;
auto h = scene->camera->m_ny;
Expand Down
2 changes: 1 addition & 1 deletion zenovis/include/zenovis/RenderEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace zenovis {
struct Scene;

struct RenderEngine {
virtual void draw() = 0;
virtual void draw(bool record) = 0;
virtual void update() = 0;

virtual ~RenderEngine() = default;
Expand Down
2 changes: 1 addition & 1 deletion zenovis/include/zenovis/Scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ struct Scene : zeno::disable_copy {
Scene();
~Scene();

void draw();
void draw(bool record);
bool loadFrameObjects(int frameid);
void cleanUpScene();
void switchRenderEngine(std::string const &name);
Expand Down
191 changes: 191 additions & 0 deletions zenovis/include/zenovis/bate/FrameBufferRender.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
#pragma once

#include "zenovis/Camera.h"
#include "zenovis/Scene.h"
#include "IGraphic.h"
#include "zenovis/ShaderManager.h"
#include "zenovis/opengl/buffer.h"
#include "zenovis/opengl/shader.h"
#include "zenovis/opengl/texture.h"
#include "zenovis/opengl/vao.h"
#include "zenovis/DrawOptions.h"

namespace zenovis {

using opengl::FBO;
using opengl::VAO;
using opengl::Buffer;
using opengl::Texture;
using opengl::RenderObject;
using opengl::Program;

using zeno::vec2i;
using zeno::vec3i;
using zeno::vec3f;

using std::unique_ptr;
using std::make_unique;

static const char * vert_code = R"(
#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoords;
out vec2 TexCoords;
void main()
{
TexCoords = aTexCoords;
gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
}
)";

static const char* frag_code = R"(
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D screenTexture;
void main()
{
vec3 col = texture(screenTexture, TexCoords).rgb;
FragColor = vec4(col, 1.0);
}
)";

static float quadVertices[] = { // vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
// positions // texCoords
-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f,

-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f
};

struct FrameBufferRender {
Scene* scene;

unique_ptr<FBO> fbo;
unique_ptr<Texture> picking_texture;
unique_ptr<RenderObject> depth_rbo;

unique_ptr<FBO> intermediate_fbo;
unique_ptr<Texture> screen_tex;

unique_ptr<VAO> quad_vao;
unique_ptr<Buffer> quad_vbo;

int w = 0;
int h = 0;
int samples = 16;

opengl::Program * shader = nullptr;

explicit FrameBufferRender(Scene* s) : scene(s) {
shader = scene->shaderMan->compile_program(vert_code, frag_code);
shader->use();
shader->set_uniformi("screenTexture", 0);

quad_vbo = make_unique<Buffer>(GL_ARRAY_BUFFER);
quad_vao = make_unique<VAO>();

CHECK_GL(glBindVertexArray(quad_vao->vao));
CHECK_GL(glBindBuffer(GL_ARRAY_BUFFER, quad_vbo->buf));
CHECK_GL(glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW));
CHECK_GL(glEnableVertexAttribArray(0));
CHECK_GL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0));
CHECK_GL(glEnableVertexAttribArray(1));
CHECK_GL(glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))));
}

~FrameBufferRender() {
destroy_buffers();
}

void generate_buffers() {
// generate framebuffer
fbo = make_unique<FBO>();
CHECK_GL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->fbo));

// get viewport size
w = scene->camera->m_nx;
h = scene->camera->m_ny;

// generate picking texture
picking_texture = make_unique<Texture>();
picking_texture->target = GL_TEXTURE_2D_MULTISAMPLE;
CHECK_GL(glBindTexture(picking_texture->target, picking_texture->tex));
CHECK_GL(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGB, w, h, GL_TRUE));
CHECK_GL(glBindTexture(picking_texture->target, 0));
CHECK_GL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, picking_texture->tex, 0));

// generate depth texture
depth_rbo = make_unique<RenderObject>();
CHECK_GL(glBindRenderbuffer(GL_RENDERBUFFER, depth_rbo->rbo));
CHECK_GL(glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_DEPTH_COMPONENT32F, w, h));
CHECK_GL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
CHECK_GL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_rbo->rbo));

// check fbo
if(!fbo->complete()) printf("fbo error\n");

// unbind fbo & texture
CHECK_GL(glBindTexture(GL_TEXTURE_2D, 0));
fbo->unbind();

intermediate_fbo = make_unique<FBO>();
screen_tex = make_unique<Texture>();
intermediate_fbo->bind();
CHECK_GL(glBindTexture(GL_TEXTURE_2D, screen_tex->tex));
CHECK_GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL));
CHECK_GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
CHECK_GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
CHECK_GL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, screen_tex->tex, 0)); // we only need a color buffer
if(!intermediate_fbo->complete()) printf("fbo error\n");
CHECK_GL(glBindTexture(GL_TEXTURE_2D, 0));
intermediate_fbo->unbind();
}

void destroy_buffers() {
fbo.reset();
picking_texture.reset();
depth_rbo.reset();
intermediate_fbo.reset();
screen_tex.reset();
}
void bind() {
// enable framebuffer writing
CHECK_GL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->fbo));
CHECK_GL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
}

void unbind() {
fbo->unbind();
}
void draw_to_screen() {
// 2. now blit multisampled buffer(s) to normal colorbuffer of intermediate FBO. Image is stored in screenTexture
CHECK_GL(glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->fbo));
CHECK_GL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, intermediate_fbo->fbo));
CHECK_GL(glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST));

// 3. now render quad with scene's visuals as its texture image
CHECK_GL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
CHECK_GL(glClearColor(1.0f, 1.0f, 1.0f, 1.0f));
CHECK_GL(glClear(GL_COLOR_BUFFER_BIT));
CHECK_GL(glDisable(GL_DEPTH_TEST));

glDisable(GL_MULTISAMPLE);
// draw Screen quad
shader->use();
CHECK_GL(glBindVertexArray(quad_vao->vao));
CHECK_GL(glActiveTexture(GL_TEXTURE0));
CHECK_GL(glBindTexture(GL_TEXTURE_2D, screen_tex->tex)); // use the now resolved color attachment as the quad's texture
CHECK_GL(glDrawArrays(GL_TRIANGLES, 0, 6));
glEnable(GL_MULTISAMPLE);
}
};
}
2 changes: 2 additions & 0 deletions zenovis/include/zenovis/opengl/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <string>
#include <vector>
#include <zeno/utils/Error.h>
#include <iostream>

namespace zenovis::opengl {

Expand Down Expand Up @@ -43,6 +44,7 @@ static void _check_opengl_error(const char *file, int line, const char *hint) {
if (err != GL_NO_ERROR) {
#endif
auto msg = get_opengl_error_string(err);
std::cerr << (std::string)file + ':' + std::to_string(line) + ": " + hint + ": " + msg << std::endl;
throw zeno::makeError((std::string)file + ':' + std::to_string(line) +
": " + hint + ": " + msg);
}
Expand Down
10 changes: 9 additions & 1 deletion zenovis/include/zenovis/opengl/texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,13 @@ struct FBO : zeno::disable_copy {
texture.target, texture.tex, 0));
}
};

struct RenderObject : zeno::disable_copy {
unsigned int rbo;
explicit RenderObject() {
CHECK_GL(glGenRenderbuffers(1, &rbo));
}
~RenderObject() {
CHECK_GL(glDeleteRenderbuffers(1, &rbo));
}
};
} // namespace zenovis::opengl
12 changes: 10 additions & 2 deletions zenovis/src/Camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ void Camera::setPhysicalCamera(float aperture, float shutter_speed, float iso, b
this->zOptixCameraSettingInfo.exposure = exposure;
}

static glm::mat4 MakeInfReversedZProjRH(float fovY_radians, float aspectWbyH, float zNear) {
float f = 1.0f / tan(fovY_radians / 2.0f);
return glm::mat4(
f / aspectWbyH, 0.0f, 0.0f, 0.0f,
0.0f, f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, -1.0f,
0.0f, 0.0f, zNear, 0.0f);
}
void Camera::placeCamera(glm::vec3 pos, glm::vec3 front, glm::vec3 up) {
front = glm::normalize(front);
up = glm::normalize(up);
Expand All @@ -74,7 +82,7 @@ void Camera::placeCamera(glm::vec3 pos, glm::vec3 front, glm::vec3 up) {
m_proj = glm::orthoZO(-radius * getAspect(), radius * getAspect(), -radius,
radius, m_far, m_near);
} else {
m_proj = glm::perspectiveZO(glm::radians(m_fov), getAspect(), m_far, m_near);
m_proj = MakeInfReversedZProjRH(glm::radians(m_fov), getAspect(), m_near);
}
}

Expand All @@ -99,7 +107,7 @@ void Camera::updateMatrix() {
void Camera::setResolution(int nx, int ny) {
m_nx = nx;
m_ny = ny;
m_proj = glm::perspectiveZO(glm::radians(m_fov), getAspect(), m_far, m_near);
m_proj = MakeInfReversedZProjRH(glm::radians(m_fov), getAspect(), m_near);
}
void Camera::setResolutionInfo(bool block, int nx, int ny)
{
Expand Down
10 changes: 5 additions & 5 deletions zenovis/src/Scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ bool Scene::loadFrameObjects(int frameid) {
return inserted;
}

void Scene::draw() {
void Scene::draw(bool record) {
if (renderMan->getDefaultEngineName() != "optx")
{
//CHECK_GL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0));
Expand All @@ -105,7 +105,7 @@ void Scene::draw() {
}

zeno::log_trace("scene redraw {}x{}", camera->m_nx, camera->m_ny);
renderMan->getEngine()->draw();
renderMan->getEngine()->draw(record);
}

std::vector<char> Scene::record_frame_offline(int hdrSize, int rgbComps) {
Expand All @@ -125,8 +125,8 @@ std::vector<char> Scene::record_frame_offline(int hdrSize, int rgbComps) {
bool bOptix = renderMan->getDefaultEngineName() == "optx";
if (bOptix)
{
draw();
return std::vector<char>();
draw(false);
return {};
}

std::vector<char> pixels(camera->m_nx * camera->m_ny * rgbComps * hdrSize);
Expand Down Expand Up @@ -158,7 +158,7 @@ std::vector<char> Scene::record_frame_offline(int hdrSize, int rgbComps) {

{
auto bindDrawBuf = opengl::scopeGLDrawBuffer(GL_COLOR_ATTACHMENT0);
draw();
draw(true);
}

if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
Expand Down
2 changes: 1 addition & 1 deletion zenovis/src/Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ void Session::set_smooth_shading(bool smooth) {
}

void Session::new_frame() {
impl->scene->draw();
impl->scene->draw(false);
//for (auto const &task: impl->render_tasks) {
//task();
//}
Expand Down
15 changes: 13 additions & 2 deletions zenovis/src/bate/RenderEngineBate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
#include <zenovis/bate/IGraphic.h>
#include <zenovis/opengl/vao.h>
#include <zenovis/opengl/scope.h>
#include "zenovis/bate/FrameBufferRender.h"

namespace zenovis::bate {

struct RenderEngineBate : RenderEngine {
std::unique_ptr<opengl::VAO> vao;
std::unique_ptr<GraphicsManager> graphicsMan;
std::vector<std::unique_ptr<IGraphicDraw>> hudGraphics;
std::unique_ptr<IGraphicDraw> primHighlight;
std::unique_ptr<FrameBufferRender> fbr;
Scene *scene;

auto setupState() {
Expand All @@ -29,6 +30,7 @@ struct RenderEngineBate : RenderEngine {

vao = std::make_unique<opengl::VAO>();
graphicsMan = std::make_unique<GraphicsManager>(scene);
fbr = std::make_unique<FrameBufferRender>(scene);

hudGraphics.push_back(makeGraphicGrid(scene));
hudGraphics.push_back(makeGraphicAxis(scene));
Expand All @@ -41,14 +43,18 @@ struct RenderEngineBate : RenderEngine {
graphicsMan->load_objects(scene->objectsMan->pairsShared());
}

void draw() override {
void draw(bool record) override {
auto guard = setupState();
CHECK_GL(glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE));
glDepthFunc(GL_GREATER);
CHECK_GL(glClearDepth(0.0));
CHECK_GL(glClearColor(scene->drawOptions->bgcolor.r, scene->drawOptions->bgcolor.g,
scene->drawOptions->bgcolor.b, 0.0f));
CHECK_GL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
if (!record) {
fbr->generate_buffers();
fbr->bind();
}

auto bindVao = opengl::scopeGLBindVertexArray(vao->vao);
graphicsMan->draw();
Expand Down Expand Up @@ -79,6 +85,11 @@ struct RenderEngineBate : RenderEngine {
CHECK_GL(glClear(GL_DEPTH_BUFFER_BIT));
scene->drawOptions->handler->draw();
}
if (!record) {
fbr->unbind();
fbr->draw_to_screen();
fbr->destroy_buffers();
}
}
};

Expand Down
Loading

0 comments on commit 710471b

Please sign in to comment.