OpenGL4 gl_texture_2d_array 不会显示

OpenGL4 gl_texture_2d_array won't display

我想开始使用现代 OpenGL,同时通过使用大小为 1280x1280x2 的二维数组纹理对元胞自动机进行编码并计算计算着色器中另一层的下一个状态来阅读这本精湛的书。这个想法是从 glumpy examples.

偷来的

然而,虽然有这样的雄心壮志,但我什至在尝试显示它时都感到困惑,甚至没有将采样器传递到着色器中。

下面我包括了工作正常的生成器和确实包含问题的代码段。

一代

#!/usr/bin/env perl

use strict;
use warnings;


sub get_arg {
    return (scalar @ARGV == 0) ? shift : shift @ARGV;
}

my $size = get_arg 1280;
my $rate = get_arg ($size >> 1);

my $symbol = (sub { ((shift) < $rate) ? '*' : '_' } );

print "$size\n";
for (0..$size) {
    print $symbol->(int(rand() * $size)) for (0..$size);
    print "\n";
}

代码

#include <stdio.h>
#include <stdbool.h>
#include <assert.h>


// including opengl libraries on linux/osx

//include glew
#include <GL/glew.h>

//include opengl
#if defined (__APPLE_CC__)
    #include <OpenGL/gl3.h>
#else
    #include <GL/gl3.h>       /* assert OpenGL 3.2 core profile available. */
#endif

//include glfw3
#define GLFW_INCLUDE_GL3  /* don't drag in legacy GL headers. */
#define GLFW_NO_GLU       /* don't drag in the old GLU lib - unless you must. */
#include <GLFW/glfw3.h>

// ----------- the program itself

GLFWwindow *g_window;

#define SIZE 1280
#define WIDTH SIZE
#define HEIGHT SIZE
#define DEPTH 2


init_glfw(const char *name) {
    // start GL context and O/S window using the GLFW helper library
    assert(glfwInit());

#if defined(__APPLE_CC__)
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#endif
    g_window = glfwCreateWindow(WIDTH, HEIGHT, name, NULL, NULL);
    assert(g_window != NULL);
    glfwMakeContextCurrent(g_window);

    // start GLEW extension handler
    glewExperimental = GL_TRUE;
    glewInit();

    // tell GL to only draw onto a pixel if the shape is closer to the viewer
    glEnable(GL_DEPTH_TEST); // enable depth-testing
    glDepthFunc(GL_LESS); // depth-testing interprets a smaller value as "closer"
    glEnable(GL_DEBUG_OUTPUT);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}


typedef enum { FILLED = '*', EMPTY = '_' } SYMBOL;
load_array(GLubyte array[SIZE * SIZE * DEPTH], FILE *stream) {
    static char c;
    for(int i = 0; i < SIZE; ++i) {
        for(int j = 0; j < SIZE; ++j) {
            bool approved = false;
            GLubyte *it = &array[SIZE * i + j];
            while(!approved) {
                approved = true;
                c = getc(stream);
                assert(c != EOF);
                switch(c) {
                    case FILLED:
                        *it = 0x00;
                    break;
                    case EMPTY:
                        *it = 0xff;
                    break;
                    default:
                        approved = false;
                    break;
                }
            }
            assert(*it == 0x00 || *it == 0xff);
            it[SIZE * SIZE] = it[0];
        }
    }
}


GLuint create_2d_texture() {
    static GLuint texture = 0;
    assert(texture == 0);

    static GLubyte field[SIZE * SIZE << 1];
    load_array(field, stdin);

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
    glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_ALPHA8, SIZE, SIZE, DEPTH);
    glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, SIZE, SIZE, DEPTH, GL_ALPHA, GL_UNSIGNED_BYTE, field);

    glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);

    return texture;
}


display() {
    GLuint texture = create_2d_texture();
    assert(texture != 0);
    glEnable(GL_CULL_FACE);
    glCullFace(GL_FRONT_AND_BACK);

    while(!glfwWindowShouldClose(g_window)) {
        glClearColor(1.0, 1.0, 1.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glLoadIdentity();
        glMatrixMode(GL_PROJECTION);
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
        glPushMatrix();
        glEnable(GL_TEXTURE_2D_ARRAY);
        glBegin(GL_QUADS);
            glTexCoord3s(0, SIZE, 0);    glVertex3f( 0.0f, 0.0f, 0.0 );
            glTexCoord3s(SIZE, SIZE, 0); glVertex3f( SIZE, 0.0f, 0.0 );
            glTexCoord3s(0, SIZE, 0);    glVertex3f( SIZE, SIZE, 0.0 );
            glTexCoord3s(0, 0, 0);       glVertex3f( 0.0f, SIZE, 0.0 );
        glEnd();
        glPopMatrix();

        glfwSwapBuffers(g_window);
        glfwPollEvents();
        if(glfwGetKey(g_window, GLFW_KEY_ESCAPE)) {
            glfwSetWindowShouldClose(g_window, 1);
        }
    }
}


main() {
    init_glfw("I want to display a texture");
    display();
    glfwDestroyWindow(g_window);
    glfwTerminate();
}

你能帮我分析一下在屏幕上显示二维数组的问题吗?我想要实现的是使整个 window 随机黑白,但到目前为止我只是从 google 解决方案和手册页中添加更多层而完全困惑。

我不是要一个工作代码,只是一个可以帮助我解决这个问题的易于理解的解释。

glEnable(GL_TEXTURE_2D_ARRAY);

这给了你一个 OpenGL 错误。即使在兼容性配置文件中,您也无法启用任何类型的阵列纹理。为什么?

因为您根本无法使用 array textures 的固定功能处理。您不能使用 glTexEnv 从数组纹理中获取。它们完全是基于着色器的构造。

所以如果你想使用数组纹理,你必须使用着色器。