【问题标题】:How to pass float array to texture in openGL ES?如何在openGL ES中将浮点数组传递给纹理?
【发布时间】:2016-12-12 19:14:15
【问题描述】:

我正在尝试在 iOS 设备上进行一些 GPGPU 编程,但我找不到任何有关如何设置 openGL ES 3.0 环境的资源。我了解如何在片段着色器中进行计算,但我无法将浮点数组传递给片段着色器的统一采样器变量。

这就是我设置 FBO 和分配 CPU 内存的方式:

float** dens = (float**) malloc(W*sizeof(float*));
for (int i = 0; i < W; i++) {
    dens[i] = (float *)malloc(H*sizeof(float));
}

// input value
for (int i = 0; i < W; i++) {
    for (int j = 0; j < H; j++) {
        dens[i][j] = 1.0f;
    }
}

GLuint FBO;
glGenFramebuffers(1, &FBO);
glBindFramebuffer(GL_FRAMEBUFFER, FBO);

GLuint dens_gl = load_texture(W, H, GL_RGBA, 0, dens);

glBindFramebuffer(GL_FRAMEBUFFER, 0);

这是我的 load_texture 代码:

GLuint load_texture(const GLsizei width, const GLsizei height, const GLenum type, int tex_number, const float** data) {

GLuint texture_object_id;
glGenTextures(1, &texture_object_id);
assert(texture_object_id != 0);
glActiveTexture(GL_TEXTURE0 + tex_number);
glBindTexture(GL_TEXTURE_2D, texture_object_id);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexImage2D(GL_TEXTURE_2D, 0, type, width, height, 0, type, GL_UNSIGNED_BYTE, data);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + tex_number, GL_TEXTURE_2D, texture_object_id, 0);

if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
    NSLog(@"failed to make complete framebuffer objects %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
}

glBindTexture(GL_TEXTURE_2D, 0);

return texture_object_id;
}

还有我的fragmentsshader.fsh:

uniform vec2 uResolution;
uniform vec2 aPosition;
uniform sampler2D dens_gl;

void main(void) {
vec2 uv = aPosition.xy / uResolution.xy;
gl_FragColor = texture2D(dens_gl, uv);
}

没有错误代码,但我只能看到黑屏,由于我在 CPU 内存中将值设置为 1,因此我们期待白屏。我哪里做错了?

【问题讨论】:

  • 你想做什么?您显示了帧缓冲区的设置代码,但问题似乎是关于如何使纹理工作。这两件事彼此无关。
  • @BDL 我正在尝试将 CPU 浮点数组数据输入到我的片段着色器,但我的设置不起作用。我展示了我的 FBO 代码,因为当我尝试将内部格式更改为 GL_R32F、格式为 GL_RED 并键入 GL_FLOAT 时,它给了我 GL_INCOMPLETE_ATTACHMENT。上面的代码没有任何错误,但我的 iOS 设备上仍然出现黑屏。

标签: ios c opengl-es shader


【解决方案1】:

纹理是一个二维数组(即一个连续的列和行内存块)。您正在上传一维数组的列表,这些数组分散存储在内存中,因为它们都是单独动态分配的。不知道您实际上要在此处上传什么,但幸运的是它不会崩溃。

您尝试上传的 RGBA8 纹理存储 4 个单独的字节值,每个 texel 介于 0 和 255 之间(一个用于红色,一个用于蓝色等)。您正在尝试上传每个像素的浮点数,因此数据格式完全错误。

你的“位置”制服对于每个像素都是不变的,所以每个像素都会从同一个纹理坐标向上查找,这可能不是你想要的。您需要将纹理坐标作为每个顶点变化的值上传。

老实说,这里有很多基本错误 - 我建议从 iOS 的基本“纹理三角形”教程开始,网上有很多。

【讨论】:

  • 对不起,我没有解释,但我已将位置设置为属性变量,但我忘了显示它。这是在我的 c 文件中: _aPosition = glGetAttribLocation(_program, "aPosition");在我的 vsh 中。 : 属性 vec2 aPosition; void main(void) { gl_Position = vec4(aPosition, 0., 1.);我还将 CPU 输入数据更改为 malloc(WHsizeof(float)),内部格式更改为 GL_R32F,格式更改为 GL_RED 并键入 GL_FLOAT。但是我仍然收到 GL_INCOMPLETE_ATTACHMENT 错误。您对如何解决此问题有任何建议吗?非常感谢您的回复!
  • 浮点渲染目标不是核心 ES 3.0 规范的一部分,因此您使用的 GPU 可能不支持这一点。
  • 请注意,您的问题仅涉及纹理,但也花费了很多精力来设置渲染目标-两者不是一回事。您可以读取浮点纹理(这是 ES3.0 中的核心),而不是 FBO 的一部分;你就是不能渲染成一个。
  • 感谢您的 cmets。我现在已经设法解决了这个问题。我犯了一个愚蠢的错误,将 CPU 内存设置为 1 个通道,而不是 4 个。我使用 malloc(4*WHsizeof(float)) 进行了修复。现在使用您建议的格式不会出错。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-20
  • 1970-01-01
  • 2018-08-29
  • 1970-01-01
相关资源
最近更新 更多