【问题标题】:Texture Array access not working Opengl 3.3, GLSL 330纹理数组访问不起作用 Opengl 3.3,GLSL 330
【发布时间】:2014-10-29 13:31:35
【问题描述】:

我正在尝试使用 2D 纹理数组作为纹理图集。我有以下代码来渲染一个正方形。如果我用简单的颜色输出替换片段着色器中的纹理查找,则正方形会渲染,如果我使用并设置简单的 2D 纹理而不是 2d 纹理数组,它会正确渲染其中一个纹理。但是,当尝试创建和使用 2d 纹理数组时,我只是得到一个黑屏。什么给了?

//Shader Sources
const GLchar* vertexsource =
    "#version 330\n"
    "in vec2 position;"
    "in vec2 texcoord;"
    "out vec2 f_texcoord;"
    "void main() {"
    "   gl_Position = vec4(position, 0.0, 1.0);"
    "   f_texcoord = texcoord;"
    "}";
const GLchar* fragmentsource =
    "#version 330\n"
    "in vec2 f_texcoord;"
    "out vec4 color;"
    "uniform float time;"
    "uniform sampler2DArray sample;"
    "void main() {"
    "   float layer = step(sin(time), 0.0);"
    "   color = texture(sample, vec3(f_texcoord, 0.0));\n"
    "   //color = vec4(1.0,1.0,1.0,1.0);\n"
    "}";

//Vertex Data
GLfloat vertices[] = {
    //Verts         Texture verts
    -0.5f, 0.5f,    0.0f, 0.0f,
    0.5f, 0.5f,     1.0f, 0.0f,
    0.5f, -0.5f,    1.0f, 1.0f,
    -0.5f, -0.5f,   0.0f, 1.0f
};

GLuint elements[] = {
    0, 1, 2,
    2, 3, 0
};

Shaders::SetLogger(log_);
VertexShader vertexshader("D3 Vertex Shader", vertexsource);
FragmentShader fragshader("D3 Frag Shader", fragmentsource);
program = new ShaderProgram("D3 Shader Program");
program->AttachShader(vertexshader);
program->AttachShader(fragshader);
program->LinkProgram();
glUseProgram(program->glIdentifier());

GLint posattrib = program->GetAttributeLocation("position");
GLint texattrib = program->GetAttributeLocation("texcoord");
//Dont actually need this because only one Texture unit in use
GLint coloruniform = program->GetUniformLocation("sample");

GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

GLuint ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);

glEnableVertexAttribArray(posattrib);
glVertexAttribPointer(posattrib, 2, GL_FLOAT, GL_FALSE,
                      4 * sizeof(GLfloat),
                      (GLvoid*)0);

glEnableVertexAttribArray(texattrib);
glVertexAttribPointer(texattrib, 2, GL_FLOAT, GL_FALSE,
                      4 * sizeof(GLfloat),
                      (GLvoid*)(2 * sizeof(GLfloat)));

//glUniform1i(coloruniform, 0);

int width, height;
unsigned char* image = SOIL_load_image("sample.png", &width, &height,
                                       0, SOIL_LOAD_RGBA);

int width2, height2;
unsigned char* image2 = SOIL_load_image("sample2.png", &width2, &height2,
                                       0, SOIL_LOAD_RGBA);
errorstream << glGetError() << " ";

glActiveTexture(GL_TEXTURE0);
GLuint texture;
glGenTextures(1, &texture);
errorstream << glGetError() << " ";
glBindTexture(GL_TEXTURE_2D_ARRAY, texture);    
errorstream << glGetError() << " ";

glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 
             width, height, 2,
             0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)0);
errorstream << glGetError() << " ";
log_->Debug("Requested memory for texture");


glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 
                0, 0, 0, 
                width, height, 1,
                GL_RGBA, GL_UNSIGNED_BYTE, image);
errorstream << glGetError() << " ";
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 
                0, 0, 1, 
                width2, height2, 1, 
                GL_RGBA, GL_UNSIGNED_BYTE, image2);
errorstream << glGetError() << " ";


glUniform1i(coloruniform, 0);
errorstream << glGetError() << " ";
log_->Debug(errorstream.str());

以及实际绘制代码:

GLint timeuniform = program->GetUniformLocation("time");
GLint sampleuniform = program->GetUniformLocation("sample");
glActiveTexture(GL_TEXTURE0);
glUniform1f(timeuniform, frametimer_.RunningTime().asSeconds());
glUniform1i(sampleuniform, 0);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
window_->display();

编辑:在 jozxyqk 建议的更改中进行了编辑

【问题讨论】:

    标签: opengl glsl opengl-3


    【解决方案1】:

    [编辑] 可能的原因:

    • 纹理/采样器未正确绑定(见下文)。

    • 纹理为incomplete(另见this)。

      常见的问题是 GL 默认需要 mipmap(并且大多数教程/示例代码开始时都没有 mipmap)。一个简单的解决方法是:
      glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

      详情请见GL4.5 specs, sec 8.17 "Texture Completeness "

      如果所有的纹理图像和纹理参数,则称一个纹理是完整的 使用纹理进行纹理应用所需的定义是一致的。

      ...

      使用前面的定义,除非满足以下条件之一,否则纹理是完整的:

      • 缩小过滤器需要 mipmap(既不是 NEAREST 也不是 LINEAR),并且纹理不是完整的 mipmap。
    • 纹理坐标错误(例如,全为零且第一个纹素恰好是黑色)。通过使用像素颜色的坐标可以轻松验证。

    • 以上工作正常,图像中的数据只是黑色。

    要绑定纹理,

    • 致电glActiveTexture,使用GL_TEXTURE0 + texIndex

      这在设置过程中不是必需的,但会在绘制之前选择要绑定到的纹理单元。

      https://www.opengl.org/sdk/docs/man/docbook4/xhtml/glActiveTexture.xml

    • 致电glBindTexture

      这应该是之后 glActiveTexture (a related post on opengl.org)

    • 设置采样器制服glUniform1i(samplerLocation, texIndex)←主要问题,我认为

      texIndex0 代表 GL_TEXTURE01 代表 GL_TEXTURE1 等等。使用 GL_TEXTURE0 + texIndex 是一个方便的快捷方式。

      您的代码使用GL_TEXTURE0 而不是索引,即0x84C033984

    【讨论】:

    • 嗯,我做了这些改变,仍然没有运气。
    • @SamCoulter 在绘图代码中glActiveTexture 之后也应该有一个绑定调用,但是该状态应该在设置代码中保持活动状态。现在要尝试的一些调试操作可能是:color = vec4(f_texcoord,0,1); 检查坐标是否正常,将所有 255 写入 image 以检查加载是否正常。哦,一定要set GL_TEXTURE_MIN_FILTER not to use mipmaps(实际上,先做这个)。
    • GL_TEXTURE_MIN_FILTER 修复成功,你是救生员。编辑:您能否链接任何可能解释为什么会修复它的资源?
    猜你喜欢
    • 1970-01-01
    • 2021-01-05
    • 1970-01-01
    • 1970-01-01
    • 2014-05-05
    • 2013-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多