Fix image dilation (closing #108)

- Using pixel(=texel) coordinates and integer offsets
 - Using a single channel stencil texture instead of a 4-channel one
This commit is contained in:
Alexander Bock
2016-08-18 16:29:00 +02:00
parent 72e1e9231a
commit 2ae7095d9b
3 changed files with 33 additions and 16 deletions
+28 -12
View File
@@ -30,6 +30,8 @@ out vec4 color;
uniform sampler2D tex;
uniform sampler2D stencil;
// We conside the 8-neighborhood of a texel, so going a stepsize of '1' in both
// directions
vec2 offsets[8] = {
vec2(-1.0, -1.0),
vec2(-1.0, 0.0),
@@ -41,38 +43,52 @@ vec2 offsets[8] = {
vec2(1.0, 1.0)
};
vec3 gatherColors(vec2 position) {
// Collect the contributing colors from the neighboring texels and return the
// averaged value of all texels that passed the masking test based on 'stencil'
vec3 gatherNeighboringColors() {
vec2 texSize = textureSize(tex, 0);
// The total number of contributing texels
int nContributions = 0;
// The summed color of all contributing texels
vec3 totalColor = vec3(0.0);
for (int i = 0; i < 8; i++) {
// gl_FragCoord is in pixel coordinates; the ProjectionComponent sets
// the viewport such that pixels=texels, so we can use gl_FragCoord as an
// integer texel coordinate
// First offsetting them, then dividing by the texture size to get to [0,1]
vec2 samplePosition = (gl_FragCoord.xy + offsets[i]) / texSize;
// The stencelling determines the areas that we have to enlarge, such that we
// do not enlarge a previously enlarged area
if (texture(stencil, samplePosition).r != 0.0) {
vec3 c = texture(tex, samplePosition).rgb;
totalColor += c;
totalColor += texture(tex, samplePosition).rgb;
nContributions++;
}
}
return totalColor / nContributions;
// GLSL normally doesn't have a problem taking vec3(0.0)/0.0 but we don't want to
// tempt the compiler gods
if (nContributions > 0) {
return totalColor / nContributions;
}
else {
return vec3(0.0);
}
}
void main() {
vec4 c = texture(tex, vs_uv);
float s = texture(stencil, vs_uv).r;
if (s == 0.0) {
if (texture(stencil, vs_uv).r == 0.0) {
// This means that the current fragment/texel we are looking at has not been
// projected on and we only want to do the dilation into these texels
color = vec4(gatherColors(vs_uv), 1.0);
color = vec4(gatherNeighboringColors(), 1.0);
}
else {
// We are in a region where an image has been projected, so we can reuse the
// already sampled version
color = c;
color = texture(tex, vs_uv);
}
}
}
@@ -24,14 +24,14 @@
#version __CONTEXT__
#include "PowerScaling/powerScaling_vs.hglsl"
in vec4 vs_position;
in vec4 vs_normal;
in vec2 vs_uv;
in vec4 ProjTexCoord;
layout (location = 0) out vec4 color;
layout (location = 0) out vec4 color;
// Even though the stencel texture is only a single channel, we still need to
// output a vec4, or the result will disappear
layout (location = 1) out vec4 stencil;
uniform sampler2D projectionTexture;
@@ -558,7 +558,8 @@ bool ProjectionComponent::generateProjectionLayerTexture() {
_dilation.stencilTexture = std::make_unique<ghoul::opengl::Texture>(
glm::uvec3(maxSize, maxSize / 2, 1),
ghoul::opengl::Texture::Format::RGBA
ghoul::opengl::Texture::Format::Red,
ghoul::opengl::Texture::Format::Red
);
if (_dilation.stencilTexture) {