用 D 语言用 OpenGL 3 渲染一个简单的矩形
Posted
技术标签:
【中文标题】用 D 语言用 OpenGL 3 渲染一个简单的矩形【英文标题】:Rendering a simple rectangle with OpenGL 3 in D language 【发布时间】:2012-03-23 13:58:11 【问题描述】:我快疯了,因为我不能让一组简单的三角形出现在我的屏幕上。
我正在使用 D 编程语言的废弃绑定使用 OpenGL3(不推荐使用的固定管道)。
你能发现以下程序中的错误吗?它编译得很好,不会抛出任何 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);
【问题讨论】:
我不能马上告诉你问题出在哪里,但如果你真的使用 glGetError() 检查 OpenGL 错误,它几乎肯定会有所帮助。查看 std.exception 中的 enforce 函数以及它如何使用惰性参数 - 您可以将其调整为enforceGL()
函数,以便更容易捕获 OpenGL 错误。
我制作了这个代码的一个版本,我用assert(glGetError() == 0);
行检查了每个 gl 调用...没有引发错误。
你为什么要重新加载 Derelict? :o
嗨 Jeroen,我正在重新加载 Derelict 以创建 GL3 上下文。这显然是这样做的方法。
【参考方案1】:
在这一行:
glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, vertices.sizeof, null);
您确定要vertices.sizeof
,它的值为16?在 D 中,动态数组是具有两个成员(ptr
和 length
)的结构。您可能想要float.sizeof
或float.sizeof * 2
。
BufferData
电话也是如此。
【讨论】:
感谢您的回答!我更改了声明以使它们成为静态数组(我认为因为它们是用文字定义的,所以它们将是静态的)现在.sizeof 对于vertices
是 32(长度 * float.sizeof),对于 indices
是 8。但我仍然没有画出任何东西。 :(
哦等等,你太棒了。我在 glBufferData 调用中将vertices.sizeof
替换为vertices.length * float.sizeof
,与indices
相同。但是在glVertexAttribPointer
中,我需要2 * float.sizeof
作为步幅参数。有用!!谢谢!
@SantiagoV。嘿,我能够使用您的示例来帮助我入门(不使用 sdl)。我知道这是旧的,但当我这样做时,我只是一个彩色的窗户......好像三角形比窗户大得多。对此有什么想法吗?
@AbstractDissonance 对不起,没有看到你的问题......从我的代码中看到,没有投影或视图矩阵,所以可能是的,矩形是窗口的大小。
以上是关于用 D 语言用 OpenGL 3 渲染一个简单的矩形的主要内容,如果未能解决你的问题,请参考以下文章