简体   繁体   English

GLSL texture2D()始终返回(0,0,0,1)

[英]GLSL texture2D() always returns (0, 0, 0, 1)

I'm super-baffled by this. 我对此感到非常困惑。 I'm trying to render to an off-screen texture so I can perform some post-processing, but can't even get that texture to draw to the screen unmodified. 我正在尝试渲染到屏幕外的纹理,以便可以执行一些后处理,但是甚至无法将该纹理未经修改地绘制到屏幕上。 I'm currently targeting OpenGL ES 2.0 on the iPhone simulator. 我目前的目标是在iPhone模拟器上使用OpenGL ES 2.0。

I've narrowed down the problem to GLSL's texture2D() function returning vec4(0, 0, 0, 1) since, if I replace that call with any a constant color, the screen fills with the specified color. 我将问题缩小为返回vec4(0,0,0,1)的GLSL的texture2D()函数,因为如果用任何恒定颜色替换该调用,则屏幕将填充指定的颜色。 The texture is created, bound to texture unit 0, its storage is allocated, its min and mag filters set to NEAREST, and the sampler2D uniform is set to 0. 创建纹理并将其绑定到纹理单元0,分配其存储空间,将其最小滤镜和mag滤镜设置为NEAREST,并将sampler2D统一设置为0。

I've tried removing all the render-to-texture code and initializing its data explicitly and I get the same result, and if target the screen framebuffer directly, I get the image I expect, so I'm fairly confident the texture's data is all defined by the time I try to sample from it. 我尝试删除所有渲染到纹理的代码并显式初始化其数据,并且得到相同的结果,并且如果直接定位到屏幕帧缓冲区,则可以得到期望的图像,因此我非常有信心纹理的数据是所有这些都是在我尝试从中采样时定义的。

I've tried making sure my texture isn't bound to any texture unit while it's being rendered to, but that didn't make a difference. 我尝试确保纹理在被渲染时没有绑定到任何纹理单元,但这没有任何区别。

I've also tried glEnable(GL_TEXTURE_2D) but I was under the impression that doesn't matter for ES 2.0 anymore. 我也尝试过glEnable(GL_TEXTURE_2D),但给我的印象是ES 2.0不再重要。 It didn't help anyway. 无论如何都没有帮助。

I'm actually using my own thin C++ wrapper library around OpenGL ES 2.0, but if you know OpenGL ES 2.0 well, what's happening in this code should be clear regardless. 我实际上是在围绕OpenGL ES 2.0使用我自己的瘦C ++包装器库,但是如果您对OpenGL ES 2.0了如指掌,无论如何,这段代码中发生的事情都应该清楚。 I apologize for the code not being plain OpenGL; 我对代码不是纯OpenGL表示歉意; my next debugging step is to re-write the code without my wrapper library. 我的下一个调试步骤是在没有包装器库的情况下重新编写代码。 I was just wondering if I'm making any bonehead mistakes that jump out anyway. 我只是想知道我是否正在犯任何突然跳出的骨头错误。

I have, however, added plain OpenGL glGet*() queries before the last drawArrays call for all the state variables I set, and everything gets set as expected. 但是,在最后一次drawArrays调用之前,我为我设置的所有状态变量添加了普通的OpenGL glGet *()查询,并且一切都按预期设置。

The only not-super-obvious part of the code are the Smart<> objects. 代码中唯一不是非常明显的部分是Smart <>对象。 They simply wrap GL object references and reference arrays and call their associated glDelete*() in their destructors. 他们只是包装GL对象引用和引用数组,并在其析构函数中调用其关联的glDelete *()。

#include <tsvl/vec.hpp>
using namespace tsvl;

#include <tsgl2/Context.hpp>
#include <tsgl2/Smart.hpp>
using namespace tsgl2;

#include <array>
#include <exception>
#include <string>
using namespace std;

#define SHADER_SOURCE(text) "#version 100\n" #text


namespace {

const AttributeLocation vertexPositionAttributeLocation(0);

const string vec2PassthroughVertexShaderSource = SHADER_SOURCE(
  attribute vec2 vertexPosition;
  void main() {
    gl_Position = vec4(vertexPosition, 0, 1);
  }
);

const string greenFragmentShaderSource = SHADER_SOURCE(
  void main() {
    gl_FragColor = vec4(0, 1, 0, 1);
  }
);

const string combineTexturesFragmentShaderSource = SHADER_SOURCE(
  precision highp float;

  uniform vec2 screenSize;
  uniform sampler2D samplers[1];

  void main() {
    vec2 texCoord = gl_FragCoord.xy / screenSize;
    gl_FragColor = texture2D(samplers[0], texCoord);
  }
);

const vec2 vertices[] = {
  vec2(-0.9f, -0.9f),
  vec2( 0.9f, -0.9f),
  vec2( 0.0f,  0.9f),
};
const int vertexCount = sizeof(vertices) / sizeof(vertices[0]);

const vec2 screenCorners[] = {
  vec2(-1.0f, -1.0f),
  vec2( 1.0f, -1.0f),
  vec2( 1.0f,  1.0f),
  vec2(-1.0f,  1.0f),
};
const int screenCornerCount = sizeof(screenCorners) / sizeof(screenCorners[0]);

} // unnamed namespace


void drawDemoScene(int screenWidth, int screenHeight) {
  FramebufferRef screenFramebuffer = Framebuffer::currentBinding();

  //

  Smart<array<TextureRef, 8>> renderTextures(Context::genTextures<8>());
  Smart<array<FramebufferRef, 8>> renderFramebuffers(Context::genFramebuffers<8>());

  Context::setActiveTextureUnit(TextureUnit(0)); // My wrapper translates this to GL_TEXTURE0
  Texture2D::bind(renderTextures.get()[0]);
  Texture2D::setStorage(TextureFormat::RGBA8, IntRect::Size(screenWidth, screenHeight));
  Texture2D::setMinificationFilter(TextureMinificationFilter::NEAREST);
  Texture2D::setMagnificationFilter(TextureMagnificationFilter::NEAREST);

  Framebuffer::bind(renderFramebuffers.get()[0]);
  Framebuffer::ColorAttachment::set(renderTextures.get()[0], FramebufferTextureTarget::TEXTURE_2D);
  if (Framebuffer::status() != FramebufferStatus::COMPLETE)
    throw exception();

  //

  vertexPositionAttributeLocation.enableAttributeArray();

  Smart<ShaderRef> vec2PassthroughVertexShader(Context::createShader(ShaderType::VERTEX));
  vec2PassthroughVertexShader->setSource(vec2PassthroughVertexShaderSource);
  vec2PassthroughVertexShader->compile();
  if (!vec2PassthroughVertexShader->compileWasSuccessful())
    throw exception();

  Smart<ShaderRef> greenFragmentShader(Context::createShader(ShaderType::FRAGMENT));
  greenFragmentShader->setSource(greenFragmentShaderSource);
  greenFragmentShader->compile();
  if (!greenFragmentShader->compileWasSuccessful())
    throw exception();

  Smart<ShaderRef> combineTexturesFragmentShader(Context::createShader(ShaderType::FRAGMENT));
  combineTexturesFragmentShader->setSource(combineTexturesFragmentShaderSource);
  combineTexturesFragmentShader->compile();
  if (!combineTexturesFragmentShader->compileWasSuccessful())
    throw exception();

  Smart<ProgramRef> vec2PassthroughGreenProgram(Context::createProgram());
  vec2PassthroughGreenProgram->attach(*vec2PassthroughVertexShader);
  vec2PassthroughGreenProgram->attach(*greenFragmentShader);
  vec2PassthroughGreenProgram->bindAttributeToLocation(
      "vertexPosition", vertexPositionAttributeLocation);
  vec2PassthroughGreenProgram->link();
  vec2PassthroughGreenProgram->validate();
  if (!vec2PassthroughGreenProgram->validationWasSuccessful())
    throw exception();

  Smart<ProgramRef> combineTexturesProgram(Context::createProgram());
  combineTexturesProgram->attach(*vec2PassthroughVertexShader);
  combineTexturesProgram->attach(*combineTexturesFragmentShader);
  combineTexturesProgram->bindAttributeToLocation(
      "vertexPosition", vertexPositionAttributeLocation);
  combineTexturesProgram->link();
  combineTexturesProgram->validate();
  if (!combineTexturesProgram->validationWasSuccessful())
    throw exception();

  UniformLocation screenSizeUniformLocation =
      combineTexturesProgram->locationOfUniform("screenSize");
  UniformLocation samplersUniformLocation =
      combineTexturesProgram->locationOfUniform("samplers");

  //

  Context::setColorClearValue(0.0f, 0.0f, 0.0f, 0.0f);
  Context::setLineWidth(2.0f);
  Context::setViewport(IntRect(0, 0, screenWidth, screenHeight));
  Context::useProgram(*vec2PassthroughGreenProgram);

  Framebuffer::bind(renderFramebuffers.get()[0]);

  vertexPositionAttributeLocation.setAttributeArrayPointerAndStride(
      DONT_NORMALIZE, 2, AttributeLocation::ArrayDataType::FLOAT, vertices, 0);

  Context::clear(CLEAR_COLOR_BUFFER);
  Context::drawArrays(DrawMode::LINE_LOOP, 0, vertexCount);

  //

  Context::enableBlending();
  Context::setBlendFuncs(SourceBlendFunc::SRC_ALPHA, DestBlendFunc::ONE_MINUS_SRC_ALPHA);
  Context::setColorClearValue(1.0f, 1.0f, 1.0f, 1.0f);
  Context::setViewport(IntRect(0, 0, screenWidth, screenHeight));
  Context::useProgram(*combineTexturesProgram);

  Framebuffer::bind(screenFramebuffer);

  vertexPositionAttributeLocation.setAttributeArrayPointerAndStride(
      DONT_NORMALIZE, 2, AttributeLocation::ArrayDataType::FLOAT, screenCorners, 0);

  screenSizeUniformLocation.setUniformValue(vec2(screenWidth, screenHeight));
  samplersUniformLocation.setUniformValue(TextureUnit(0)); // Even though setActiveTextureUnit()
                                                           // translated this to GL_TEXTURE0
                                                           // It stays plain int 0 here.

  Context::clear(CLEAR_COLOR_BUFFER);
  Context::drawArrays(DrawMode::TRIANGLE_FAN, 0, screenCornerCount);
}

You can see how my wrapper library is implemented here: https://github.com/jbat-es/tsgl2 您可以在此处查看如何实现我的包装器库: https : //github.com/jbat-es/tsgl2

EDIT: 编辑:

Okay, I wrote a very stripped down version in plain OpenGL and it has the same problem: 好的,我在纯OpenGL中编写了一个非常精简的版本,它具有相同的问题:

void drawDemoScenePlainGL(int screenWidth, int screenHeight) {
  GLuint texture;
  glGenTextures(1, &texture);

  glBindTexture(GL_TEXTURE_2D, texture);
  int data[320][460];
  memset(data, 0xFF, 320*460*sizeof(int));
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screenWidth, screenHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glBindTexture(GL_TEXTURE_2D, 0);

  //

  glEnableVertexAttribArray(0);

  GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
  const char* source = vec2PassthroughVertexShaderSource.c_str();
  int sourceLength = vec2PassthroughVertexShaderSource.length();
  glShaderSource(vertexShader, 1, &source, &sourceLength);
  glCompileShader(vertexShader);

  GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
  source = combineTexturesFragmentShaderSource.c_str();
  sourceLength = combineTexturesFragmentShaderSource.length();
  glShaderSource(fragmentShader, 1, &source, &sourceLength);
  glCompileShader(fragmentShader);

  GLuint program = glCreateProgram();
  glAttachShader(program, vertexShader);
  glAttachShader(program, fragmentShader);
  glBindAttribLocation(program, 0, "vertexPosition");
  glLinkProgram(program);

  GLuint screenSizeUniformLocation = glGetUniformLocation(program, "screenSize");
  GLuint samplersUniformLocation = glGetUniformLocation(program, "samplers");

  //

  glClearColor(1, 1, 1, 1);
  glUseProgram(program);
  glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, screenCorners);
  glViewport(0, 0, screenWidth, screenHeight);

  glActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_2D, texture);

  glUniform2f(screenSizeUniformLocation, screenWidth, screenHeight);
  glUniform1i(samplersUniformLocation, 0);

  glClear(GL_COLOR_BUFFER_BIT);
  glDrawArrays(GL_TRIANGLE_FAN, 0, screenCornerCount);
}

The texture wrap modes default to GL_REPEAT which only support power-of-two textures. 纹理环绕模式默认为GL_REPEAT,该模式仅支持2幂幂纹理。 Simply adding 只需添加

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

Solves the problem. 解决问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM