使用D语言在OpenGL 3中渲染简单的矩形

12

我正在为无法在我的屏幕上显示一组简单的三角形而发疯。

我正在使用OpenGL3(没有过时的固定管道),使用D编程语言的derelict绑定。

您能否发现以下程序中的错误?它可以编译,不会抛出任何OpenGL / GLSL错误,但只显示一个带有我设置的清除颜色的空白屏幕。

import std.string;
import std.conv;
import derelict.opengl3.gl3;
import derelict.sdl2.sdl2;

immutable string minimalVertexShader = `
#version 120
attribute vec2 position;
void main(void)
{
    gl_Position = vec4(position, 0, 1);
}
`;

immutable string minimalFragmentShader = `
#version 120
void main(void)
{
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

void main() {
    DerelictSDL2.load();
    DerelictGL3.load();

    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        throw new Exception("Failed to initialize SDL: " ~ to!string(SDL_GetError()));
    }

    // Set OpenGL version
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);

    // Set OpenGL attributes
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

    auto sdlwindow = SDL_CreateWindow("D App",
        SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);

    if (!sdlwindow)
        throw new Exception("Failed to create a SDL window: " ~ to!string(SDL_GetError()));

    SDL_GL_CreateContext(sdlwindow);
    DerelictGL3.reload();

    float[] vertices = [ -1, -1,  1, -1,  -1, 1,  1, 1];
    ushort[] indices = [0, 1, 2, 3];
    uint vbo, ibo;
    // Create VBO
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, vertices.sizeof, vertices.ptr, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    // Create IBO
    glGenBuffers(1, &ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.sizeof, indices.ptr, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    // Program
    auto program = glCreateProgram();
    // Vertex Shader
    auto vsh = glCreateShader(GL_VERTEX_SHADER);
    auto vshSrc = minimalVertexShader.toStringz;
    glShaderSource(vsh, 1, &vshSrc, null);
    glCompileShader(vsh);
    glAttachShader(program, vsh);
    // Fragment Shader
    auto fsh = glCreateShader(GL_FRAGMENT_SHADER);
    auto fshSrc = minimalFragmentShader.toStringz;
    glShaderSource(fsh, 1, &fshSrc, null);
    glCompileShader(fsh);
    glAttachShader(program, fsh);

    glLinkProgram(program);
    glUseProgram(program);

    auto position = glGetAttribLocation(program, "position");
    auto run = true;

    while (run) {
        SDL_Event event;
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
                case SDL_QUIT:
                    run = false;
                default:
                    break;
            }
        }

        glClearColor(1, 0.9, 0.8, 1);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glEnableVertexAttribArray(position);
        glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, vertices.sizeof, null);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
        glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, null);
        glDisableVertexAttribArray(position);

        SDL_GL_SwapWindow(sdlwindow);
    }
}

1
我不能立刻告诉你问题出在哪里,但如果你使用glGetError()来检查OpenGL错误,几乎肯定会有所帮助。请参考std.exception中的enforce函数以及它如何使用惰性参数--你可以将其调整为enforceGL()函数,以便更容易地捕获OpenGL错误。 - Justin W
我写了一个版本的这段代码,在其中每个GL调用都加上了assert(glGetError() == 0);的检查语句…… 没有出现任何错误。 - Santiago V.
你为什么要重新加载Derelict? :o - Jeroen
嗨Jeroen,我正在重新加载Derelict以创建GL3上下文。显然这是做的方法。 - Santiago V.
1个回答

14

在这一行上:

glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, vertices.sizeof, null);

你确定要使用值为16的 vertices.sizeof 吗?在 D 语言中,动态数组是一个具有两个成员 (ptrlength) 的结构体。你可能想要使用 float.sizeoffloat.sizeof * 2

对于你的 BufferData 调用同样适用。


谢谢您的回答!我将声明更改为静态数组(我认为它们由文字定义,所以它们将是静态的),现在vertices的.sizeof为32(长度* float.sizeof),而indices为8。但是仍然无法绘制任何内容。 :( - Santiago V.
1
哦,等等,你太棒了。我在glBufferData调用中用vertices.length * float.sizeof替换了vertices.sizeof,并且在indices中也是一样的。但是在glVertexAttribPointer中,我需要使用2 * float.sizeof作为步长参数。它起作用了!谢谢! - Santiago V.
@SantiagoV。嗨,我能够使用您的示例帮助我入门(不使用sdl)。我知道这很旧,但当我这样做时,我只是得到了一个有颜色的窗口...好像三角形比窗口大得多。对此有什么想法吗? - AbstractDissonance
@AbstractDissonance 抱歉,没有看到你的问题...从我代码中所看到的,没有投影或视图矩阵,所以很可能是矩形是窗口的大小。 - Santiago V.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接