GLSL texture2D()始终返回(0,0,0,1) [英] GLSL texture2D() always returns (0, 0, 0, 1)

查看:134
本文介绍了GLSL texture2D()始终返回(0,0,0,1)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

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

我尝试删除所有渲染到纹理的代码并显式初始化其数据,并且得到相同的结果,如果直接定位屏幕帧缓冲区,则可以得到期望的图像,因此我非常有信心纹理的数据全部由我尝试对其进行采样的时间定义.

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.

我也尝试过glEnable(GL_TEXTURE_2D),但我的印象是,不再对ES 2.0有意义.无论如何都无济于事.

I've also tried glEnable(GL_TEXTURE_2D) but I was under the impression that doesn't matter for ES 2.0 anymore. It didn't help anyway.

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

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. I apologize for the code not being plain 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.

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

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.

代码中唯一不是非常明显的部分是Smart <>对象.他们只包装GL对象引用和引用数组,并在其析构函数中调用其关联的glDelete *().

The only not-super-obvious part of the code are the Smart<> objects. They simply wrap GL object references and reference arrays and call their associated glDelete*() in their destructors.

#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

You can see how my wrapper library is implemented here: https://github.com/jbat-es/tsgl2

好吧,我用普通的OpenGL写了一个精简的版本,它有同样的问题:

Okay, I wrote a very stripped down version in plain OpenGL and it has the same problem:

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,仅支持二次幂纹理.只需添加

The texture wrap modes default to GL_REPEAT which only support power-of-two textures. 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);

解决问题.

这篇关于GLSL texture2D()始终返回(0,0,0,1)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆