为了账号安全,请及时绑定邮箱和手机立即绑定

在 Golang 中绘制像素缓冲区到框架的跨平台方式?

在 Golang 中绘制像素缓冲区到框架的跨平台方式?

Go
白猪掌柜的 2022-12-19 20:03:26
假设我有一个内存位图/像素网格,我想在某种窗口中将它们全部写到屏幕上。例如:[ [255,0,0],[200,100,100]... [255,0,100],[155,200,100]... ...]有没有一种简单而高效的方法来做到这一点?我很乐意使用 OpenGL 或 Vulkan,但它们在这里似乎有点矫枉过正。任何仍然允许我捕获鼠标/键盘输入的东西的奖励积分,但如果它使事情复杂化,我很乐意自己管理这部分。我个人在 Linux 上工作,如果它不能移植到 Windows,我也可以接受,但这会很好。编辑:只是根据 Ben Hoyt 的评论对此进行了更新 - 我的目标是提供令人耳目一新的框架,将用例想象成编写 GIF 播放器。给定一组这些帧,我想按顺序显示它们,并在它们之间显示一个相当低的显示。
查看完整描述

2 回答

?
暮色呼如

TA贡献1853条经验 获得超9个赞

如果您的目标只是将图像加载到屏幕上,这里有一种使用 OpenGL 和 GLFW 的直接方法。您可以使用像 Fyne 这样的库来执行此操作,但它已经在内部使用了 OpenGL 和 GLFW(以及许多其他依赖项),因此您最好去掉中间人。


这是我的样板程序,它使用 OpenGL 纹理和帧缓冲区将图像 blits 到屏幕。


package main


import (

    "image"

    "runtime"


    "github.com/go-gl/gl/all-core/gl"

    "github.com/go-gl/glfw/v3.3/glfw"

)


func init() {

    // GLFW: This is needed to arrange that main() runs on main thread.

    // See documentation for functions that are only allowed to be called from the main thread.

    runtime.LockOSThread()

}


func main() {

    err := glfw.Init()

    if err != nil {

        panic(err)

    }

    defer glfw.Terminate()


    window, err := glfw.CreateWindow(640, 480, "My Window", nil, nil)

    if err != nil {

        panic(err)

    }


    window.MakeContextCurrent()


    err = gl.Init()

    if err != nil {

        panic(err)

    }


    var texture uint32

    {

        gl.GenTextures(1, &texture)


        gl.BindTexture(gl.TEXTURE_2D, texture)

        gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)

        gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)

        gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)

        gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)


        gl.BindImageTexture(0, texture, 0, false, 0, gl.WRITE_ONLY, gl.RGBA8)

    }


    var framebuffer uint32

    {

        gl.GenFramebuffers(1, &framebuffer)

        gl.BindFramebuffer(gl.FRAMEBUFFER, framebuffer)

        gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0)


        gl.BindFramebuffer(gl.READ_FRAMEBUFFER, framebuffer)

        gl.BindFramebuffer(gl.DRAW_FRAMEBUFFER, 0)

    }


    for !window.ShouldClose() {


        var w, h = window.GetSize()


        var img = image.NewRGBA(image.Rect(0, 0, w, h))


        // -------------------------

        // MODIFY OR LOAD IMAGE HERE

        // -------------------------


        gl.BindTexture(gl.TEXTURE_2D, texture)

        gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, int32(w), int32(h), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(img.Pix))


        gl.BlitFramebuffer(0, 0, int32(w), int32(h), 0, 0, int32(w), int32(h), gl.COLOR_BUFFER_BIT, gl.LINEAR)


        window.SwapBuffers()

        glfw.PollEvents()

    }

}


查看完整回答
反对 回复 2022-12-19
?
隔江千里

TA贡献1906条经验 获得超10个赞

我最终为此使用了 Fyne,以支持跨平台和支持快速刷新的目标。如果有人知道在屏幕上放置像素缓冲区的本机方法,请随时在这里发表评论,但这看起来非常轻量级并且本机适用于 Go。关于如何正确执行此操作的我的 GHI 可以在这里看到:https ://github.com/fyne-io/fyne/issues/3052

以 60 FPS 播放大量连续光栅帧:

https://i.stack.imgur.com/YkcFW.gif

查看完整回答
反对 回复 2022-12-19
  • 2 回答
  • 0 关注
  • 98 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信