GLSL 330: образец текстуры вниз

Я хочу уменьшить входную текстуру с 800x600 до одной четверти (200x150 пикселей). Но если я это сделаю, я смогу увидеть лишь небольшую часть изображения. Кажется, что кадровый шейдер не сэмплирует всю текстуру. В следующем примере показано создание эффекта глубины резкости.

Вершинный шейдер:

#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;
}

Фрагментный шейдер:

#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);
}

Входная текстура имеет размер 800x600, а выходная текстура — 200x150 пикселей. В качестве m_InvertedScreenSize я использую 1/800 и 1/600 пикселей. Это правильно?

Я загружаю два треугольника, которые представляют собой экранные координаты 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, }, }; 

Моя экранная матрица переводит эти вершины в пространство отсечения через ортогональную матрицу.

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);

Следующие изображения показывают исходную текстуру и результат. Первый — это исходное изображение без понижающей дискретизации. Во-вторых, это реальная сэмплированная текстура. И третья — это текстура с пониженной частотой дискретизации с вычислением ScreenCoords *= 4.0f;.

Это текстура, которая входит в шейдер и должна быть уменьшена.Результат после выборки вниз... Изображение, которое я хочу  иметь.


person Tobias Schwandt    schedule 20.03.2013    source источник
comment
Что не так в аппаратной реализации билинейной фильтрации и мипмэппинга? Проверьте также возможный дубликат: stackoverflow.com/ вопросы/9805574/   -  person Aki Suihkonen    schedule 21.03.2013
comment
Я использую линейную фильтрацию в качестве сэмплера цвета и текстуры глубины.   -  person Tobias Schwandt    schedule 21.03.2013
comment
Если я умножу ScreenCoords на 4, я получу правильный результат. Но почему? Нужно ли менять матрицу экрана? Примечание. Я визуализирую в четырехугольник (постобработка).   -  person Tobias Schwandt    schedule 21.03.2013
comment
Трудно ответить на этот вопрос, не зная, каковы исходные данные для этого процесса. Каковы ваши вершинные атрибуты и тому подобное?   -  person Nicol Bolas    schedule 21.03.2013
comment
Я загружаю два треугольника, которые представляют собой экранные координаты 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, }, }; Моя экранная матрица переводит эти вершины в пространство отсечения через ортогональную матрицу.   -  person Tobias Schwandt    schedule 21.03.2013