2

I want to down sample an input texture from 800x600 to one quarter itself (200x150 pixel). But if I do that I can see only a little bit of the image. It seems that the frament shader doesn't down sample the whole texture. The following example is to create an depth-of-field effect.

Vertex shader:

#version 330

uniform UVertFrameBuffer
{
    mat4  m_ScreenMatrix;
};

uniform UDofInvertedScreenSize
{
    vec2 m_InvertedScreenSize;
};

// -----------------------------------------------------------------------------
// in variables
// -----------------------------------------------------------------------------

layout(location = 0) in vec3 VertexPosition;

// -----------------------------------------------------------------------------
// out variables
// -----------------------------------------------------------------------------

struct SPixelCoords
{
    vec2 tcColor0;
    vec2 tcColor1;
};

out SPixelCoords vs_PixelCoords;

// -----------------------------------------------------------------------------
// Program
// -----------------------------------------------------------------------------

void main()
{
    vec4 Position = vec4(VertexPosition.xy, 0.0f, 1.0f);

    vec4 PositionInClipSpace = m_ScreenMatrix * Position;
    vec2 ScreenCoords        = VertexPosition.xy;

    // -----------------------------------------------------------------------------

    vs_PixelCoords.tcColor0 = ScreenCoords + vec2(-1.0f, -1.0f) * m_InvertedScreenSize;
    vs_PixelCoords.tcColor1 = ScreenCoords + vec2(+1.0f, -1.0f) * m_InvertedScreenSize;

    // -----------------------------------------------------------------------------

    gl_Position = PositionInClipSpace;
}

Fragment shader:

#version 330

uniform sampler2D g_ColorTex;
uniform sampler2D g_DepthTex;

uniform UDofDownBuffer
{
    vec2  m_DofNear;
    vec2  m_DofRowDelta;
};

// -----------------------------------------------------------------------------
// Inputs per vertice
// -----------------------------------------------------------------------------

struct SPixelCoords
{
    vec2 tcColor0;
    vec2 tcColor1;
};

in SPixelCoords vs_PixelCoords;

// -----------------------------------------------------------------------------
// Output to graphic card
// -----------------------------------------------------------------------------

layout (location = 0) out vec4 FragColor;

// -----------------------------------------------------------------------------
// Program
// -----------------------------------------------------------------------------

void main() 
{
    // Initialize variables
    vec3  Color;
    float MaxCoc;
    vec4  Depth;
    vec4  CurCoc;
    vec4  Coc;
    vec2  RowOfs[4];

    // Calculate row offset
    RowOfs[0] = vec2(0.0f);
    RowOfs[1] = m_DofRowDelta.xy;
    RowOfs[2] = m_DofRowDelta.xy * 2.0f;
    RowOfs[3] = m_DofRowDelta.xy * 3.0f;

    // Bilinear filtering to average 4 color samples
    Color  = vec3(0.0f);
    Color += texture(g_ColorTex, vs_PixelCoords.tcColor0.xy + RowOfs[0]).rgb;
    Color += texture(g_ColorTex, vs_PixelCoords.tcColor1.xy + RowOfs[0]).rgb;
    Color += texture(g_ColorTex, vs_PixelCoords.tcColor0.xy + RowOfs[2]).rgb;
    Color += texture(g_ColorTex, vs_PixelCoords.tcColor1.xy + RowOfs[2]).rgb;
    Color /= 4.0f;

    // Calculate CoC
    ...

    // Calculate fragment color
    FragColor = vec4(Color, MaxCoc);
}

The input texture is 800x600 and the output texture is 200x150 pixel. As m_InvertedScreenSize I use 1/800 and 1/600 pixel. Is that right?

I upload two triangles which represent screen coordinates of OpenGL.

QuadVertices[][1] = { 
{ 0.0f, 1.0f, 0.0f, }, 
{ 1.0f, 1.0f, 0.0f, }, 
{ 1.0f, 0.0f, 0.0f, }, 
{ 0.0f, 0.0f, 0.0f, }, }; 

QuadIndices[][2] = { 
{ 0, 1, 2, }, 
{ 0, 2, 3, }, }; 

My screen matrix translate these vertices into clipping space via a orthogonal matrix.

Position(0.0f, 0.0f, 1.0f);
Target(0.0f, 0.0f, 0.0f);
Up(0.0f, 1.0f, 0.0f);

LookAt(Position, Target, Up);

SetOrthographic(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);

The following images shows the input texture and the result. First one is the original image without down sampling. Second is the actual down sampled texture. And the third one is a down sampled texture with calculating ScreenCoords *= 4.0f;.

This is the texture that goes into shader and should be down sampled. Result after down sampling... Image I want to have.

Tobias
  • 427
  • 4
  • 19
  • What's wrong in the HW implementation of bilinear filtering and mipmapping? Check also a possible duplicate: http://stackoverflow.com/questions/9805574/opengl-glsl-implementation-of-texture-filtering – Aki Suihkonen Mar 20 '13 at 21:23
  • I use linear filtering as sampler for color and depth texture. – Tobias Mar 20 '13 at 21:35
  • If I multiple ScreenCoords with 4 then I get the right result. But why? Do I have to change Screen Matrix? Note: I render to a quad (post process). – Tobias Mar 20 '13 at 22:29
  • It's hard to answer this question without knowing what the inputs to this process are. What are your vertex attributes and such? – Nicol Bolas Mar 20 '13 at 23:12
  • I upload two triangles which represent screen coordinates of OpenGL. QuadVertices[][3] = { { 0.0f, 1.0f, 0.0f, }, { 1.0f, 1.0f, 0.0f, }, { 1.0f, 0.0f, 0.0f, }, { 0.0f, 0.0f, 0.0f, }, }; QuadIndices[][3] = { { 0, 1, 2, }, { 0, 2, 3, }, }; My screen matrix translate these vertices into clipping space via a orthogonal matrix. – Tobias Mar 21 '13 at 00:37

0 Answers0