0

I was using the following fragment shader to display a texture:

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

However, I wanted to be able to only display a clip of the image rather than the entire image. So, I added a call to textureSize to get the width and height of the texture so I could normalize the coordinates myself. But, it comes up with what looks like it's just repeating

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

This is h ow I am uploading the data:

  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

genpfault
  • 51,148
  • 11
  • 85
  • 139
Acorn
  • 1,147
  • 12
  • 27

1 Answers1

2

What you've done is taken the texture coordinates and remapped them to cover just the first pixel in the image. If you want to clip the input image, you'll need to specify to the shader the bounds of the area you wish to show. You could pass in a lower left and upper right coordinate and test against those. Something like this (not tested):

#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;
}
user1118321
  • 25,567
  • 4
  • 55
  • 86