OpenGL顶点缓冲在golang中无法绘制任何内容。

huangapple go评论83阅读模式
英文:

OpenGL Vertex Buffer doesn't draw anything in golang

问题

我尝试使用这个教程来编写Golang代码:http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/
Go版本的代码可以打开窗口并将背景设置为蓝色,但是没有显示三角形。C版本的代码可以显示三角形。
以下是Go版本的代码:

err := glfw.Init()
if err != nil {
    log.Fatal("Failed to init GLFW: " + err.Error())
}

err = glfw.OpenWindow(1024, 768, 0,0,0,0, 32,0, glfw.Windowed)
if err != nil {
    log.Fatal("Failed to open GLFW window: " + err.Error())
}

if gl.Init() != 0 {
    log.Fatal("Failed to init GL")
}

gl.ClearColor(0.0, 0.0, 0.3, 0.0)

// 创建顶点缓冲区
gVertexBufferData := []float32{-1.0,-1.0,0.0, 1.0,-1.0,0.0, 0.0,1.0,0.0}
vertexBuffer := gl.GenBuffer()
vertexBuffer.Bind(gl.ARRAY_BUFFER)
gl.BufferData(gl.ARRAY_BUFFER, len(gVertexBufferData), gVertexBufferData, gl.STATIC_DRAW)

for {
    // 清空屏幕
    gl.Clear(gl.COLOR_BUFFER_BIT)
    
    // 第一个属性缓冲区:顶点
    var vertexAttrib gl.AttribLocation = 0
    vertexAttrib.EnableArray()
    vertexBuffer.Bind(gl.ARRAY_BUFFER)
    var f float32 = 0.0
    vertexAttrib.AttribPointer(
        3,     // 大小
        false, // 是否归一化
        0,     // 步长
        &f) // 数组缓冲区偏移量
    
    // 绘制三角形
    gl.DrawArrays(gl.TRIANGLES, 0, 3)
    
    vertexAttrib.DisableArray()
    
    glfw.SwapBuffers()
}

以下是可以工作的C版本的代码:

if(!glfwInit())
    return -1;

if(!glfwOpenWindow( 1024, 768, 0,0,0,0, 32,0, GLFW_WINDOW ))
    return -1;

if(glewInit() != GLEW_OK)
    return -1;

glClearColor(0.0f, 0.0f, 0.3f, 0.0f);

GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);

static const GLfloat g_vertex_buffer_data[] = { 
    -1.0f, -1.0f, 0.0f,
    1.0f, -1.0f, 0.0f,
    0.0f,  1.0f, 0.0f,
};
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);

while(1) {
    glClear( GL_COLOR_BUFFER_BIT );
    
    // 第一个属性缓冲区:顶点
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glVertexAttribPointer(
        0,
        3, // 大小
        GL_FLOAT, // 类型
        GL_FALSE, // 是否归一化
        0, // 步长
        (void*)0 // 数组缓冲区偏移量
    );

    // 绘制三角形
    glDrawArrays(GL_TRIANGLES, 0, 3); // 从索引0到3绘制一个三角形

    glDisableVertexAttribArray(0);

    // 交换缓冲区
    glfwSwapBuffers();
}

也许是因为我给vertexAttrib.AttribPointer()传递了错误的参数,因为我不确定在(void*)0之外应该传递什么。我尝试了nil,但导致应用程序崩溃。&gVertexBufferData[0]也不起作用。
我使用的是github.com/banthar/gl作为glew-wrapper,go 1.0.2和ubuntu 12.04 amd64。
编辑更新:
glGetError没有返回任何错误。

英文:

I tried to use this tutorial with Golang: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/
The go-version opens the window and makes the background blue, but it doesn't show the triangle. The c-version does show it.
This is the code in Go:

err := glfw.Init()
if err != nil {
    log.Fatal("Failed to init GLFW: " + err.Error())
}

err = glfw.OpenWindow(1024, 768, 0,0,0,0, 32,0, glfw.Windowed)
if err != nil {
    log.Fatal("Failed to open GLFW window: " + err.Error())
}

if gl.Init() != 0 {
    log.Fatal("Failed to init GL")
}

gl.ClearColor(0.0, 0.0, 0.3, 0.0)

// create vertexbuffer
gVertexBufferData := []float32{-1.0,-1.0,0.0, 1.0,-1.0,0.0, 0.0,1.0,0.0}
vertexBuffer := gl.GenBuffer()
vertexBuffer.Bind(gl.ARRAY_BUFFER)
gl.BufferData(gl.ARRAY_BUFFER, len(gVertexBufferData), gVertexBufferData, gl.STATIC_DRAW)

for {
    // clear screen
    gl.Clear(gl.COLOR_BUFFER_BIT)
    
    // first attribute buffer: vertices
    var vertexAttrib gl.AttribLocation = 0
    vertexAttrib.EnableArray()
    vertexBuffer.Bind(gl.ARRAY_BUFFER)
    var f float32 = 0.0
    vertexAttrib.AttribPointer(
        3,     // size
        false, // normalized?
        0,     // stride
        &f) // array buffer offset
    
    // draw the triangle
    gl.DrawArrays(gl.TRIANGLES, 0, 3)
    
    vertexAttrib.DisableArray()
    
    glfw.SwapBuffers()
}

And this is the code in c which works:

if(!glfwInit())
    return -1;

if(!glfwOpenWindow( 1024, 768, 0,0,0,0, 32,0, GLFW_WINDOW ))
    return -1;

if(glewInit() != GLEW_OK)
    return -1;

glClearColor(0.0f, 0.0f, 0.3f, 0.0f);

GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);

static const GLfloat g_vertex_buffer_data[] = { 
    -1.0f, -1.0f, 0.0f,
    1.0f, -1.0f, 0.0f,
    0.0f,  1.0f, 0.0f,
};
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);

while(1) {
    glClear( GL_COLOR_BUFFER_BIT );
    
    // 1rst attribute buffer : vertices
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glVertexAttribPointer(
        0,
        3, // size
        GL_FLOAT, // type
        GL_FALSE, // normalized?
        0, // stride
        (void*)0 // array buffer offset
    );

    // Draw the triangle !
    glDrawArrays(GL_TRIANGLES, 0, 3); // From index 0 to 3 -> 1 triangle

    glDisableVertexAttribArray(0);

    // Swap buffers
    glfwSwapBuffers();
}

Maybe I give vertexAttrib.AttribPointer() the wrong arguments, because I'm not sure what to give it instead of (void*)0. I tried nil, but that caused the application to crash. &gVertexBufferData[0] doesn't work either.

I'm using github.com/banthar/gl as glew-wrapper, go 1.0.2 and ubuntu 12.04 amd64.

EDIT update:

glGetError doesn't give any errors

答案1

得分: 5

我遇到了同样的问题,并在查看了你的帖子后成功解决了它,首先非常感谢。

我通过使用banthar绑定的work分支,并使用以下AttribPointer调用来显示一个三角形:

vertexAttrib.AttribPointer(
        3,     // 大小
        gl.FLOAT, // 类型
        false, // 是否归一化?
        0,     // 步长
        nil) // 数组缓冲区偏移量

并通过将字节大小传递给BufferData来传递大小。

[...]
data := []float32{0, 1, 0, -1, -1, 0, 1, -1, 0}
[...]
gl.BufferData(gl.ARRAY_BUFFER, len(data)*4, data, gl.STATIC_DRAW)
[...]

可能有更好的方法来传递正确的长度。

英文:

I had the same problem and I managed to fix it after looking at your post, so first of all thanks a lot.

I managed to display a triangle by using the work branch of banthar bindings with this call to AttribPointer:

vertexAttrib.AttribPointer(
        3,     // size
        gl.FLOAT, //type
        false, // normalized?
        0,     // stride
        nil) // array buffer offset

and by passing the size in bytes to BufferData.

[...]
data := []float32{0, 1, 0, -1, -1, 0, 1, -1, 0}
[...]
gl.BufferData(gl.ARRAY_BUFFER, len(data)*4, data, gl.STATIC_DRAW)
[...]

There is probably a better way to pass the right length.

答案2

得分: 3

我最近遇到了与Golang OpenGL绑定类似的问题,而这个问题是我能找到的唯一参考之一。然而,现有的答案都没有解决我的问题,因为2015年的绑定与2012年的绑定略有不同。

解决我的问题的方法是在创建VBO时调用gl.BufferData()函数。

一个导致问题的代码示例如下:

[...]
vertices := []float32{0, 1, 0, -1, -1, 0, 1, -1, 0}
[...]
gl.BufferData(
	gl.ARRAY_BUFFER,
	len(vertices)*4,
	unsafe.Pointer(&vertices),
	gl.STATIC_DRAW)
[...]

已经提供的一个解决方案建议将此代码更改为以下内容:

[...]
vertices := []float32{0, 1, 0, -1, -1, 0, 1, -1, 0}
[...]
gl.BufferData(
    gl.ARRAY_BUFFER,
    len(vertices)*4,
    vertices,
    gl.STATIC_DRAW)
[...]

然而,我使用的绑定具有与此处使用的绑定不同的函数签名,并出现错误:

cannot use vertices (type []float32) as type unsafe.Pointer in argument to gl.BufferData

我最终找到的解决方案,并希望在这里提供,以便其他人不必经历我为解决这个问题所花费的头痛,如下所示:

[...]
vertices := []float32{0, 1, 0, -1, -1, 0, 1, -1, 0}
[...]
gl.BufferData(
	gl.ARRAY_BUFFER,
	len(vertices)*4, //len(vertices)*int(reflect.TypeOf(vertices).Elem().Size()),
	gl.Ptr(vertices),
	gl.STATIC_DRAW)
[...]

我还包含了一个被注释掉的选项,用于将len(vertices)*4替换为根据切片类型找到的'4',这产生完全相同的结果(在这种情况下是float32类型)。

脚注

我使用的绑定:
github.com/go-gl/gl/all-core/gl
github.com/go-gl/glfw/v3.1/glfw

我的OpenGL上下文是使用以下提示创建的:
primaryMonitor := glfw.GetPrimaryMonitor()
vidMode := primaryMonitor.GetVideoMode()

glfw.WindowHint(glfw.ContextVersionMajor, 3)
glfw.WindowHint(glfw.ContextVersionMinor, 3)
glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)

glfw.WindowHint(glfw.RedBits, vidMode.RedBits)
glfw.WindowHint(glfw.GreenBits, vidMode.GreenBits)
glfw.WindowHint(glfw.BlueBits, vidMode.BlueBits)
glfw.WindowHint(glfw.RefreshRate, vidMode.RefreshRate)
glfw.WindowHint(glfw.Visible, glfw.False)
英文:

I recently came into a similar issue with the Golang OpenGL bindings, and this question was one of the only references to it I could find.
However, none of the existing answers solved my problem, as the bindings appear to be slightly different now in 2015 than they looked in 2012.

The solution to my issue which hasn't already been covered by the existing answers involved the gl.BufferData() function called when creating a VBO.

A problem-producing example of the code in question would look like this:

[...]
vertices := []float32{0, 1, 0, -1, -1, 0, 1, -1, 0}
[...]
gl.BufferData(
	gl.ARRAY_BUFFER,
	len(vertices)*4,
	unsafe.Pointer(&vertices),
	gl.STATIC_DRAW)
[...]

One solution already provided recommended to change this code to something like this:

[...]
vertices := []float32{0, 1, 0, -1, -1, 0, 1, -1, 0}
[...]
gl.BufferData(
    gl.ARRAY_BUFFER,
    len(vertices)*4,
    vertices,
    gl.STATIC_DRAW)
[...]

However the bindings I used had a different function signature to those used here, and errored with:

cannot use vertices (type []float32) as type unsafe.Pointer in argument to gl.BufferData

The solution I ended up finding, and wanted to put here so nobody else should have to go through the headache it took trying to figure out the issue, looks like this:

[...]
vertices := []float32{0, 1, 0, -1, -1, 0, 1, -1, 0}
[...]
gl.BufferData(
	gl.ARRAY_BUFFER,
	len(vertices)*4, //len(vertices)*int(reflect.TypeOf(vertices).Elem().Size()),
	gl.Ptr(vertices),
	gl.STATIC_DRAW)
[...]

I also included a commented out option to replace len(vertices)*4 with, which produces the exact same result, but finds the '4' based on the type of slice (float32 in this case)

Footnotes

The bindings I used:
github.com/go-gl/gl/all-core/gl
github.com/go-gl/glfw/v3.1/glfw

My OpenGL context was created with these hints:
primaryMonitor := glfw.GetPrimaryMonitor()
vidMode := primaryMonitor.GetVideoMode()

glfw.WindowHint(glfw.ContextVersionMajor, 3)
glfw.WindowHint(glfw.ContextVersionMinor, 3)
glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)

glfw.WindowHint(glfw.RedBits, vidMode.RedBits)
glfw.WindowHint(glfw.GreenBits, vidMode.GreenBits)
glfw.WindowHint(glfw.BlueBits, vidMode.BlueBits)
glfw.WindowHint(glfw.RefreshRate, vidMode.RefreshRate)
glfw.WindowHint(glfw.Visible, glfw.False)

答案3

得分: 1

我遇到了同样的问题,最后发现是因为某种原因调用glfw.OpenWindowHint会搞乱它。它会请求正确的上下文,我的opengl版本也匹配,没有任何错误,但它不起作用。如果我省略这个提示,我会得到一个4.3的上下文,一切似乎都正常。

即使我在提示中请求4.3,它也不起作用。如果我请求其他东西,我的opengl字符串匹配,但再次不起作用。

希望这能帮到你。

英文:

I was having the same problem, ended up being that for some reason calling glfw.OpenWindowHint was screwing it up. It would request the correct context, my opengl version would match, I would get no errors at all, but it wouldn't work. If I leave out the hint, I get a 4.3 context and everything seems to work.

Even if I request 4.3 in the hint, it doesn't work. If I request something else, my opengl string matches, but once again it doesn't work.

Hope this helps

答案4

得分: 0

我不知道Go语言中的OpenGL绑定具体是什么样子的,但是我至少可以告诉你这么多:

glVertexAttribPointer的最后一个参数应该是从缓冲对象开始的字节偏移量,所以(在你的情况下)是0。

> 注意:该参数的C类型通常应该是int,因为它是一个字节偏移量。但是由于历史原因,它是void*类型 - 在VBOs之前它有不同的含义。

尝试传递一个字面值0,或者如果这不起作用,尝试传递一个值为0的指针。如何在Go语言中实现这一点?这是你需要弄清楚的,因为我不了解Go语言。我告诉了你OpenGL的期望,希望这对你有所帮助。


另外:为了调试,请经常检查glGetError()

英文:

I don't know how the OpenGL bindings to Go look exactly, but I can tell you at least this much:

The last parameter to glVertexAttribPointer should be the byte offset from the start of the buffer object, so (in your case) 0.

> Note: The C type of that parameter generally should be int, as it's a byte offset. Instead, it's void* for legacy reasons - it used to have a different meaning before VBOs.

Instead of &f try passing either a literal 0 or, if this doesn't work, a pointer with value equal to 0. How to do that in Go? This is for you to figure out, since I don't grok Go. I told you what OpenGL expects and I hope this much helps.


Also: For debugging, please check glGetError() often.

huangapple
  • 本文由 发表于 2012年7月2日 01:11:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/11284055.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定