2015-11-16 49 views
1

我卡在glReadPixels:看起來沒有數據寫入輸出數組。glReadPixels不會將數據寫入數組

從手冊(https://www.opengl.org/sdk/docs/man/docbook4/xhtml/glReadPixels.xml)中可以看出如果發生錯誤,則不會更改數據內容。,但顯然沒有錯誤返回glGetError()

我真的不明白什麼是錯的......這裏是代碼 - 在golang中 - 在屏幕上採樣隨機點。它總是打印[0 0 0],儘管沒有像素應該是黑色的(甚至沒有背景)。

package main 

import (
    "fmt" 
    "github.com/go-gl/gl/v4.1-core/gl" 
    "github.com/veandco/go-sdl2/sdl" 
    "math/rand" 
    "os" 
    "runtime" 
) 

func main() { 
    // Random crashes, this seems to fix 
    runtime.LockOSThread() 

    var wWidth, wHeight int = 500, 500 

    // Initialize SDL 
    if err := sdl.Init(sdl.INIT_EVERYTHING); err != nil { 
     panic(err) 
    } 
    defer sdl.Quit() 

    // Initialize OpenGL 
    if err := gl.Init(); err != nil { 
     panic(err) 
    } 

    // Create the OpenGL-capable window 
    win, err := sdl.CreateWindow(
     "glReadPixels Test", 
     sdl.WINDOWPOS_CENTERED, 
     sdl.WINDOWPOS_CENTERED, 
     wWidth, wHeight, 
     sdl.WINDOW_OPENGL) 

    if err != nil { 
     panic(err) 
    } 
    defer win.Destroy() 

    // Setup OpenGL context 
    var ctx sdl.GLContext 
    ctx, err = sdl.GL_CreateContext(win) 
    if err != nil { 
     panic(err) 
    } 
    defer sdl.GL_DeleteContext(ctx) 

    // Settings 
    initGL(wWidth, wHeight) 

    for { 
     for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() { 
      switch event.(type) { 
      case *sdl.QuitEvent: 
       os.Exit(0) 
      } 
     } 

     // Clear and draw 
     gl.Clear(gl.COLOR_BUFFER_BIT) 
     gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) 

     rx, ry := rand.Intn(wWidth), rand.Intn(wHeight) 

     gl.ReadBuffer(gl.FRONT) // Not working with gl.BACK either 
     data := make([]byte, 3) 
     //data[0], data[1], data[2] = 123, 213, 132 // Test if it's overwritten 
     gl.ReadPixels(int32(rx), int32(ry), 1, 1, gl.RGB, gl.UNSIGNED_BYTE, gl.Ptr(&data)) 
     fmt.Println("Read at", rx, ry, data) 

     // Show on window 
     sdl.GL_SwapWindow(win) 

     // Check for errors... 
     if gl.GetError() != gl.NO_ERROR { 
      fmt.Println("GL ERROR Somewhere!") 
     } 

     sdl.Delay(uint32(300)) 
    } 
} 

func initGL(winW, winH int) { 
    gl.ClearColor(0.2, 0.2, 0.3, 1.0) 
    gl.Viewport(0, 0, int32(winW), int32(winH)) 

    // Shader sources 
    vertShaderSrc := gl.Str(` 
#version 130 

in vec3 vertPos; 
in vec2 vertUV; 

out vec2 fragUV; 

void main() { 
    gl_Position = vec4(vertPos, 1.0f); 
    fragUV = vertUV; 
} 
` + "\x00") 

    fragShaderSrc := gl.Str(`#version 130 
in vec2 fragUV; 
out vec3 outColor; 

void main() { 
    if (fragUV.x < 0.5 ^^ fragUV.y < 0.5) 
     outColor = vec3(1.0, 0.0, 0.0); 
    else 
     outColor = vec3(0.0, 0.0, 1.0); 
} 
` + "\x00") 

    // Shaders 
    var vShader, fShader uint32 
    vShader = gl.CreateShader(gl.VERTEX_SHADER) 
    fShader = gl.CreateShader(gl.FRAGMENT_SHADER) 
    gl.ShaderSource(vShader, 1, &vertShaderSrc, nil) 
    gl.ShaderSource(fShader, 1, &fragShaderSrc, nil) 
    gl.CompileShader(vShader) 
    gl.CompileShader(fShader) 

    // Program 
    var progr uint32 = gl.CreateProgram() 
    gl.AttachShader(progr, vShader) 
    gl.AttachShader(progr, fShader) 
    gl.BindAttribLocation(progr, 0, gl.Str("vertPos\x00")) 
    gl.BindAttribLocation(progr, 1, gl.Str("vertUV\x00")) 
    gl.LinkProgram(progr) 
    gl.UseProgram(progr) 

    const N float32 = -0.5 
    const P float32 = 0.5 

    // Setup the "canvas": a simple quad 
    canvasData := []float32{ 
     N, N, 0, 0.0, 0.0, 
     P, N, 0, 1.0, 0.0, 
     N, P, 0, 0.0, 1.0, 
     P, P, 0, 1.0, 1.0, 
    } 

    var vboID uint32 
    gl.GenBuffers(1, &vboID) 
    gl.BindBuffer(gl.ARRAY_BUFFER, vboID) 
    gl.BufferData(gl.ARRAY_BUFFER, len(canvasData)*4, gl.Ptr(canvasData), gl.STATIC_DRAW) 

    var vaoID uint32 
    gl.GenVertexArrays(1, &vaoID) 
    gl.BindVertexArray(vaoID) 

    gl.EnableVertexAttribArray(0) 
    gl.EnableVertexAttribArray(1) 

    gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 5*4, gl.PtrOffset(0)) 
    gl.VertexAttribPointer(1, 2, gl.FLOAT, false, 5*4, gl.PtrOffset(3*4)) 
} 

回答

1

這個問題可能

gl.ReadPixels(int32(rx), int32(ry), 1, 1, gl.RGB, gl.UNSIGNED_BYTE, gl.Ptr(&data)) 

具體

gl.Ptr(&data) 

該功能的文檔:

​​

你傳遞一個指針切片。這是...有問題,如果你看看實施。

func Ptr(data interface{}) unsafe.Pointer { 
    if data == nil { 
     return unsafe.Pointer(nil) 
    } 
    var addr unsafe.Pointer 
    v := reflect.ValueOf(data) 
    switch v.Type().Kind() { 
    case reflect.Ptr: 
     e := v.Elem() 
     switch e.Kind() { 
     case 
      reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 
      reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, 
      reflect.Float32, reflect.Float64: 
      addr = unsafe.Pointer(e.UnsafeAddr()) 
     } 
    case reflect.Uintptr: 
     addr = unsafe.Pointer(v.Pointer()) 
    case reflect.Slice: 


addr = unsafe.Pointer(v.Index(0).UnsafeAddr()) 
    default: 
     panic(fmt.Sprintf("Unsupported type %s; must be a pointer, slice, or array", v.Type())) 
    } 
    return addr 
} 

正如你所看到的,如果你在一個指針傳遞爲比基本UINT /浮點/ INT其他任何東西,它會悄悄地失敗,並返回一個空unsafe.Pointer如果它的類型不正確。所以你要麼通過gl.Ptr(&data[0])gl.Ptr(data)。坦白地說,這不是暫時性的。

+0

謝謝你sooo多!我沒有想到它,我沒有看'Ptr'文檔:(我認爲我現在可能在我的代碼中有其他錯誤>。 AkiRoss

+1

@AkiRoss - 我實際上做了一個文件這個錯誤報告與'go-gl'有關,因爲我們確實應該是恐慌或者自動解引用,或者從字面上理解其他任何東西,而不是祕密地返回空指針 – LinearZoetrope

+0

我同意我有同樣的想法,但沒時間打開一個問題,謝謝。 – AkiRoss