OpenGL Vertex Buffer no dibuja nada en golang

Traté de usar este tutorial con Golang: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/ La versión go abre la ventana y hace que el fondo sea azul, pero no muestra el triángulo. La versión c lo muestra. Este es el código en 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()
}

Y este es el código en c que funciona:

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();
}

Tal vez le doy a vertexAttrib.AttribPointer() los argumentos incorrectos, porque no estoy seguro de qué darle en lugar de (void*)0. Intenté cero, pero eso provocó que la aplicación fallara. &gVertexBufferData[0] tampoco funciona.

Estoy usando github.com/banthar/gl como glew-wrapper, go 1.0.2 y ubuntu 12.04 amd64.

EDITAR actualización:

glGetError no da ningún error

preguntado el 01 de julio de 12 a las 18:07

¿Qué línea genera ese glError? ¿Estás seguro de que es AttribPointer? La línea que causa el error es tan importante de conocer como el error mismo. INVALID_ENUM no implica que haya ningún problema con el valor de compensación. -

Fue una suposición falsa, solo ocurre cuando defino glfw.OpenGLVersion como 3.3 con glfw.OpenWindowHint() -

4 Respuestas

Tuve el mismo problema y logré solucionarlo después de ver tu publicación, así que antes que nada muchas gracias.

Logré mostrar un triángulo usando la rama de trabajo de los enlaces banthar con esta llamada a AttribPointer:

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

y pasando el tamaño en bytes a BufferData.

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

Probablemente haya una mejor manera de pasar la longitud correcta.

Respondido 29 ago 12, 21:08

Yay, me topé con este hilo nuevamente y funcionó, gracias :-) - Lara

Mientras revisaba mi código para que no funcionara, me preguntaba por qué gl.BufferData se molestaba en querer el tamaño cuando podía obtenerlo fácilmente de la matriz/rebanada en sí. Tiene sentido ahora tener que pasar el verdadero subyacente tamaño, porque no puede obtener el tamaño de su tipo contenido porque no puede saber el tipo dentro de la matriz, ya que el tercer argumento data es de tipo interface{}. - lloeki

Recientemente tuve un problema similar con los enlaces de Golang OpenGL, y esta pregunta fue una de las únicas referencias que pude encontrar. Sin embargo, ninguna de las respuestas existentes resolvió mi problema, ya que los enlaces parecen ser ligeramente diferentes ahora en 2015 de lo que parecían en 2012.

La solución a mi problema, que aún no ha sido cubierta por las respuestas existentes, involucró la función gl.BufferData() llamada al crear un VBO.

Un ejemplo que produce problemas del código en cuestión se vería así:

[...]
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)
[...]

Una solución ya provista recomendó cambiar este código a algo como esto:

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

Sin embargo, los enlaces que usé tenían una firma de función diferente a las que se usan aquí, y tenían un error con:

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

La solución que terminé encontrando, y que quería poner aquí para que nadie más tuviera que pasar por el dolor de cabeza que tomó tratar de resolver el problema, se ve así:

[...]
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)
[...]

También incluí una opción comentada para reemplazar len (vértices) * 4 con, que produce exactamente el mismo resultado, pero encuentra el '4' según el tipo de corte (float32 en este caso)

Notas a pie de página

Los enlaces que usé:
github.com/go-gl/gl/all-core/gl
github.com/go-gl/glfw/v3.1/glfw

Mi contexto OpenGL se creó con estas sugerencias: 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)

Respondido 29 Oct 15, 07:10

Estaba teniendo el mismo problema, terminó siendo que, por alguna razón, llamar a glfw.OpenWindowHint lo estaba arruinando. Solicitaría el contexto correcto, mi versión de opengl coincidiría, no obtendría ningún error, pero no funcionaría. Si omito la sugerencia, obtengo un contexto 4.3 y todo parece funcionar.

Incluso si solicito 4.3 en la sugerencia, no funciona. Si solicito algo más, mi cadena opengl coincide, pero una vez más no funciona.

Espero que esto ayude

Respondido el 20 de Septiembre de 12 a las 01:09

No sé cómo se ven exactamente los enlaces de OpenGL a Go, pero puedo decirte al menos esto:

El último parámetro para glVertexAttribPointer debe ser el desplazamiento de bytes desde el inicio del objeto de búfer, por lo que (en su caso) 0.

Nota: El tipo C de ese parámetro generalmente debe ser int, ya que es un desplazamiento de bytes. En cambio, es void* por razones heredadas, solía tener un significado diferente antes de los VBO.

En lugar de &f intente pasar un 0 literal o, si esto no funciona, un puntero con valor igual a 0. ¿Cómo hacer eso en Go? Esto es para que lo descubras, ya que no asimilo a Go. Te dije lo que espera OpenGL y espero que esto ayude mucho.


También: para la depuración, verifique glGetError() a menudo.

Respondido 01 Jul 12, 18:07

Gracias por la respuesta. Problema con glVertexAttribPointer: no puedo pasar 0, el envoltorio usa el tipo de desplazamiento como tipo para glVertexAttribPointer (tercer argumento). Pero incluso cuando le doy un int, nada cambia. glGetError: ¡muchas gracias! Edité la publicación inicial para eso. - Lara

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.