繁体   English   中英

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

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

我对此感到非常困惑。 我正在尝试渲染到屏幕外的纹理,以便可以执行一些后处理,但是甚至无法将该纹理未经修改地绘制到屏幕上。 我目前的目标是在iPhone模拟器上使用OpenGL ES 2.0。

我将问题缩小为返回vec4(0,0,0,1)的GLSL的texture2D()函数,因为如果用任何恒定颜色替换该调用,则屏幕将填充指定的颜色。 创建纹理并将其绑定到纹理单元0,分配其存储空间,将其最小滤镜和mag滤镜设置为NEAREST,并将sampler2D统一设置为0。

我尝试删除所有渲染到纹理的代码并显式初始化其数据,并且得到相同的结果,并且如果直接定位到屏幕帧缓冲区,则可以得到期望的图像,因此我非常有信心纹理的数据是所有这些都是在我尝试从中采样时定义的。

我尝试确保纹理在被渲染时没有绑定到任何纹理单元,但这没有任何区别。

我也尝试过glEnable(GL_TEXTURE_2D),但给我的印象是ES 2.0不再重要。 无论如何都没有帮助。

我实际上是在围绕OpenGL ES 2.0使用我自己的瘦C ++包装器库,但是如果您对OpenGL ES 2.0了如指掌,无论如何,这段代码中发生的事情都应该清楚。 我对代码不是纯OpenGL表示歉意; 我的下一个调试步骤是在没有包装器库的情况下重新编写代码。 我只是想知道我是否正在犯任何突然跳出的骨头错误。

但是,在最后一次drawArrays调用之前,我为我设置的所有状态变量添加了普通的OpenGL glGet *()查询,并且一切都按预期设置。

代码中唯一不是非常明显的部分是Smart <>对象。 他们只是包装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);
}

您可以在此处查看如何实现我的包装器库: https : //github.com/jbat-es/tsgl2

编辑:

好的,我在纯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);
}

纹理环绕模式默认为GL_REPEAT,该模式仅支持2幂幂纹理。 只需添加

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

解决问题。

暂无
暂无

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

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