Fix manual depth test hole cutting

This commit is contained in:
Malin E
2023-03-03 08:44:13 +01:00
parent fedbf9a31e
commit 98836e5393
4 changed files with 46 additions and 12 deletions

View File

@@ -28,6 +28,7 @@
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/rendering/framebufferrenderer.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/util/distanceconversion.h>
@@ -72,11 +73,12 @@ namespace {
GL_COLOR_ATTACHMENT2,
};
constexpr std::array<const char*, 12> UniformNames = {
constexpr std::array<const char*, 14> UniformNames = {
"nLightSources", "lightDirectionsViewSpace", "lightIntensities",
"modelViewTransform", "normalTransform", "projectionTransform",
"performShading", "ambientIntensity", "diffuseIntensity",
"specularIntensity", "performManualDepthTest", "gBufferDepthTexture"
"specularIntensity", "performManualDepthTest", "gBufferDepthTexture",
"viewport", "resolution"
};
constexpr std::array<const char*, 3> UniformOpacityNames = {
@@ -812,7 +814,7 @@ void RenderableModel::render(const RenderData& data, RendererTasks&) {
glClearBufferfv(GL_COLOR, 1, glm::value_ptr(glm::vec4(0.f, 0.f, 0.f, 0.f)));
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use a manuel depth test to make the models aware of the rest of the envierment
// Use a manuel depth test to make the models aware of the rest of the scene
_program->setUniform(
_uniformCache.performManualDepthTest,
_enableDepthTest
@@ -831,6 +833,23 @@ void RenderableModel::render(const RenderData& data, RendererTasks&) {
gBufferDepthTextureUnit
);
// Will also need the resolution and viewport to get a texture coordinate for the
// G-buffer depth texture
_program->setUniform(
_uniformCache.resolution,
glm::vec2(global::windowDelegate->currentDrawBufferResolution())
);
GLint vp[4] = { 0 };
global::renderEngine->openglStateCache().viewport(vp);
glm::ivec4 viewport = glm::ivec4(vp[0], vp[1], vp[2], vp[3]);
_program->setUniform(
_uniformCache.viewport,
static_cast<float>(viewport[0]),
static_cast<float>(viewport[1]),
static_cast<float>(viewport[2]),
static_cast<float>(viewport[3])
);
// Render Pass 1
// Render all parts of the model into the new framebuffer without opacity

View File

@@ -105,7 +105,8 @@ private:
UniformCache(nLightSources, lightDirectionsViewSpace, lightIntensities,
modelViewTransform, normalTransform, projectionTransform,
performShading, ambientIntensity, diffuseIntensity,
specularIntensity, performManualDepthTest, gBufferDepthTexture) _uniformCache;
specularIntensity, performManualDepthTest, gBufferDepthTexture,
viewport, resolution) _uniformCache;
std::vector<std::unique_ptr<LightSource>> _lightSources;

View File

@@ -25,7 +25,6 @@
#include "fragment.glsl"
in vec2 vs_st;
in vec2 vs_viewportPixelCoord;
in vec3 vs_normalViewSpace;
in vec4 vs_positionCameraSpace;
in float vs_screenSpaceDepth;
@@ -51,6 +50,9 @@ uniform float lightIntensities[8];
uniform bool performManualDepthTest = false;
uniform sampler2D gBufferDepthTexture;
uniform vec4 viewport;
uniform vec2 resolution;
Fragment getFragment() {
Fragment frag;
frag.depth = vs_screenSpaceDepth;
@@ -60,9 +62,27 @@ Fragment getFragment() {
frag.color.a = 1.0;
if (performManualDepthTest) {
// gl_FragCoord.x goes from 0 to resolution.x and gl_FragCoord.y goes from 0 to
// resolution.y, need to normalize it
vec2 texCoord = gl_FragCoord.xy;
texCoord.x = texCoord.x / resolution.x;
texCoord.y = texCoord.y / resolution.y;
// Modify the texCoord based on the Viewport and Resolution. This modification is
// necessary in case of side-by-side stereo as we only want to access the part of the
// feeding texture that we are currently responsible for. Otherwise we would map the
// entire feeding texture into our half of the result texture, leading to a doubling
// of the "missing" half. If you don't believe me, load a configuration file with the
// side_by_side stereo mode enabled, disable FXAA, and remove this modification.
// The same calculation is done in the FXAA shader, the HDR resolving and the
// atmosphere shader
vec2 st = texCoord;
st.x = st.x / (resolution.x / viewport[2]) + (viewport[0] / resolution.x);
st.y = st.y / (resolution.y / viewport[3]) + (viewport[1] / resolution.y);
// Manual depth test
float gBufferDepth =
denormalizeFloat(texture(gBufferDepthTexture, vs_viewportPixelCoord).x);
denormalizeFloat(texture(gBufferDepthTexture, st).x);
if (vs_screenSpaceDepth > gBufferDepth) {
frag.color = vec4(0.0);
frag.depth = gBufferDepth;

View File

@@ -32,7 +32,6 @@ layout(location = 2) in vec3 in_normal;
layout(location = 3) in vec3 in_tangent;
out vec2 vs_st;
out vec2 vs_viewportPixelCoord;
out vec3 vs_normalViewSpace;
out float vs_screenSpaceDepth;
out vec4 vs_positionCameraSpace;
@@ -68,9 +67,4 @@ void main() {
vec3 B = normalize(cross(N, T));
vs_TBN = mat3(T, B, N);
// Figure out the fragment's position in the viewport
vec3 ndc = gl_Position.xyz / gl_Position.w; // perspective divide/normalize
vec2 viewportCoord = ndc.xy * 0.5 + 0.5; // ndc is -1 to 1 in GL. scale for 0 to 1
vs_viewportPixelCoord = viewportCoord;
}