从剪辑计算纹理坐标

时间:2019-02-18 06:20:38

标签: c++ opengl glsl

我正在使用以下片段着色器显示纹理:

std::string const fragment_shader_source = 
    "#version 330 core\n"
    ""
    "in vec4 fColor;\n"
    "in vec2 fTexPos;\n"
    "\n"
    "out vec4 finalColor;\n"
    "\n"
    "uniform sampler2D textureUniform;\n"
    "\n"
    "void main() {\n"
    "    \n"
    "    vec4 textureColor = texture(textureUniform, fTexPos);\n"
    "    finalColor = fColor * textureColor;\n"
    "}";

enter image description here

但是,我希望只能显示图像的片段,而不是整个图像。因此,我添加了对textureSize的调用,以获取纹理的宽度和高度,以便我自己对坐标进行标准化。但是,它看起来就像是在重复

std::string const fragment_shader_source = 
    "#version 330 core\n"
    ""
    "in vec4 fColor;\n"
    "in vec2 fTexPos;\n"
    "\n"
    "out vec4 finalColor;\n"
    "\n"
    "uniform sampler2D textureUniform;\n"
    "\n"
    "void main() {\n"
    "    \n"
    "    ivec2 samplerSize = textureSize(textureUniform, 0);\n"
    "    vec2 texturePos = vec2(fTexPos.x / float(samplerSize.x), fTexPos.y / float(samplerSize.y));\n"
    "    vec4 textureColor = texture(textureUniform, texturePos);\n"
    "    finalColor = fColor * textureColor;\n"
    "}";

这就是我要上传的数据:

  glBufferData(GL_ARRAY_BUFFER, sizeof(acorn::graphics::Vertex) * sprite_batch_.size() * 6, nullptr, GL_DYNAMIC_DRAW);

  std::vector<Vertex> vertex_data;
  for(auto const& sprite : sprite_batch_) {
    GLfloat fw = (sprite.origin_x + sprite.u);
    GLfloat bw = sprite.origin_x;

    GLfloat fh = (sprite.origin_y + sprite.v);
    GLfloat bh = sprite.origin_y;

    //                      body                  color          texture
    //                      x     y      r    g      b    a     s   t
    vertex_data.push_back({0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, fw, fh});
    vertex_data.push_back({-0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, bw, fh});
    vertex_data.push_back({0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, fw, bh});
    vertex_data.push_back({-0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, bw, bh});
    vertex_data.push_back({-0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, bw, fh});
    vertex_data.push_back({0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, fw, bh});

  }

  glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertex) * vertex_data.size(), static_cast<void*>(vertex_data.data()));


  glDrawArrays(GL_TRIANGLES, 0, 6);

enter image description here

1 个答案:

答案 0 :(得分:2)

您要做的是获取纹理坐标,并将其重新映射为仅覆盖图像中的第一个像素。如果要裁剪输入图像,则需要向着色器指定要显示的区域的边界。您可以传递左下角和右上角的坐标,然后对这些坐标进行测试。这样的东西(未经测试):

#version 330 core
in vec4 fColor;
in vec2 fTexPos;

out vec4 finalColor

uniform sampler2D textureUniform;
uniform float2 lowerLeft;
uniform float2 upperRight;

void main()
{
    if ((lowerLeft.x <= fTexPos.x) && (fTexPos.x <= upperRight.x) &&
        (lowerLeft.y <= fTexPos.y) && (fTexPos.y <= upperRight.y))
    {
        textureColor = texture(textureUniform, fTexPos);
    }
    else
    {
        textureColor = vec4(0.0);
    }
    finalColor = textureColor * fColor;
}