无法将简单的无符号字节 RGB 纹理映射到四边形:

2024-04-16

我有一个非常简单的程序,将虚拟红色纹理映射到四边形。

下面是 C++ 中的纹理定义:

struct DummyRGB8Texture2d
{
    uint8_t data[3*4];
    int width;
    int height;

};

DummyRGB8Texture2d myTexture
{
    { 
        255,0,0,
        255,0,0,
        255,0,0,
        255,0,0
    },
    2u,
    2u
};

这就是我设置纹理的方式:

void SetupTexture()
{
    // allocate a texture on the default texture unit (GL_TEXTURE0): 

    GL_CHECK(glCreateTextures(GL_TEXTURE_2D, 1, &m_texture));

    // allocate texture:
    GL_CHECK(glTextureStorage2D(m_texture, 1, GL_RGB8, myTexture.width, myTexture.height));

    GL_CHECK(glTextureParameteri(m_texture, GL_TEXTURE_WRAP_S, GL_REPEAT));
    GL_CHECK(glTextureParameteri(m_texture, GL_TEXTURE_WRAP_T, GL_REPEAT));
    GL_CHECK(glTextureParameteri(m_texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
    GL_CHECK(glTextureParameteri(m_texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST));

    // tell the shader that the sampler2d uniform uses the default texture unit (GL_TEXTURE0) 
    GL_CHECK(glProgramUniform1i(m_program->Id(), /* location in shader */ 3, /* texture unit index */ 0));

    // bind the created texture to the specified target. this is necessary even in dsa
    GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_texture));

    GL_CHECK(glGenerateMipmap(GL_TEXTURE_2D));
}

这就是我将纹理绘制到四边形的方法:

void Draw()
{
    m_target->ClearTargetBuffers();
    m_program->MakeCurrent();

    // load the texture to the GPU:
    GL_CHECK(glTextureSubImage2D(m_texture, 0, 0, 0, myTexture.width, myTexture.height,
            GL_RGB, GL_UNSIGNED_BYTE, myTexture.data));

    GL_CHECK(glBindVertexArray(m_vao));     

    GL_CHECK(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(VideoQuadElementArray.size()), GL_UNSIGNED_INT, 0));
        m_target->SwapTargetBuffers();
}

结果:

我不明白为什么这个纹理不会显示为红色。另外,如果我将纹理内部格式更改为 RGBA / RGBA8 和纹理数据数组在每行中都有另一个元素,我得到了一个漂亮的红色纹理。


如果它相关,这里是我的顶点属性和我的(非常简单的)着色器:

struct VideoQuadVertex
{
    glm::vec3 vertex;
    glm::vec2 uv;
};

std::array<VideoQuadVertex, 4> VideoQuadInterleavedArray
{
    /* vec3 */ VideoQuadVertex{ glm::vec3{ -0.25f, -0.25f, 0.5f }, /* vec2 */  glm::vec2{ 0.0f, 0.0f } },
    /* vec3 */ VideoQuadVertex{ glm::vec3{ 0.25f, -0.25f, 0.5f }, /* vec2 */   glm::vec2{ 1.0f, 0.0f } },
    /* vec3 */ VideoQuadVertex{ glm::vec3{ 0.25f, 0.25f, 0.5f }, /* vec2 */    glm::vec2{ 1.0f, 1.0f } },
    /* vec3 */ VideoQuadVertex{ glm::vec3{ -0.25f, 0.25f, 0.5f }, /* vec2 */ glm::vec2{ 0.0f, 1.0f } }


};

顶点设置:

void SetupVertexData()
{


// create a VAO to hold all node rendering states, no need for binding:
    GL_CHECK(glCreateVertexArrays(1, &m_vao));

// create vertex buffer objects for data and indices and initialize them:
GL_CHECK(glCreateBuffers(static_cast<GLsizei>(m_vbo.size()), m_vbo.data()));

// allocate memory for interleaved vertex attributes and transfer them to the GPU:
GL_CHECK(glNamedBufferData(m_vbo[EVbo::Data], VideoQuadInterleavedArray.size() * sizeof(VideoQuadVertex), VideoQuadInterle

GL_CHECK(glVertexArrayAttribBinding(m_vao, 0, 0));
GL_CHECK(glVertexArrayVertexBuffer(m_vao, 0, m_vbo[EVbo::Data], 0, sizeof(VideoQuadVertex)));


// setup the indices array:
GL_CHECK(glNamedBufferData(m_vbo[EVbo::Element], VideoQuadElementArray.size() * sizeof(GLuint), VideoQuadElementArray.data
GL_CHECK(glVertexArrayElementBuffer(m_vao, m_vbo[EVbo::Element]));

// enable the relevant attributes for this VAO and
// specify their format and binding point:

// vertices:
GL_CHECK(glEnableVertexArrayAttrib(m_vao, 0 /* location in shader*/));
GL_CHECK(glVertexArrayAttribFormat(
    m_vao,
    0,                  // attribute location
    3,                  // number of components in each data member
    GL_FLOAT,           // type of each component
    GL_FALSE,           // should normalize
    offsetof(VideoQuadVertex, vertex)   // offset from the begining of the buffer
));

// uvs:
GL_CHECK(glEnableVertexArrayAttrib(m_vao, 1 /* location in shader*/));
GL_CHECK(glVertexAttribFormat(
    1,                                  // attribute location
    2,                                  // number of components in each data member
    GL_FLOAT,                           // type of each component
    GL_FALSE,                           // should normalize
    offsetof(VideoQuadVertex, uv)   // offset from the begining of the buffer
));

GL_CHECK(glVertexArrayAttribBinding(m_vao, 1, 0));

}

顶点着色器:

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texture_coordinate;


out FragmentData
{
    vec2 uv;
} toFragment;


void main(void)
{   
    toFragment.uv = texture_coordinate;
    gl_Position = vec4 (position, 1.0f);
}

片段着色器:

in FragmentData
{
    vec2 uv;
} data;

out vec4 color;

layout (location = 3) uniform sampler2D tex_object;

void main()
{
    color = texture(tex_object, data.uv);   
}

GL_UNPACK_ALIGNMENT指定内存中每个像素行开头的对齐要求。默认情况下GL_UNPACK_ALIGNMENT设置为 4。 这意味着纹理的每一行的长度应该为 4*N 字节。

您使用数据指定 2*2 纹理:255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0

With GL_UNPACK_ALIGNMENT设置为 4 这被解释为

         column 1          column 2              alignment
row 1:   255, 0,   0,      255, 0,     0,        255, 0,
row 2:   0,   255, 0,      0,   undef, undef

所以纹理读作

          column 1   olumn 2  
row 1:    red,       red,
row 2:    green,     RGB(0, ?, ?)

你必须设置glPixelStorei(GL_UNPACK_ALIGNMENT, 1); https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPixelStore.xhtml before glTextureSubImage2D,用于读取紧密排列的纹理。

如果你不想改变GL_UNPACK_ALIGNMENT(对齐方式保持为4),您必须按如下方式调整数据:

struct DummyRGB8Texture2d
{
    uint8_t data[8*2];
    int width;
    int height;
};

DummyRGB8Texture2d myTexture
{
    { 
        255, 0, 0, 255, 0, 0, // row 1
        0, 0,                 // 2 bytes alignment
        255, 0, 0, 255, 0, 0, // row 2
        0, 0                  // 2 bytes alignment
    },
    2u,
    2u
};

See further:
  • 堆栈溢出问题glPixelStorei(GL_UNPACK_ALIGNMENT, 1) 缺点? https://stackoverflow.com/questions/11042027/glpixelstoreigl-unpack-alignment-1-disadvantages
  • 堆栈溢出问题OpenGL GL_UNPACK_ALIGNMENT https://stackoverflow.com/questions/33887344/opengl-gl-unpack-alignment
  • 科诺斯OpenGL常见错误 - 纹理上传和像素读取 https://www.khronos.org/opengl/wiki/Common_Mistakes#Texture_upload_and_pixel_reads
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法将简单的无符号字节 RGB 纹理映射到四边形: 的相关文章

随机推荐

  • 机器人框架 - 清除元素文本关键字不起作用

    我们有一个 html 结构的文本字段 如下所示
  • 在 CSS 流布局中自动调整图像大小以模拟 html 表格布局

    我有一个图像 根据屏幕分辨率 它会在 CSS 流布局中下降到看不见的位置 因为我已将其宽度和高度设置为静态值 CSS 流布局中是否有一种方法可以在有人缩小浏览器窗口时自动调整图像大小 我已经在 html table 布局中看到了这一点 并且
  • 具有双重重置的复数累加和

    我试图遵循一些关于何时将数据分组到图表中的规则 我将如何处理这个数据框 A tibble 11 x 8 assay year qtr invalid valid total assays hfr predicted inv
  • 使用 Active Directory 集成身份验证的 Azure SQL 数据库连接无法打开

    我正在尝试使用类似于以下内容的连接字符串通过实体框架连接到 Azure SQL 数据库 Data Source
  • Android Studio - Gradle:如何替换文件中的变量

    我对 Gradle 相当陌生 一直在使用 Eclipse 和 Ant 来完成所有构建 在我们的应用程序中 我们有一个 config properties 文件 位于与 src 和 res 等处于同一级别的 asset 文件夹中 在此文件中
  • 如何强制 Hibernate 将日期返回为 java.util.Date 而不是时间戳?

    情况 我有一个带有 java util Date 类型变量的持久类 import java util Date Entity Table name prd period Cache usage CacheConcurrencyStrateg
  • PyPy 明显慢于 CPython

    我一直在测试我制作的缓存系统 其目的是加速 Django Web 应用程序 它将所有内容存储在内存中 根据 cProfile 我的测试中的大部分时间都花在 QuerySet clone 内 结果证明效率非常低 考虑到实现 这实际上并不奇怪
  • 如何将所有为零的元素移动到数组末尾?

    编写一个函数 该函数接受一个值数组 并将所有为零的元素移动到数组末尾 否则保留数组的顺序 零元素还必须保持它们出现的顺序 零元素由 0 或 0 定义 某些测试可能包含非数字文字的元素 不允许使用任何临时数组或对象 也不允许使用任何 Arra
  • 允许特定用户写访问

    我的 Firebase 读 写规则有点受阻 我希望我有一种方法可以在检查身份验证时设置断点 没有办法 不是吗 我的问题很简单 我觉得我应该能够更好地理解它 我觉得大部分都是因为没有完全理解规则 此信息是一种在线查看产品的简单方法 并且所有者
  • 将数据注释应用于 MVC 中视图模型的子属性?

    在属性上添加简单的数据注释非常棒 public class UnicornViewModel Required public string Name get set 但假设我有这样的事情 public class SuperPower pu
  • 在C++中实现可迭代的优先级队列

    我需要为一个项目实现一个优先级队列 但是STL的priority queue没有指出 因为我们需要迭代所有元素并随机删除它们 我们正在考虑使用STLset为此 将其包装在一个类中以使其成为 ADT 对此有更聪明的解决方案吗 我们怎样才能让它
  • Django Rest Framework 自定义响应消息

    我有两个关于 Django Rest Framework 响应消息的问题 1 使用时generics ListCreateAPIView or RetrieveDestroyAPIView 通常返回一个资源 例如 使用 POST 方法调用
  • Haskell 中的简单合并排序并行化没有加速

    注 这篇文章于2011 06 10完全重写 感谢彼得帮助我 另外 如果我不接受一个答案 请不要生气 因为这个问题似乎是相当开放式的 但是 如果你解决了它 当然你会得到复选标记 另一位用户发布了有关并行化合并排序的问题 我以为我会写一个简单的
  • 如果我输入文本框 1,3 那么 checkbox1 和 checkbox3 将被禁用而不被选中!

    如果我输入文本框 1 3 那么 checkbox1 和 checkbox3 将被禁用而不被选中 我在下面提供的编码正在工作 但是 它根据文本框中的文本检查 cjeckoxes 即 1 3 然后将检查 checkbox1 和 checkbox
  • UnknownFieldException - 没有这样的字段

    当我尝试使用 xstream 将 xml 文件编组到 POJO 中时 我不断收到此错误 我不确定发生了什么 可以用新的眼光来看待事物 Exception in thread main com thoughtworks xstream con
  • java 中 (--i + ++i) 中表达式的输出

    int i 9 System out println i i 执行输出 17i 的最终值为 9 但是根据java中的结合性和优先级规则 i应该首先执行 即从右到左 给出10 然后 i给出9 将两者相加 答案应该是19 至于我知道这样的代码在
  • 在 OpenGL 着色器中检测 NaN 的最佳方法

    今天早上我遇到了一个似乎神秘的错误 我很幸运能够很快找到解决方案 我除以计数器以生成片段着色器内部的平均值 当然 当计数器为零时 所得的颜色值变为 NaN 在混合过程中 NVidia 优雅地将 NaN 视为 0 值 但 Intel 没有这样
  • 调试断言失败 OpenCv is_block_type_valid(header->_block_use)

    我是使用 Visual Studio 和 openCv 编程的新手 我编写了一个简单的程序来显示图像的红色通道 但每次运行代码时都会抛出 DEBUG ASSERTION FAILED 错误 include
  • jqGrid 复选框列

    我有一个相当复杂的网格 有两列格式化为复选框 这些列定义如下 name Alert A index Alert A width 22 align center sortable false formatter CheckBoxFormatt
  • 无法将简单的无符号字节 RGB 纹理映射到四边形:

    我有一个非常简单的程序 将虚拟红色纹理映射到四边形 下面是 C 中的纹理定义 struct DummyRGB8Texture2d uint8 t data 3 4 int width int height DummyRGB8Texture2