代码之家  ›  专栏  ›  技术社区  ›  Acorn

从剪辑计算纹理坐标

  •  0
  • Acorn  · 技术社区  · 5 年前

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

    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

    0 回复  |  直到 5 年前
        1
  •  2
  •   user1118321    5 年前

    你所做的是采取纹理坐标,并重新映射它们,只覆盖图像中的第一个像素如果要剪裁输入图像,则需要将要显示区域的边界指定给着色器你可以通过左下角和右上角的坐标测试类似这样的东西(未测试):

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