├── .github └── workflows │ └── golangci-lint.yaml ├── .gitignore ├── .golangci.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── assets └── screenshot.png ├── cmd ├── example_glfw_opengl2 │ ├── README.md │ └── main.go ├── example_glfw_opengl3 │ ├── README.md │ └── main.go ├── example_sdl_opengl2 │ ├── README.md │ └── main.go └── example_sdl_opengl3 │ ├── README.md │ └── main.go ├── go.mod ├── go.sum └── internal ├── demo ├── Window.go └── doc.go ├── example ├── Run.go └── doc.go ├── platforms ├── constants.go ├── doc.go ├── errors.go ├── glfw.go └── sdl.go └── renderers ├── OpenGL2.go ├── OpenGL3.go ├── doc.go ├── gl-shader ├── main.frag └── main.vert └── gl ├── README.md ├── v2.1 └── gl │ ├── KHR │ └── khrplatform.h │ ├── conversions.go │ ├── debug.go │ ├── package.go │ └── procaddr.go └── v3.2-core └── gl ├── KHR └── khrplatform.h ├── conversions.go ├── debug.go ├── package.go └── procaddr.go /.github/workflows/golangci-lint.yaml: -------------------------------------------------------------------------------- 1 | name: golangci-lint 2 | on: [push, pull_request] 3 | jobs: 4 | golangci: 5 | name: lint 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v2 9 | - name: Install libraries 10 | run: | 11 | sudo apt-get update 12 | sudo apt-get install -y mesa-utils mesa-common-dev libsdl2-dev libglfw3-dev 13 | 14 | - name: Set up Go 15 | uses: actions/setup-go@v3 16 | with: 17 | go-version: '1.17.8' 18 | check-latest: false 19 | # Disabled because a "clean" build was not in store for archiving this repository. 20 | # Still, keeping the action "alive" as a shell, to showcase what would be necessary to build the programs. 21 | # - name: golangci-lint 22 | # uses: golangci/golangci-lint-action@v3 23 | # with: 24 | # version: v1.44.2 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | 3 | imgui.ini 4 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | deadline: 10m 3 | build-tags: 4 | - glfw 5 | - sdl 6 | 7 | skip-dirs: 8 | - internal/renderers/gl 9 | 10 | linters: 11 | # Take an aggressive approach: enable everything and only disable if not useful. 12 | # So far there are fewer to disable than to enable explicitly. 13 | enable-all: true 14 | 15 | # linters are disabled if their majority of issues is considered false-positive (intended code) 16 | # and the remaining issues (if existing) aren't worth it. 17 | disable: 18 | - gochecknoglobals 19 | - gocognit # disabled because of the high complexity of demo files 20 | - goimports # disabled because of so many false-positives with "imgui-go" 21 | - gofumpt # disabled because no extra need 22 | - gosec 23 | - maligned 24 | - nestif # disabled because of the high complexity of demo files 25 | - gomnd # disabled as most OpenGL stuff are direct constants. 26 | - funlen # disabled because of example code. While people will probably tend to duplicate this, they'll handle it on their own. 27 | - wsl # this one became too pedantic and with a different style than I would. 28 | 29 | issues: 30 | exclude-use-default: false # disable filtering of defaults for better zero-issue policy 31 | exclude: 32 | # There is a lot of pointer-mangling happening here, so disable this govet warning 33 | - possible misuse of unsafe.Pointer 34 | max-per-linter: 0 # disable limit; report all issues of a linter 35 | max-same-issues: 0 # disable limit; report all issues of the same issue 36 | 37 | linters-settings: 38 | lll: 39 | line-length: 160 40 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing Guidelines 2 | 3 | Thank you for considering to contribute to this project! 4 | 5 | The following text lists guidelines for contributions. 6 | These guidelines don't have legal status, so use them as a reference and common sense - and feel free to update them as well! 7 | 8 | 9 | ### "I just want to know..." 10 | 11 | For questions, or general usage-information about **Dear ImGui**, please refer to the [homepage](https://github.com/ocornut/imgui), or look in the detailed documentation of the C++ source. 12 | This project contains the "ported" examples of **Dear ImGui**, adopted to a more Go-like style, using the available Go wrappers. 13 | 14 | 15 | ### Extensions 16 | 17 | If you can and want to make use of the code from these examples in your own projects, you are happy to do so. 18 | 19 | > The code shared between the examples is put into `internal` package on purpose. 20 | > This project contains only reference implementations, not meant to be directly included in others. 21 | 22 | Pull-requests with extensions are happily accepted, provided that they uphold the following minimum requirements: 23 | * Code is properly formatted & linted (use [golangci-lint](https://github.com/golangci/golangci-lint) for a full check) 24 | 25 | > If there are linter errors that you didn't introduce, you don't have to clean them up - I might have missed them and will be handling them separately. 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | New BSD License 2 | 3 | © 2019, Christian Haas 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | * Neither the name of "InkyBlackness" nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE LISTED COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Examples of Dear ImGui for Go 2 | 3 | [![Go Report Card](https://goreportcard.com/badge/github.com/inkyblackness/imgui-go-examples)](https://goreportcard.com/report/github.com/inkyblackness/imgui-go-examples) 4 | [![Lint Status](https://github.com/inkyblackness/imgui-go-examples/workflows/golangci-lint/badge.svg)](https://github.com/inkyblackness/imgui-go-examples/actions) 5 | 6 | ## Discontinued 7 | **This repository is no longer maintained as per 2022-12-31. 8 | Please refer to the README of the main repository for details and alternatives: https://github.com/inkyblackness/imgui-go .** 9 | 10 | -- 11 | 12 | This project contains a set of [Go](https://www.golang.org) examples for [imgui-go](https://github.com/inkyblackness/imgui-go), which is a wrapper for [**Dear ImGui**](https://github.com/ocornut/imgui). 13 | 14 | It provides reference implementations on how to use and integrate **Dear ImGui** in Go. 15 | 16 | ![Screenshot](assets/screenshot.png) 17 | 18 | ## Layout 19 | The project follows the basic concept of the examples of **Dear ImGui** by separating platform and renderer bindings from the example applications that wire them together in compatible constellations. 20 | 21 | * `cmd` contains the main functions of the example applications. They typically combine a platform with a renderer. 22 | * `internal` contains the reusable library components 23 | * `platforms` contains code for mouse/keyboard/gamepad inputs, cursor shape, timing, windowing. For example based on: [GLFW3](https://github.com/go-gl/glfw) and [SDL2](https://github.com/veandco/go-sdl2). 24 | * `renderers` contains code for creating the main font texture, rendering imgui draw data. For example using: [OpenGL](https://github.com/go-gl) (both v2.1 (fixed pipe) and v3.2 (shaders) via [glow](https://github.com/go-gl/glow) generated binding code) 25 | * `example` contains the common example code. 26 | * `demo` contains the ported `imgui_demo.cpp` code to showcase what is wrapped. 27 | 28 | ## Running examples 29 | 30 | Some platforms and/or renderers may require dedicated build flags to be passed. 31 | Each example comes with a separate `README.md` that describes how to run them. 32 | 33 | > Build flags are used in order to avoid compiling all the libraries at once. 34 | 35 | ## License 36 | 37 | The project is available under the terms of the **New BSD License** (see LICENSE file). 38 | -------------------------------------------------------------------------------- /assets/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inkyblackness/imgui-go-examples/c0f92f1c17a91ea0fd97b6e3a576cab1d01e91f9/assets/screenshot.png -------------------------------------------------------------------------------- /cmd/example_glfw_opengl2/README.md: -------------------------------------------------------------------------------- 1 | ## GLFW + OpenGL2 example 2 | 3 | To run this example, you need [GLFW3](https://github.com/go-gl/glfw). Enable tag `glfw` when building/running: 4 | 5 | go run -tags 'glfw' . 6 | -------------------------------------------------------------------------------- /cmd/example_glfw_opengl2/main.go: -------------------------------------------------------------------------------- 1 | // +build glfw 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | 9 | "github.com/inkyblackness/imgui-go/v4" 10 | 11 | "github.com/inkyblackness/imgui-go-examples/internal/example" 12 | "github.com/inkyblackness/imgui-go-examples/internal/platforms" 13 | "github.com/inkyblackness/imgui-go-examples/internal/renderers" 14 | ) 15 | 16 | func main() { 17 | context := imgui.CreateContext(nil) 18 | defer context.Destroy() 19 | io := imgui.CurrentIO() 20 | 21 | platform, err := platforms.NewGLFW(io, platforms.GLFWClientAPIOpenGL2) 22 | if err != nil { 23 | _, _ = fmt.Fprintf(os.Stderr, "%v\n", err) 24 | os.Exit(-1) 25 | } 26 | defer platform.Dispose() 27 | 28 | renderer, err := renderers.NewOpenGL2(io) 29 | if err != nil { 30 | _, _ = fmt.Fprintf(os.Stderr, "%v\n", err) 31 | os.Exit(-1) 32 | } 33 | defer renderer.Dispose() 34 | 35 | example.Run(platform, renderer) 36 | } 37 | -------------------------------------------------------------------------------- /cmd/example_glfw_opengl3/README.md: -------------------------------------------------------------------------------- 1 | ## GLFW + OpenGL3 example 2 | 3 | To run this example, you need [GLFW3](https://github.com/go-gl/glfw). Enable tag `glfw` when building/running: 4 | 5 | go run -tags 'glfw' . 6 | -------------------------------------------------------------------------------- /cmd/example_glfw_opengl3/main.go: -------------------------------------------------------------------------------- 1 | // +build glfw 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | 9 | "github.com/inkyblackness/imgui-go/v4" 10 | 11 | "github.com/inkyblackness/imgui-go-examples/internal/example" 12 | "github.com/inkyblackness/imgui-go-examples/internal/platforms" 13 | "github.com/inkyblackness/imgui-go-examples/internal/renderers" 14 | ) 15 | 16 | func main() { 17 | context := imgui.CreateContext(nil) 18 | defer context.Destroy() 19 | io := imgui.CurrentIO() 20 | 21 | platform, err := platforms.NewGLFW(io, platforms.GLFWClientAPIOpenGL3) 22 | if err != nil { 23 | _, _ = fmt.Fprintf(os.Stderr, "%v\n", err) 24 | os.Exit(-1) 25 | } 26 | defer platform.Dispose() 27 | 28 | renderer, err := renderers.NewOpenGL3(io) 29 | if err != nil { 30 | _, _ = fmt.Fprintf(os.Stderr, "%v\n", err) 31 | os.Exit(-1) 32 | } 33 | defer renderer.Dispose() 34 | 35 | example.Run(platform, renderer) 36 | } 37 | -------------------------------------------------------------------------------- /cmd/example_sdl_opengl2/README.md: -------------------------------------------------------------------------------- 1 | ## SDL2 + OpenGL2 example 2 | 3 | To run this example, you need [SDL2](https://github.com/veandco/go-sdl2). Enable tag `sdl` when building/running: 4 | 5 | go run -tags 'sdl' . 6 | -------------------------------------------------------------------------------- /cmd/example_sdl_opengl2/main.go: -------------------------------------------------------------------------------- 1 | // +build sdl 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | 9 | "github.com/inkyblackness/imgui-go/v4" 10 | 11 | "github.com/inkyblackness/imgui-go-examples/internal/example" 12 | "github.com/inkyblackness/imgui-go-examples/internal/platforms" 13 | "github.com/inkyblackness/imgui-go-examples/internal/renderers" 14 | ) 15 | 16 | func main() { 17 | context := imgui.CreateContext(nil) 18 | defer context.Destroy() 19 | io := imgui.CurrentIO() 20 | 21 | platform, err := platforms.NewSDL(io, platforms.SDLClientAPIOpenGL2) 22 | if err != nil { 23 | _, _ = fmt.Fprintf(os.Stderr, "%v\n", err) 24 | os.Exit(-1) 25 | } 26 | defer platform.Dispose() 27 | 28 | renderer, err := renderers.NewOpenGL2(io) 29 | if err != nil { 30 | _, _ = fmt.Fprintf(os.Stderr, "%v\n", err) 31 | os.Exit(-1) 32 | } 33 | defer renderer.Dispose() 34 | 35 | example.Run(platform, renderer) 36 | } 37 | -------------------------------------------------------------------------------- /cmd/example_sdl_opengl3/README.md: -------------------------------------------------------------------------------- 1 | ## SDL2 + OpenGL3 example 2 | 3 | To run this example, you need [SDL2](https://github.com/veandco/go-sdl2). Enable tag `sdl` when building/running: 4 | 5 | go run -tags 'sdl' . 6 | -------------------------------------------------------------------------------- /cmd/example_sdl_opengl3/main.go: -------------------------------------------------------------------------------- 1 | // +build sdl 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | 9 | "github.com/inkyblackness/imgui-go/v4" 10 | 11 | "github.com/inkyblackness/imgui-go-examples/internal/example" 12 | "github.com/inkyblackness/imgui-go-examples/internal/platforms" 13 | "github.com/inkyblackness/imgui-go-examples/internal/renderers" 14 | ) 15 | 16 | func main() { 17 | context := imgui.CreateContext(nil) 18 | defer context.Destroy() 19 | io := imgui.CurrentIO() 20 | 21 | platform, err := platforms.NewSDL(io, platforms.SDLClientAPIOpenGL3) 22 | if err != nil { 23 | _, _ = fmt.Fprintf(os.Stderr, "%v\n", err) 24 | os.Exit(-1) 25 | } 26 | defer platform.Dispose() 27 | 28 | renderer, err := renderers.NewOpenGL3(io) 29 | if err != nil { 30 | _, _ = fmt.Fprintf(os.Stderr, "%v\n", err) 31 | os.Exit(-1) 32 | } 33 | defer renderer.Dispose() 34 | 35 | example.Run(platform, renderer) 36 | } 37 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/inkyblackness/imgui-go-examples 2 | 3 | require ( 4 | github.com/davecgh/go-spew v1.1.1 // indirect 5 | github.com/go-gl/glfw v0.0.0-20210727001814-0db043d8d5be 6 | github.com/inkyblackness/imgui-go/v4 v4.7.0 7 | github.com/veandco/go-sdl2 v0.4.10 8 | ) 9 | 10 | go 1.16 11 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/go-gl/glfw v0.0.0-20210727001814-0db043d8d5be h1:UVW91pfMB1GRQfVwC7//RGVbqX6Ea8jURmJhlANak1M= 5 | github.com/go-gl/glfw v0.0.0-20210727001814-0db043d8d5be/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 6 | github.com/inkyblackness/imgui-go/v4 v4.7.0 h1:Gc169uXvSydsr/gjw3p1cmHCI1XIpqX7I3KBmfeMMOo= 7 | github.com/inkyblackness/imgui-go/v4 v4.7.0/go.mod h1:g8SAGtOYUP7rYaOB2AsVKCEHmPMDmJKgt4z6d+flhb0= 8 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 9 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 10 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 11 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 12 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 13 | github.com/veandco/go-sdl2 v0.4.10 h1:8QoD2bhWl7SbQDflIAUYWfl9Vq+mT8/boJFAUzAScgY= 14 | github.com/veandco/go-sdl2 v0.4.10/go.mod h1:OROqMhHD43nT4/i9crJukyVecjPNYYuCofep6SNiAjY= 15 | -------------------------------------------------------------------------------- /internal/demo/Window.go: -------------------------------------------------------------------------------- 1 | package demo 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/inkyblackness/imgui-go/v4" 7 | ) 8 | 9 | type windowFlags struct { 10 | noTitlebar bool 11 | noScrollbar bool 12 | noMenu bool 13 | noMove bool 14 | noResize bool 15 | noCollapse bool 16 | noNav bool 17 | noBackground bool 18 | noBringToFront bool 19 | } 20 | 21 | func (f windowFlags) combined() imgui.WindowFlags { 22 | flags := imgui.WindowFlagsNone 23 | if f.noTitlebar { 24 | flags |= imgui.WindowFlagsNoTitleBar 25 | } 26 | if f.noScrollbar { 27 | flags |= imgui.WindowFlagsNoScrollbar 28 | } 29 | if !f.noMenu { 30 | flags |= imgui.WindowFlagsMenuBar 31 | } 32 | if f.noMove { 33 | flags |= imgui.WindowFlagsNoMove 34 | } 35 | if f.noResize { 36 | flags |= imgui.WindowFlagsNoResize 37 | } 38 | if f.noCollapse { 39 | flags |= imgui.WindowFlagsNoCollapse 40 | } 41 | if f.noNav { 42 | flags |= imgui.WindowFlagsNoNav 43 | } 44 | if f.noBackground { 45 | flags |= imgui.WindowFlagsNoBackground 46 | } 47 | if f.noBringToFront { 48 | flags |= imgui.WindowFlagsNoBringToFrontOnFocus 49 | } 50 | return flags 51 | } 52 | 53 | var window = struct { 54 | flags windowFlags 55 | noClose bool 56 | 57 | widgets widgets 58 | layout layout 59 | popups popups 60 | columns columns 61 | tables tables 62 | misc misc 63 | }{} 64 | 65 | func bulletText(text string) { 66 | imgui.Bullet() 67 | imgui.Text(text) 68 | } 69 | 70 | // Show demonstrates most ImGui features that were ported to Go. 71 | // This function tries to recreate the original demo window as closely as possible. 72 | // 73 | // In theory, if both windows would provide the identical functionality, then the wrapper would be complete. 74 | func Show(keepOpen *bool) { 75 | imgui.SetNextWindowPosV(imgui.Vec2{X: 650, Y: 20}, imgui.ConditionFirstUseEver, imgui.Vec2{}) 76 | imgui.SetNextWindowSizeV(imgui.Vec2{X: 550, Y: 680}, imgui.ConditionFirstUseEver) 77 | 78 | if window.noClose { 79 | keepOpen = nil 80 | } 81 | if !imgui.BeginV("ImGui-Go Demo", keepOpen, window.flags.combined()) { 82 | // Early out if the window is collapsed, as an optimization. 83 | imgui.End() 84 | return 85 | } 86 | 87 | // Use fixed width for labels (by passing a negative value), the rest goes to widgets. 88 | // We choose a width proportional to our font size. 89 | imgui.PushItemWidth(imgui.FontSize() * -12) 90 | 91 | // MenuBar 92 | if imgui.BeginMenuBar() { 93 | if imgui.BeginMenu("Menu") { 94 | imgui.EndMenu() 95 | } 96 | if imgui.BeginMenu("Examples") { 97 | imgui.EndMenu() 98 | } 99 | if imgui.BeginMenu("Tools") { 100 | imgui.EndMenu() 101 | } 102 | 103 | imgui.EndMenuBar() 104 | } 105 | 106 | imgui.Text(fmt.Sprintf("dear imgui says hello. (%s)", imgui.Version())) 107 | imgui.Spacing() 108 | 109 | if imgui.CollapsingHeader("Help") { 110 | imgui.Text("ABOUT THIS DEMO:") 111 | bulletText("Sections below are demonstrating many aspects of the wrapper.") 112 | bulletText("This demo may not be complete. Refer to the \"native\" demo window for a full overview.") 113 | bulletText("The \"Examples\" menu above leads to more demo contents.") 114 | bulletText("The \"Tools\" menu above gives access to: About Box, Style Editor,\n" + 115 | "and Metrics (general purpose Dear ImGui debugging tool).") 116 | imgui.Separator() 117 | 118 | imgui.Text("PROGRAMMER GUIDE:") 119 | bulletText("See the demo.Show() code in internal/demo/Window.go. <- you are here!") 120 | bulletText("See comments in imgui.cpp.") 121 | bulletText("See example applications in the examples/ folder.") 122 | bulletText("Read the FAQ at http://www.dearimgui.org/faq/") 123 | bulletText("Set 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls.") 124 | bulletText("Set 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls.") 125 | imgui.Separator() 126 | 127 | imgui.Text("USER GUIDE:") 128 | showUserGuide() 129 | } 130 | 131 | // MISSING: Configuration 132 | 133 | if imgui.CollapsingHeader("Window options") { 134 | imgui.Checkbox("No titlebar", &window.flags.noTitlebar) 135 | imgui.SameLineV(150, -1) 136 | imgui.Checkbox("No scrollbar", &window.flags.noScrollbar) 137 | imgui.SameLineV(300, -1) 138 | imgui.Checkbox("No menu", &window.flags.noMenu) 139 | imgui.Checkbox("No move", &window.flags.noMove) 140 | imgui.SameLineV(150, -1) 141 | imgui.Checkbox("No resize", &window.flags.noResize) 142 | imgui.SameLineV(300, -1) 143 | imgui.Checkbox("No collapse", &window.flags.noCollapse) 144 | imgui.Checkbox("No close", &window.noClose) 145 | imgui.SameLineV(150, -1) 146 | imgui.Checkbox("No nav", &window.flags.noNav) 147 | imgui.SameLineV(300, -1) 148 | imgui.Checkbox("No background", &window.flags.noBackground) 149 | imgui.Checkbox("No bring to front", &window.flags.noBringToFront) 150 | } 151 | 152 | // All demo contents 153 | window.widgets.show() 154 | window.layout.show() 155 | window.popups.show() 156 | window.columns.show() 157 | window.tables.show() 158 | window.misc.show() 159 | 160 | // End of ShowDemoWindow() 161 | imgui.End() 162 | } 163 | 164 | func showUserGuide() { 165 | bulletText("Double-click on title bar to collapse window.") 166 | bulletText("Click and drag on lower corner to resize window\n(double-click to auto fit window to its contents).") 167 | bulletText("CTRL+Click on a slider or drag box to input value as text.") 168 | bulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.") 169 | 170 | // MISSING: Allow FontUserScaling 171 | 172 | bulletText("While inputing text:\n") 173 | imgui.Indent() 174 | bulletText("CTRL+Left/Right to word jump.") 175 | bulletText("CTRL+A or double-click to select all.") 176 | bulletText("CTRL+X/C/V to use clipboard cut/copy/paste.") 177 | bulletText("CTRL+Z,CTRL+Y to undo/redo.") 178 | bulletText("ESCAPE to revert.") 179 | bulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.") 180 | imgui.Unindent() 181 | bulletText("With keyboard navigation enabled:") 182 | imgui.Indent() 183 | bulletText("Arrow keys to navigate.") 184 | bulletText("Space to activate a widget.") 185 | bulletText("Return to input text into a widget.") 186 | bulletText("Escape to deactivate a widget, close popup, exit child window.") 187 | bulletText("Alt to jump to the menu layer of a window.") 188 | bulletText("CTRL+Tab to select a window.") 189 | imgui.Unindent() 190 | } 191 | 192 | type widgets struct { 193 | buttonClicked int 194 | check bool 195 | radio int32 196 | } 197 | 198 | // nolint: nestif 199 | func (widgets *widgets) show() { 200 | if !imgui.CollapsingHeader("Widgets") { 201 | return 202 | } 203 | 204 | if imgui.TreeNode("Basic") { 205 | if imgui.Button("Button") { 206 | widgets.buttonClicked++ 207 | } 208 | if widgets.buttonClicked&1 != 0 { 209 | imgui.SameLine() 210 | imgui.Text("Thanks for clicking me!") 211 | } 212 | 213 | imgui.Checkbox("checkbox", &widgets.check) 214 | 215 | if imgui.RadioButton("radio a", widgets.radio == 0) { 216 | widgets.radio = 0 217 | } 218 | imgui.SameLine() 219 | if imgui.RadioButton("radio b", widgets.radio == 1) { 220 | widgets.radio = 1 221 | } 222 | imgui.SameLine() 223 | if imgui.RadioButton("radio c", widgets.radio == 2) { 224 | widgets.radio = 2 225 | } 226 | 227 | imgui.Combo("combo", &widgets.radio, []string{ 228 | "one item", 229 | "two items", 230 | "three items", 231 | }) 232 | 233 | imgui.TreePop() 234 | } 235 | } 236 | 237 | type tables struct { 238 | background bool 239 | borders bool 240 | noInnerBorders bool 241 | header bool 242 | } 243 | 244 | var demoTableHeader = []string{ 245 | "Name", "Favourite Food", "Favourite Colour", 246 | } 247 | 248 | var demoTable = [][]string{ 249 | {"Eric", "Bannana", "Yellow"}, 250 | {"Peter", "Apple", "Red"}, 251 | {"Bruce", "Liquorice", "Black"}, 252 | {"Aaron", "Chocolates", "Blue"}, 253 | } 254 | 255 | func (tables *tables) show() { 256 | if !imgui.CollapsingHeader("Tables") { 257 | return 258 | } 259 | 260 | if imgui.TreeNode("Rows & Columns") { 261 | if imgui.BeginTable("tableRowsAndColumns", 3) { 262 | for row := 0; row < 4; row++ { 263 | imgui.TableNextRow() 264 | for column := 0; column < 3; column++ { 265 | imgui.TableSetColumnIndex(column) 266 | imgui.Text(fmt.Sprintf("Row %d Column %d", row, column)) 267 | } 268 | } 269 | imgui.EndTable() 270 | } 271 | imgui.TreePop() 272 | } 273 | 274 | if imgui.TreeNode("Options") { 275 | // tables are useful for more than tabulated data. we use tables here 276 | // to facilitate layout of the option checkboxes 277 | if imgui.BeginTable("tableOptions", 2) { 278 | imgui.TableNextRow() 279 | if imgui.TableNextColumn() { 280 | imgui.Checkbox("Background", &tables.background) 281 | } 282 | if imgui.TableNextColumn() { 283 | imgui.Checkbox("Header Row", &tables.header) 284 | } 285 | 286 | imgui.TableNextRow() 287 | if imgui.TableNextColumn() { 288 | imgui.Checkbox("Borders", &tables.borders) 289 | } 290 | if tables.borders { 291 | if imgui.TableNextColumn() { 292 | imgui.Checkbox("No Inner Borders", &tables.noInnerBorders) 293 | } 294 | } 295 | 296 | imgui.EndTable() 297 | } 298 | 299 | // set flags according to the options that have been selected 300 | flgs := imgui.TableFlagsNone 301 | if tables.background { 302 | flgs |= imgui.TableFlagsRowBg 303 | } 304 | if tables.borders { 305 | flgs |= imgui.TableFlagsBorders 306 | if tables.noInnerBorders { 307 | flgs |= imgui.TableFlagsNoBordersInBody 308 | } 309 | } 310 | 311 | if imgui.BeginTableV("tableRowsAndColumns", len(demoTableHeader), flgs, imgui.Vec2{}, 0.0) { 312 | if tables.header { 313 | imgui.TableHeadersRow() 314 | for column := 0; column < len(demoTableHeader); column++ { 315 | imgui.TableSetColumnIndex(column) 316 | imgui.Text(demoTableHeader[column]) 317 | } 318 | } 319 | 320 | for row := 0; row < len(demoTable); row++ { 321 | imgui.TableNextRow() 322 | for column := 0; column < len(demoTableHeader); column++ { 323 | imgui.TableSetColumnIndex(column) 324 | imgui.Text(demoTable[row][column]) 325 | } 326 | } 327 | imgui.EndTable() 328 | } 329 | imgui.TreePop() 330 | } 331 | } 332 | 333 | type layout struct { 334 | } 335 | 336 | func (layout *layout) show() { 337 | 338 | } 339 | 340 | type popups struct { 341 | } 342 | 343 | func (popups *popups) show() { 344 | 345 | } 346 | 347 | type columns struct { 348 | } 349 | 350 | func (columns *columns) show() { 351 | 352 | } 353 | 354 | type misc struct { 355 | } 356 | 357 | func (misc *misc) show() { 358 | 359 | } 360 | -------------------------------------------------------------------------------- /internal/demo/doc.go: -------------------------------------------------------------------------------- 1 | // Package demo contains the ported code of imgui_demo.cpp . 2 | // This package is intended both to showcase what ImGui can provide, as well as 3 | // what has actually been wrapped. 4 | // The visible part should be matched as closely as possible - the code only in spirit. 5 | package demo 6 | -------------------------------------------------------------------------------- /internal/example/Run.go: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/inkyblackness/imgui-go/v4" 8 | 9 | "github.com/inkyblackness/imgui-go-examples/internal/demo" 10 | ) 11 | 12 | // Platform covers mouse/keyboard/gamepad inputs, cursor shape, timing, windowing. 13 | type Platform interface { 14 | // ShouldStop is regularly called as the abort condition for the program loop. 15 | ShouldStop() bool 16 | // ProcessEvents is called once per render loop to dispatch any pending events. 17 | ProcessEvents() 18 | // DisplaySize returns the dimension of the display. 19 | DisplaySize() [2]float32 20 | // FramebufferSize returns the dimension of the framebuffer. 21 | FramebufferSize() [2]float32 22 | // NewFrame marks the begin of a render pass. It must update the imgui IO state according to user input (mouse, keyboard, ...) 23 | NewFrame() 24 | // PostRender marks the completion of one render pass. Typically this causes the display buffer to be swapped. 25 | PostRender() 26 | // ClipboardText returns the current text of the clipboard, if available. 27 | ClipboardText() (string, error) 28 | // SetClipboardText sets the text as the current text of the clipboard. 29 | SetClipboardText(text string) 30 | } 31 | 32 | type clipboard struct { 33 | platform Platform 34 | } 35 | 36 | func (board clipboard) Text() (string, error) { 37 | return board.platform.ClipboardText() 38 | } 39 | 40 | func (board clipboard) SetText(text string) { 41 | board.platform.SetClipboardText(text) 42 | } 43 | 44 | // Renderer covers rendering imgui draw data. 45 | type Renderer interface { 46 | // PreRender causes the display buffer to be prepared for new output. 47 | PreRender(clearColor [3]float32) 48 | // Render draws the provided imgui draw data. 49 | Render(displaySize [2]float32, framebufferSize [2]float32, drawData imgui.DrawData) 50 | } 51 | 52 | const ( 53 | millisPerSecond = 1000 54 | sleepDuration = time.Millisecond * 25 55 | ) 56 | 57 | // Run implements the main program loop of the demo. It returns when the platform signals to stop. 58 | // This demo application shows some basic features of ImGui, as well as exposing the standard demo window. 59 | func Run(p Platform, r Renderer) { 60 | imgui.CurrentIO().SetClipboard(clipboard{platform: p}) 61 | 62 | showDemoWindow := false 63 | showGoDemoWindow := false 64 | clearColor := [3]float32{0.0, 0.0, 0.0} 65 | f := float32(0) 66 | counter := 0 67 | showAnotherWindow := false 68 | 69 | for !p.ShouldStop() { 70 | p.ProcessEvents() 71 | 72 | // Signal start of a new frame 73 | p.NewFrame() 74 | imgui.NewFrame() 75 | 76 | // 1. Show a simple window. 77 | // Tip: if we don't call imgui.Begin()/imgui.End() the widgets automatically appears in a window called "Debug". 78 | { 79 | imgui.Text("ภาษาไทย测试조선말") // To display these, you'll need to register a compatible font 80 | imgui.Text("Hello, world!") // Display some text 81 | imgui.SliderFloat("float", &f, 0.0, 1.0) // Edit 1 float using a slider from 0.0f to 1.0f 82 | imgui.ColorEdit3("clear color", &clearColor) // Edit 3 floats representing a color 83 | 84 | imgui.Checkbox("Demo Window", &showDemoWindow) // Edit bools storing our window open/close state 85 | imgui.Checkbox("Go Demo Window", &showGoDemoWindow) 86 | imgui.Checkbox("Another Window", &showAnotherWindow) 87 | 88 | if imgui.Button("Button") { // Buttons return true when clicked (most widgets return true when edited/activated) 89 | counter++ 90 | } 91 | imgui.SameLine() 92 | imgui.Text(fmt.Sprintf("counter = %d", counter)) 93 | 94 | imgui.Text(fmt.Sprintf("Application average %.3f ms/frame (%.1f FPS)", 95 | millisPerSecond/imgui.CurrentIO().Framerate(), imgui.CurrentIO().Framerate())) 96 | } 97 | 98 | // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. 99 | if showAnotherWindow { 100 | // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) 101 | imgui.BeginV("Another window", &showAnotherWindow, 0) 102 | imgui.Text("Hello from another window!") 103 | if imgui.Button("Close Me") { 104 | showAnotherWindow = false 105 | } 106 | imgui.End() 107 | } 108 | 109 | // 3. Show the ImGui demo window. Most of the sample code is in imgui.ShowDemoWindow(). 110 | // Read its code to learn more about Dear ImGui! 111 | if showDemoWindow { 112 | // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. 113 | // Here we just want to make the demo initial state a bit more friendly! 114 | const demoX = 650 115 | const demoY = 20 116 | imgui.SetNextWindowPosV(imgui.Vec2{X: demoX, Y: demoY}, imgui.ConditionFirstUseEver, imgui.Vec2{}) 117 | 118 | imgui.ShowDemoWindow(&showDemoWindow) 119 | } 120 | if showGoDemoWindow { 121 | demo.Show(&showGoDemoWindow) 122 | } 123 | 124 | // Rendering 125 | imgui.Render() // This call only creates the draw data list. Actual rendering to framebuffer is done below. 126 | 127 | r.PreRender(clearColor) 128 | // A this point, the application could perform its own rendering... 129 | // app.RenderScene() 130 | 131 | r.Render(p.DisplaySize(), p.FramebufferSize(), imgui.RenderedDrawData()) 132 | p.PostRender() 133 | 134 | // sleep to avoid 100% CPU usage for this demo 135 | <-time.After(sleepDuration) 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /internal/example/doc.go: -------------------------------------------------------------------------------- 1 | // Package example contains the core logic of the demo. 2 | // The Run() function demonstrates how a typical application would create a UI. 3 | // The function herein is not concerned about technology-specific things, such as 4 | // which abstraction library or which drawing interface is used. 5 | package example 6 | -------------------------------------------------------------------------------- /internal/platforms/constants.go: -------------------------------------------------------------------------------- 1 | package platforms 2 | 3 | const ( 4 | windowWidth = 1280 5 | windowHeight = 720 6 | 7 | mouseButtonPrimary = 0 8 | mouseButtonSecondary = 1 9 | mouseButtonTertiary = 2 10 | mouseButtonCount = 3 11 | ) 12 | -------------------------------------------------------------------------------- /internal/platforms/doc.go: -------------------------------------------------------------------------------- 1 | // Package platforms contains abstraction-specific code. 2 | // This package contains wrappers for common abstraction libraries which provide 3 | // functionality to imgui in a common manner. 4 | // They are used by the demo package. 5 | package platforms 6 | -------------------------------------------------------------------------------- /internal/platforms/errors.go: -------------------------------------------------------------------------------- 1 | package platforms 2 | 3 | // StringError describes a basic error with static information. 4 | type StringError string 5 | 6 | // Error returns the string itself. 7 | func (err StringError) Error() string { 8 | return string(err) 9 | } 10 | 11 | const ( 12 | // ErrUnsupportedClientAPI is used in case the API is not available by the platform. 13 | ErrUnsupportedClientAPI = StringError("unsupported ClientAPI") 14 | ) 15 | -------------------------------------------------------------------------------- /internal/platforms/glfw.go: -------------------------------------------------------------------------------- 1 | // +build glfw 2 | 3 | package platforms 4 | 5 | import ( 6 | "fmt" 7 | "math" 8 | "runtime" 9 | 10 | "github.com/go-gl/glfw/v3.2/glfw" 11 | "github.com/inkyblackness/imgui-go/v4" 12 | ) 13 | 14 | // GLFWClientAPI identifies the render system that shall be initialized. 15 | type GLFWClientAPI string 16 | 17 | // This is a list of GLFWClientAPI constants. 18 | const ( 19 | GLFWClientAPIOpenGL2 GLFWClientAPI = "OpenGL2" 20 | GLFWClientAPIOpenGL3 GLFWClientAPI = "OpenGL3" 21 | ) 22 | 23 | // GLFW implements a platform based on github.com/go-gl/glfw (v3.2). 24 | type GLFW struct { 25 | imguiIO imgui.IO 26 | 27 | window *glfw.Window 28 | 29 | time float64 30 | mouseJustPressed [3]bool 31 | } 32 | 33 | // NewGLFW attempts to initialize a GLFW context. 34 | func NewGLFW(io imgui.IO, clientAPI GLFWClientAPI) (*GLFW, error) { 35 | runtime.LockOSThread() 36 | 37 | err := glfw.Init() 38 | if err != nil { 39 | return nil, fmt.Errorf("failed to initialize glfw: %w", err) 40 | } 41 | 42 | switch clientAPI { 43 | case GLFWClientAPIOpenGL2: 44 | glfw.WindowHint(glfw.ContextVersionMajor, 2) 45 | glfw.WindowHint(glfw.ContextVersionMinor, 1) 46 | case GLFWClientAPIOpenGL3: 47 | glfw.WindowHint(glfw.ContextVersionMajor, 3) 48 | glfw.WindowHint(glfw.ContextVersionMinor, 2) 49 | glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile) 50 | glfw.WindowHint(glfw.OpenGLForwardCompatible, 1) 51 | default: 52 | glfw.Terminate() 53 | return nil, ErrUnsupportedClientAPI 54 | } 55 | 56 | window, err := glfw.CreateWindow(windowWidth, windowHeight, "ImGui-Go GLFW+"+string(clientAPI)+" example", nil, nil) 57 | if err != nil { 58 | glfw.Terminate() 59 | return nil, fmt.Errorf("failed to create window: %w", err) 60 | } 61 | window.MakeContextCurrent() 62 | glfw.SwapInterval(1) 63 | 64 | platform := &GLFW{ 65 | imguiIO: io, 66 | window: window, 67 | } 68 | platform.setKeyMapping() 69 | platform.installCallbacks() 70 | 71 | return platform, nil 72 | } 73 | 74 | // Dispose cleans up the resources. 75 | func (platform *GLFW) Dispose() { 76 | platform.window.Destroy() 77 | glfw.Terminate() 78 | } 79 | 80 | // ShouldStop returns true if the window is to be closed. 81 | func (platform *GLFW) ShouldStop() bool { 82 | return platform.window.ShouldClose() 83 | } 84 | 85 | // ProcessEvents handles all pending window events. 86 | func (platform *GLFW) ProcessEvents() { 87 | glfw.PollEvents() 88 | } 89 | 90 | // DisplaySize returns the dimension of the display. 91 | func (platform *GLFW) DisplaySize() [2]float32 { 92 | w, h := platform.window.GetSize() 93 | return [2]float32{float32(w), float32(h)} 94 | } 95 | 96 | // FramebufferSize returns the dimension of the framebuffer. 97 | func (platform *GLFW) FramebufferSize() [2]float32 { 98 | w, h := platform.window.GetFramebufferSize() 99 | return [2]float32{float32(w), float32(h)} 100 | } 101 | 102 | // NewFrame marks the begin of a render pass. It forwards all current state to imgui IO. 103 | func (platform *GLFW) NewFrame() { 104 | // Setup display size (every frame to accommodate for window resizing) 105 | displaySize := platform.DisplaySize() 106 | platform.imguiIO.SetDisplaySize(imgui.Vec2{X: displaySize[0], Y: displaySize[1]}) 107 | 108 | // Setup time step 109 | currentTime := glfw.GetTime() 110 | if platform.time > 0 { 111 | platform.imguiIO.SetDeltaTime(float32(currentTime - platform.time)) 112 | } 113 | platform.time = currentTime 114 | 115 | // Setup inputs 116 | if platform.window.GetAttrib(glfw.Focused) != 0 { 117 | x, y := platform.window.GetCursorPos() 118 | platform.imguiIO.SetMousePosition(imgui.Vec2{X: float32(x), Y: float32(y)}) 119 | } else { 120 | platform.imguiIO.SetMousePosition(imgui.Vec2{X: -math.MaxFloat32, Y: -math.MaxFloat32}) 121 | } 122 | 123 | for i := 0; i < len(platform.mouseJustPressed); i++ { 124 | down := platform.mouseJustPressed[i] || (platform.window.GetMouseButton(glfwButtonIDByIndex[i]) == glfw.Press) 125 | platform.imguiIO.SetMouseButtonDown(i, down) 126 | platform.mouseJustPressed[i] = false 127 | } 128 | } 129 | 130 | // PostRender performs a buffer swap. 131 | func (platform *GLFW) PostRender() { 132 | platform.window.SwapBuffers() 133 | } 134 | 135 | func (platform *GLFW) setKeyMapping() { 136 | // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array. 137 | platform.imguiIO.KeyMap(imgui.KeyTab, int(glfw.KeyTab)) 138 | platform.imguiIO.KeyMap(imgui.KeyLeftArrow, int(glfw.KeyLeft)) 139 | platform.imguiIO.KeyMap(imgui.KeyRightArrow, int(glfw.KeyRight)) 140 | platform.imguiIO.KeyMap(imgui.KeyUpArrow, int(glfw.KeyUp)) 141 | platform.imguiIO.KeyMap(imgui.KeyDownArrow, int(glfw.KeyDown)) 142 | platform.imguiIO.KeyMap(imgui.KeyPageUp, int(glfw.KeyPageUp)) 143 | platform.imguiIO.KeyMap(imgui.KeyPageDown, int(glfw.KeyPageDown)) 144 | platform.imguiIO.KeyMap(imgui.KeyHome, int(glfw.KeyHome)) 145 | platform.imguiIO.KeyMap(imgui.KeyEnd, int(glfw.KeyEnd)) 146 | platform.imguiIO.KeyMap(imgui.KeyInsert, int(glfw.KeyInsert)) 147 | platform.imguiIO.KeyMap(imgui.KeyDelete, int(glfw.KeyDelete)) 148 | platform.imguiIO.KeyMap(imgui.KeyBackspace, int(glfw.KeyBackspace)) 149 | platform.imguiIO.KeyMap(imgui.KeySpace, int(glfw.KeySpace)) 150 | platform.imguiIO.KeyMap(imgui.KeyEnter, int(glfw.KeyEnter)) 151 | platform.imguiIO.KeyMap(imgui.KeyEscape, int(glfw.KeyEscape)) 152 | platform.imguiIO.KeyMap(imgui.KeyA, int(glfw.KeyA)) 153 | platform.imguiIO.KeyMap(imgui.KeyC, int(glfw.KeyC)) 154 | platform.imguiIO.KeyMap(imgui.KeyV, int(glfw.KeyV)) 155 | platform.imguiIO.KeyMap(imgui.KeyX, int(glfw.KeyX)) 156 | platform.imguiIO.KeyMap(imgui.KeyY, int(glfw.KeyY)) 157 | platform.imguiIO.KeyMap(imgui.KeyZ, int(glfw.KeyZ)) 158 | } 159 | 160 | func (platform *GLFW) installCallbacks() { 161 | platform.window.SetMouseButtonCallback(platform.mouseButtonChange) 162 | platform.window.SetScrollCallback(platform.mouseScrollChange) 163 | platform.window.SetKeyCallback(platform.keyChange) 164 | platform.window.SetCharCallback(platform.charChange) 165 | } 166 | 167 | var glfwButtonIndexByID = map[glfw.MouseButton]int{ 168 | glfw.MouseButton1: mouseButtonPrimary, 169 | glfw.MouseButton2: mouseButtonSecondary, 170 | glfw.MouseButton3: mouseButtonTertiary, 171 | } 172 | 173 | var glfwButtonIDByIndex = map[int]glfw.MouseButton{ 174 | mouseButtonPrimary: glfw.MouseButton1, 175 | mouseButtonSecondary: glfw.MouseButton2, 176 | mouseButtonTertiary: glfw.MouseButton3, 177 | } 178 | 179 | func (platform *GLFW) mouseButtonChange(window *glfw.Window, rawButton glfw.MouseButton, action glfw.Action, mods glfw.ModifierKey) { 180 | buttonIndex, known := glfwButtonIndexByID[rawButton] 181 | 182 | if known && (action == glfw.Press) { 183 | platform.mouseJustPressed[buttonIndex] = true 184 | } 185 | } 186 | 187 | func (platform *GLFW) mouseScrollChange(window *glfw.Window, x, y float64) { 188 | platform.imguiIO.AddMouseWheelDelta(float32(x), float32(y)) 189 | } 190 | 191 | func (platform *GLFW) keyChange(window *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) { 192 | if action == glfw.Press { 193 | platform.imguiIO.KeyPress(int(key)) 194 | } 195 | if action == glfw.Release { 196 | platform.imguiIO.KeyRelease(int(key)) 197 | } 198 | 199 | // Modifiers are not reliable across systems 200 | platform.imguiIO.KeyCtrl(int(glfw.KeyLeftControl), int(glfw.KeyRightControl)) 201 | platform.imguiIO.KeyShift(int(glfw.KeyLeftShift), int(glfw.KeyRightShift)) 202 | platform.imguiIO.KeyAlt(int(glfw.KeyLeftAlt), int(glfw.KeyRightAlt)) 203 | platform.imguiIO.KeySuper(int(glfw.KeyLeftSuper), int(glfw.KeyRightSuper)) 204 | } 205 | 206 | func (platform *GLFW) charChange(window *glfw.Window, char rune) { 207 | platform.imguiIO.AddInputCharacters(string(char)) 208 | } 209 | 210 | // ClipboardText returns the current clipboard text, if available. 211 | func (platform *GLFW) ClipboardText() (string, error) { 212 | return platform.window.GetClipboardString() 213 | } 214 | 215 | // SetClipboardText sets the text as the current clipboard text. 216 | func (platform *GLFW) SetClipboardText(text string) { 217 | platform.window.SetClipboardString(text) 218 | } 219 | -------------------------------------------------------------------------------- /internal/platforms/sdl.go: -------------------------------------------------------------------------------- 1 | // +build sdl 2 | 3 | package platforms 4 | 5 | import ( 6 | "fmt" 7 | "runtime" 8 | 9 | "github.com/inkyblackness/imgui-go/v4" 10 | "github.com/veandco/go-sdl2/sdl" 11 | ) 12 | 13 | // SDLClientAPI identifies the render system that shall be initialized. 14 | type SDLClientAPI string 15 | 16 | // This is a list of SDLClientAPI constants. 17 | const ( 18 | SDLClientAPIOpenGL2 SDLClientAPI = "OpenGL2" 19 | SDLClientAPIOpenGL3 SDLClientAPI = "OpenGL3" 20 | ) 21 | 22 | // SDL implements a platform based on github.com/veandco/go-sdl2 (v2). 23 | type SDL struct { 24 | imguiIO imgui.IO 25 | 26 | window *sdl.Window 27 | shouldStop bool 28 | 29 | time uint64 30 | buttonsDown [mouseButtonCount]bool 31 | } 32 | 33 | // NewSDL attempts to initialize an SDL context. 34 | func NewSDL(io imgui.IO, clientAPI SDLClientAPI) (*SDL, error) { 35 | runtime.LockOSThread() 36 | 37 | err := sdl.Init(sdl.INIT_VIDEO) 38 | if err != nil { 39 | return nil, fmt.Errorf("failed to initialize SDL2: %w", err) 40 | } 41 | 42 | window, err := sdl.CreateWindow("ImGui-Go SDL2+"+string(clientAPI)+" example", 43 | sdl.WINDOWPOS_CENTERED, sdl.WINDOWPOS_CENTERED, windowWidth, windowHeight, sdl.WINDOW_OPENGL) 44 | if err != nil { 45 | sdl.Quit() 46 | return nil, fmt.Errorf("failed to create window: %w", err) 47 | } 48 | 49 | platform := &SDL{ 50 | imguiIO: io, 51 | window: window, 52 | } 53 | platform.setKeyMapping() 54 | 55 | switch clientAPI { 56 | case SDLClientAPIOpenGL2: 57 | _ = sdl.GLSetAttribute(sdl.GL_CONTEXT_MAJOR_VERSION, 2) 58 | _ = sdl.GLSetAttribute(sdl.GL_CONTEXT_MINOR_VERSION, 1) 59 | case SDLClientAPIOpenGL3: 60 | _ = sdl.GLSetAttribute(sdl.GL_CONTEXT_MAJOR_VERSION, 3) 61 | _ = sdl.GLSetAttribute(sdl.GL_CONTEXT_MINOR_VERSION, 2) 62 | _ = sdl.GLSetAttribute(sdl.GL_CONTEXT_FLAGS, sdl.GL_CONTEXT_FORWARD_COMPATIBLE_FLAG) 63 | _ = sdl.GLSetAttribute(sdl.GL_CONTEXT_PROFILE_MASK, sdl.GL_CONTEXT_PROFILE_CORE) 64 | default: 65 | platform.Dispose() 66 | return nil, ErrUnsupportedClientAPI 67 | } 68 | _ = sdl.GLSetAttribute(sdl.GL_DOUBLEBUFFER, 1) 69 | _ = sdl.GLSetAttribute(sdl.GL_DEPTH_SIZE, 24) 70 | _ = sdl.GLSetAttribute(sdl.GL_STENCIL_SIZE, 8) 71 | 72 | glContext, err := window.GLCreateContext() 73 | if err != nil { 74 | platform.Dispose() 75 | return nil, fmt.Errorf("failed to create OpenGL context: %w", err) 76 | } 77 | err = window.GLMakeCurrent(glContext) 78 | if err != nil { 79 | platform.Dispose() 80 | return nil, fmt.Errorf("failed to set current OpenGL context: %w", err) 81 | } 82 | 83 | _ = sdl.GLSetSwapInterval(1) 84 | 85 | return platform, nil 86 | } 87 | 88 | // Dispose cleans up the resources. 89 | func (platform *SDL) Dispose() { 90 | if platform.window != nil { 91 | _ = platform.window.Destroy() 92 | platform.window = nil 93 | } 94 | sdl.Quit() 95 | } 96 | 97 | // ShouldStop returns true if the window is to be closed. 98 | func (platform *SDL) ShouldStop() bool { 99 | return platform.shouldStop 100 | } 101 | 102 | // ProcessEvents handles all pending window events. 103 | func (platform *SDL) ProcessEvents() { 104 | for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() { 105 | platform.processEvent(event) 106 | } 107 | } 108 | 109 | // DisplaySize returns the dimension of the display. 110 | func (platform *SDL) DisplaySize() [2]float32 { 111 | w, h := platform.window.GetSize() 112 | return [2]float32{float32(w), float32(h)} 113 | } 114 | 115 | // FramebufferSize returns the dimension of the framebuffer. 116 | func (platform *SDL) FramebufferSize() [2]float32 { 117 | w, h := platform.window.GLGetDrawableSize() 118 | return [2]float32{float32(w), float32(h)} 119 | } 120 | 121 | // NewFrame marks the begin of a render pass. It forwards all current state to imgui.CurrentIO(). 122 | func (platform *SDL) NewFrame() { 123 | // Setup display size (every frame to accommodate for window resizing) 124 | displaySize := platform.DisplaySize() 125 | platform.imguiIO.SetDisplaySize(imgui.Vec2{X: displaySize[0], Y: displaySize[1]}) 126 | 127 | // Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution) 128 | frequency := sdl.GetPerformanceFrequency() 129 | currentTime := sdl.GetPerformanceCounter() 130 | if platform.time > 0 { 131 | platform.imguiIO.SetDeltaTime(float32(currentTime-platform.time) / float32(frequency)) 132 | } else { 133 | const fallbackDelta = 1.0 / 60.0 134 | platform.imguiIO.SetDeltaTime(fallbackDelta) 135 | } 136 | platform.time = currentTime 137 | 138 | // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. 139 | x, y, state := sdl.GetMouseState() 140 | platform.imguiIO.SetMousePosition(imgui.Vec2{X: float32(x), Y: float32(y)}) 141 | for i, button := range []uint32{sdl.BUTTON_LEFT, sdl.BUTTON_RIGHT, sdl.BUTTON_MIDDLE} { 142 | platform.imguiIO.SetMouseButtonDown(i, platform.buttonsDown[i] || (state&sdl.Button(button)) != 0) 143 | platform.buttonsDown[i] = false 144 | } 145 | } 146 | 147 | // PostRender performs a buffer swap. 148 | func (platform *SDL) PostRender() { 149 | platform.window.GLSwap() 150 | } 151 | 152 | func (platform *SDL) setKeyMapping() { 153 | keys := map[int]int{ 154 | imgui.KeyTab: sdl.SCANCODE_TAB, 155 | imgui.KeyLeftArrow: sdl.SCANCODE_LEFT, 156 | imgui.KeyRightArrow: sdl.SCANCODE_RIGHT, 157 | imgui.KeyUpArrow: sdl.SCANCODE_UP, 158 | imgui.KeyDownArrow: sdl.SCANCODE_DOWN, 159 | imgui.KeyPageUp: sdl.SCANCODE_PAGEUP, 160 | imgui.KeyPageDown: sdl.SCANCODE_PAGEDOWN, 161 | imgui.KeyHome: sdl.SCANCODE_HOME, 162 | imgui.KeyEnd: sdl.SCANCODE_END, 163 | imgui.KeyInsert: sdl.SCANCODE_INSERT, 164 | imgui.KeyDelete: sdl.SCANCODE_DELETE, 165 | imgui.KeyBackspace: sdl.SCANCODE_BACKSPACE, 166 | imgui.KeySpace: sdl.SCANCODE_BACKSPACE, 167 | imgui.KeyEnter: sdl.SCANCODE_RETURN, 168 | imgui.KeyEscape: sdl.SCANCODE_ESCAPE, 169 | imgui.KeyA: sdl.SCANCODE_A, 170 | imgui.KeyC: sdl.SCANCODE_C, 171 | imgui.KeyV: sdl.SCANCODE_V, 172 | imgui.KeyX: sdl.SCANCODE_X, 173 | imgui.KeyY: sdl.SCANCODE_Y, 174 | imgui.KeyZ: sdl.SCANCODE_Z, 175 | } 176 | 177 | // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array. 178 | for imguiKey, nativeKey := range keys { 179 | platform.imguiIO.KeyMap(imguiKey, nativeKey) 180 | } 181 | } 182 | 183 | func (platform *SDL) processEvent(event sdl.Event) { 184 | switch event.GetType() { 185 | case sdl.QUIT: 186 | platform.shouldStop = true 187 | case sdl.MOUSEWHEEL: 188 | wheelEvent := event.(*sdl.MouseWheelEvent) 189 | var deltaX, deltaY float32 190 | if wheelEvent.X > 0 { 191 | deltaX++ 192 | } else if wheelEvent.X < 0 { 193 | deltaX-- 194 | } 195 | if wheelEvent.Y > 0 { 196 | deltaY++ 197 | } else if wheelEvent.Y < 0 { 198 | deltaY-- 199 | } 200 | platform.imguiIO.AddMouseWheelDelta(deltaX, deltaY) 201 | case sdl.MOUSEBUTTONDOWN: 202 | buttonEvent := event.(*sdl.MouseButtonEvent) 203 | switch buttonEvent.Button { 204 | case sdl.BUTTON_LEFT: 205 | platform.buttonsDown[mouseButtonPrimary] = true 206 | case sdl.BUTTON_RIGHT: 207 | platform.buttonsDown[mouseButtonSecondary] = true 208 | case sdl.BUTTON_MIDDLE: 209 | platform.buttonsDown[mouseButtonTertiary] = true 210 | } 211 | case sdl.TEXTINPUT: 212 | inputEvent := event.(*sdl.TextInputEvent) 213 | platform.imguiIO.AddInputCharacters(string(inputEvent.Text[:])) 214 | case sdl.KEYDOWN: 215 | keyEvent := event.(*sdl.KeyboardEvent) 216 | platform.imguiIO.KeyPress(int(keyEvent.Keysym.Scancode)) 217 | platform.updateKeyModifier() 218 | case sdl.KEYUP: 219 | keyEvent := event.(*sdl.KeyboardEvent) 220 | platform.imguiIO.KeyRelease(int(keyEvent.Keysym.Scancode)) 221 | platform.updateKeyModifier() 222 | } 223 | } 224 | 225 | func (platform *SDL) updateKeyModifier() { 226 | modState := sdl.GetModState() 227 | mapModifier := func(lMask sdl.Keymod, lKey int, rMask sdl.Keymod, rKey int) (lResult int, rResult int) { 228 | if (modState & lMask) != 0 { 229 | lResult = lKey 230 | } 231 | if (modState & rMask) != 0 { 232 | rResult = rKey 233 | } 234 | return 235 | } 236 | platform.imguiIO.KeyShift(mapModifier(sdl.KMOD_LSHIFT, sdl.SCANCODE_LSHIFT, sdl.KMOD_RSHIFT, sdl.SCANCODE_RSHIFT)) 237 | platform.imguiIO.KeyCtrl(mapModifier(sdl.KMOD_LCTRL, sdl.SCANCODE_LCTRL, sdl.KMOD_RCTRL, sdl.SCANCODE_RCTRL)) 238 | platform.imguiIO.KeyAlt(mapModifier(sdl.KMOD_LALT, sdl.SCANCODE_LALT, sdl.KMOD_RALT, sdl.SCANCODE_RALT)) 239 | } 240 | 241 | // ClipboardText returns the current clipboard text, if available. 242 | func (platform *SDL) ClipboardText() (string, error) { 243 | return sdl.GetClipboardText() 244 | } 245 | 246 | // SetClipboardText sets the text as the current clipboard text. 247 | func (platform *SDL) SetClipboardText(text string) { 248 | _ = sdl.SetClipboardText(text) 249 | } 250 | -------------------------------------------------------------------------------- /internal/renderers/OpenGL2.go: -------------------------------------------------------------------------------- 1 | package renderers 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | 7 | "github.com/inkyblackness/imgui-go-examples/internal/renderers/gl/v2.1/gl" 8 | "github.com/inkyblackness/imgui-go/v4" 9 | ) 10 | 11 | // OpenGL2 implements a renderer based on github.com/go-gl/gl (v2.1). 12 | type OpenGL2 struct { 13 | imguiIO imgui.IO 14 | 15 | fontTexture uint32 16 | } 17 | 18 | // NewOpenGL2 attempts to initialize a renderer. 19 | // An OpenGL context has to be established before calling this function. 20 | func NewOpenGL2(io imgui.IO) (*OpenGL2, error) { 21 | err := gl.Init() 22 | if err != nil { 23 | return nil, fmt.Errorf("failed to initialize OpenGL: %w", err) 24 | } 25 | 26 | renderer := &OpenGL2{ 27 | imguiIO: io, 28 | } 29 | renderer.createFontsTexture() 30 | return renderer, nil 31 | } 32 | 33 | // Dispose cleans up the resources. 34 | func (renderer *OpenGL2) Dispose() { 35 | renderer.destroyFontsTexture() 36 | } 37 | 38 | // PreRender clears the framebuffer. 39 | func (renderer *OpenGL2) PreRender(clearColor [3]float32) { 40 | gl.ClearColor(clearColor[0], clearColor[1], clearColor[2], 1.0) 41 | gl.Clear(gl.COLOR_BUFFER_BIT) 42 | } 43 | 44 | // Render translates the ImGui draw data to OpenGL3 commands. 45 | func (renderer *OpenGL2) Render(displaySize [2]float32, framebufferSize [2]float32, drawData imgui.DrawData) { 46 | // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) 47 | displayWidth, displayHeight := displaySize[0], displaySize[1] 48 | fbWidth, fbHeight := framebufferSize[0], framebufferSize[1] 49 | if (fbWidth <= 0) || (fbHeight <= 0) { 50 | return 51 | } 52 | drawData.ScaleClipRects(imgui.Vec2{ 53 | X: fbWidth / displayWidth, 54 | Y: fbHeight / displayHeight, 55 | }) 56 | 57 | // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill. 58 | var lastTexture int32 59 | gl.GetIntegerv(gl.TEXTURE_BINDING_2D, &lastTexture) 60 | var lastPolygonMode [2]int32 61 | gl.GetIntegerv(gl.POLYGON_MODE, &lastPolygonMode[0]) 62 | var lastViewport [4]int32 63 | gl.GetIntegerv(gl.VIEWPORT, &lastViewport[0]) 64 | var lastScissorBox [4]int32 65 | gl.GetIntegerv(gl.SCISSOR_BOX, &lastScissorBox[0]) 66 | gl.PushAttrib(gl.ENABLE_BIT | gl.COLOR_BUFFER_BIT | gl.TRANSFORM_BIT) 67 | gl.Enable(gl.BLEND) 68 | gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) 69 | gl.Disable(gl.CULL_FACE) 70 | gl.Disable(gl.DEPTH_TEST) 71 | gl.Disable(gl.LIGHTING) 72 | gl.Disable(gl.COLOR_MATERIAL) 73 | gl.Enable(gl.SCISSOR_TEST) 74 | gl.EnableClientState(gl.VERTEX_ARRAY) 75 | gl.EnableClientState(gl.TEXTURE_COORD_ARRAY) 76 | gl.EnableClientState(gl.COLOR_ARRAY) 77 | gl.Enable(gl.TEXTURE_2D) 78 | gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL) 79 | 80 | // You may want this if using this code in an OpenGL 3+ context where shaders may be bound 81 | // gl.UseProgram(0) 82 | 83 | // Setup viewport, orthographic projection matrix 84 | // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). 85 | // DisplayMin is typically (0,0) for single viewport apps. 86 | gl.Viewport(0, 0, int32(fbWidth), int32(fbHeight)) 87 | gl.MatrixMode(gl.PROJECTION) 88 | gl.PushMatrix() 89 | gl.LoadIdentity() 90 | gl.Ortho(0, float64(displayWidth), float64(displayHeight), 0, -1, 1) 91 | gl.MatrixMode(gl.MODELVIEW) 92 | gl.PushMatrix() 93 | gl.LoadIdentity() 94 | 95 | vertexSize, vertexOffsetPos, vertexOffsetUv, vertexOffsetCol := imgui.VertexBufferLayout() 96 | indexSize := imgui.IndexBufferLayout() 97 | 98 | drawType := gl.UNSIGNED_SHORT 99 | const bytesPerUint32 = 4 100 | if indexSize == bytesPerUint32 { 101 | drawType = gl.UNSIGNED_INT 102 | } 103 | 104 | // Render command lists 105 | for _, commandList := range drawData.CommandLists() { 106 | vertexBuffer, _ := commandList.VertexBuffer() 107 | indexBuffer, _ := commandList.IndexBuffer() 108 | indexBufferOffset := uintptr(indexBuffer) 109 | 110 | gl.VertexPointer(2, gl.FLOAT, int32(vertexSize), unsafe.Pointer(uintptr(vertexBuffer)+uintptr(vertexOffsetPos))) 111 | gl.TexCoordPointer(2, gl.FLOAT, int32(vertexSize), unsafe.Pointer(uintptr(vertexBuffer)+uintptr(vertexOffsetUv))) 112 | gl.ColorPointer(4, gl.UNSIGNED_BYTE, int32(vertexSize), unsafe.Pointer(uintptr(vertexBuffer)+uintptr(vertexOffsetCol))) 113 | 114 | for _, command := range commandList.Commands() { 115 | if command.HasUserCallback() { 116 | command.CallUserCallback(commandList) 117 | } else { 118 | clipRect := command.ClipRect() 119 | gl.Scissor(int32(clipRect.X), int32(fbHeight)-int32(clipRect.W), int32(clipRect.Z-clipRect.X), int32(clipRect.W-clipRect.Y)) 120 | gl.BindTexture(gl.TEXTURE_2D, uint32(command.TextureID())) 121 | gl.DrawElementsWithOffset(gl.TRIANGLES, int32(command.ElementCount()), uint32(drawType), indexBufferOffset) 122 | } 123 | 124 | indexBufferOffset += uintptr(command.ElementCount() * indexSize) 125 | } 126 | } 127 | 128 | // Restore modified state 129 | gl.DisableClientState(gl.COLOR_ARRAY) 130 | gl.DisableClientState(gl.TEXTURE_COORD_ARRAY) 131 | gl.DisableClientState(gl.VERTEX_ARRAY) 132 | gl.BindTexture(gl.TEXTURE_2D, uint32(lastTexture)) 133 | gl.MatrixMode(gl.MODELVIEW) 134 | gl.PopMatrix() 135 | gl.MatrixMode(gl.PROJECTION) 136 | gl.PopMatrix() 137 | gl.PopAttrib() 138 | gl.PolygonMode(gl.FRONT, uint32(lastPolygonMode[0])) 139 | gl.PolygonMode(gl.BACK, uint32(lastPolygonMode[1])) 140 | gl.Viewport(lastViewport[0], lastViewport[1], lastViewport[2], lastViewport[3]) 141 | gl.Scissor(lastScissorBox[0], lastScissorBox[1], lastScissorBox[2], lastScissorBox[3]) 142 | } 143 | 144 | func (renderer *OpenGL2) createFontsTexture() { 145 | // Build texture atlas 146 | image := renderer.imguiIO.Fonts().TextureDataRGBA32() 147 | 148 | // Upload texture to graphics system 149 | var lastTexture int32 150 | gl.GetIntegerv(gl.TEXTURE_BINDING_2D, &lastTexture) 151 | gl.GenTextures(1, &renderer.fontTexture) 152 | gl.BindTexture(gl.TEXTURE_2D, renderer.fontTexture) 153 | gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) 154 | gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) 155 | gl.PixelStorei(gl.UNPACK_ROW_LENGTH, 0) 156 | gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(image.Width), int32(image.Height), 0, gl.RGBA, gl.UNSIGNED_BYTE, image.Pixels) 157 | 158 | // Store our identifier 159 | renderer.imguiIO.Fonts().SetTextureID(imgui.TextureID(renderer.fontTexture)) 160 | 161 | // Restore state 162 | gl.BindTexture(gl.TEXTURE_2D, uint32(lastTexture)) 163 | } 164 | 165 | func (renderer *OpenGL2) destroyFontsTexture() { 166 | if renderer.fontTexture != 0 { 167 | gl.DeleteTextures(1, &renderer.fontTexture) 168 | imgui.CurrentIO().Fonts().SetTextureID(0) 169 | renderer.fontTexture = 0 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /internal/renderers/OpenGL3.go: -------------------------------------------------------------------------------- 1 | package renderers 2 | 3 | import ( 4 | _ "embed" // using embed for the shader sources 5 | "fmt" 6 | 7 | "github.com/inkyblackness/imgui-go-examples/internal/renderers/gl/v3.2-core/gl" 8 | "github.com/inkyblackness/imgui-go/v4" 9 | ) 10 | 11 | //go:embed gl-shader/main.vert 12 | var unversionedVertexShader string 13 | 14 | //go:embed gl-shader/main.frag 15 | var unversionedFragmentShader string 16 | 17 | // OpenGL3 implements a renderer based on github.com/go-gl/gl (v3.2-core). 18 | type OpenGL3 struct { 19 | imguiIO imgui.IO 20 | 21 | glslVersion string 22 | fontTexture uint32 23 | shaderHandle uint32 24 | vertHandle uint32 25 | fragHandle uint32 26 | attribLocationTex int32 27 | attribLocationProjMtx int32 28 | attribLocationPosition int32 29 | attribLocationUV int32 30 | attribLocationColor int32 31 | vboHandle uint32 32 | elementsHandle uint32 33 | } 34 | 35 | // NewOpenGL3 attempts to initialize a renderer. 36 | // An OpenGL context has to be established before calling this function. 37 | func NewOpenGL3(io imgui.IO) (*OpenGL3, error) { 38 | err := gl.Init() 39 | if err != nil { 40 | return nil, fmt.Errorf("failed to initialize OpenGL: %w", err) 41 | } 42 | 43 | renderer := &OpenGL3{ 44 | imguiIO: io, 45 | glslVersion: "#version 150", 46 | } 47 | renderer.createDeviceObjects() 48 | 49 | io.SetBackendFlags(io.GetBackendFlags() | imgui.BackendFlagsRendererHasVtxOffset) 50 | 51 | return renderer, nil 52 | } 53 | 54 | // Dispose cleans up the resources. 55 | func (renderer *OpenGL3) Dispose() { 56 | renderer.invalidateDeviceObjects() 57 | } 58 | 59 | // PreRender clears the framebuffer. 60 | func (renderer *OpenGL3) PreRender(clearColor [3]float32) { 61 | gl.ClearColor(clearColor[0], clearColor[1], clearColor[2], 1.0) 62 | gl.Clear(gl.COLOR_BUFFER_BIT) 63 | } 64 | 65 | // Render translates the ImGui draw data to OpenGL3 commands. 66 | func (renderer *OpenGL3) Render(displaySize [2]float32, framebufferSize [2]float32, drawData imgui.DrawData) { 67 | // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) 68 | displayWidth, displayHeight := displaySize[0], displaySize[1] 69 | fbWidth, fbHeight := framebufferSize[0], framebufferSize[1] 70 | if (fbWidth <= 0) || (fbHeight <= 0) { 71 | return 72 | } 73 | drawData.ScaleClipRects(imgui.Vec2{ 74 | X: fbWidth / displayWidth, 75 | Y: fbHeight / displayHeight, 76 | }) 77 | 78 | // Backup GL state 79 | var lastActiveTexture int32 80 | gl.GetIntegerv(gl.ACTIVE_TEXTURE, &lastActiveTexture) 81 | gl.ActiveTexture(gl.TEXTURE0) 82 | var lastProgram int32 83 | gl.GetIntegerv(gl.CURRENT_PROGRAM, &lastProgram) 84 | var lastTexture int32 85 | gl.GetIntegerv(gl.TEXTURE_BINDING_2D, &lastTexture) 86 | var lastSampler int32 87 | gl.GetIntegerv(gl.SAMPLER_BINDING, &lastSampler) 88 | var lastArrayBuffer int32 89 | gl.GetIntegerv(gl.ARRAY_BUFFER_BINDING, &lastArrayBuffer) 90 | var lastElementArrayBuffer int32 91 | gl.GetIntegerv(gl.ELEMENT_ARRAY_BUFFER_BINDING, &lastElementArrayBuffer) 92 | var lastVertexArray int32 93 | gl.GetIntegerv(gl.VERTEX_ARRAY_BINDING, &lastVertexArray) 94 | var lastPolygonMode [2]int32 95 | gl.GetIntegerv(gl.POLYGON_MODE, &lastPolygonMode[0]) 96 | var lastViewport [4]int32 97 | gl.GetIntegerv(gl.VIEWPORT, &lastViewport[0]) 98 | var lastScissorBox [4]int32 99 | gl.GetIntegerv(gl.SCISSOR_BOX, &lastScissorBox[0]) 100 | var lastBlendSrcRgb int32 101 | gl.GetIntegerv(gl.BLEND_SRC_RGB, &lastBlendSrcRgb) 102 | var lastBlendDstRgb int32 103 | gl.GetIntegerv(gl.BLEND_DST_RGB, &lastBlendDstRgb) 104 | var lastBlendSrcAlpha int32 105 | gl.GetIntegerv(gl.BLEND_SRC_ALPHA, &lastBlendSrcAlpha) 106 | var lastBlendDstAlpha int32 107 | gl.GetIntegerv(gl.BLEND_DST_ALPHA, &lastBlendDstAlpha) 108 | var lastBlendEquationRgb int32 109 | gl.GetIntegerv(gl.BLEND_EQUATION_RGB, &lastBlendEquationRgb) 110 | var lastBlendEquationAlpha int32 111 | gl.GetIntegerv(gl.BLEND_EQUATION_ALPHA, &lastBlendEquationAlpha) 112 | lastEnableBlend := gl.IsEnabled(gl.BLEND) 113 | lastEnableCullFace := gl.IsEnabled(gl.CULL_FACE) 114 | lastEnableDepthTest := gl.IsEnabled(gl.DEPTH_TEST) 115 | lastEnableScissorTest := gl.IsEnabled(gl.SCISSOR_TEST) 116 | 117 | // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill 118 | gl.Enable(gl.BLEND) 119 | gl.BlendEquation(gl.FUNC_ADD) 120 | gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) 121 | gl.Disable(gl.CULL_FACE) 122 | gl.Disable(gl.DEPTH_TEST) 123 | gl.Enable(gl.SCISSOR_TEST) 124 | gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL) 125 | 126 | // Setup viewport, orthographic projection matrix 127 | // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). 128 | // DisplayMin is typically (0,0) for single viewport apps. 129 | gl.Viewport(0, 0, int32(fbWidth), int32(fbHeight)) 130 | orthoProjection := [4][4]float32{ 131 | {2.0 / displayWidth, 0.0, 0.0, 0.0}, 132 | {0.0, 2.0 / -displayHeight, 0.0, 0.0}, 133 | {0.0, 0.0, -1.0, 0.0}, 134 | {-1.0, 1.0, 0.0, 1.0}, 135 | } 136 | gl.UseProgram(renderer.shaderHandle) 137 | gl.Uniform1i(renderer.attribLocationTex, 0) 138 | gl.UniformMatrix4fv(renderer.attribLocationProjMtx, 1, false, &orthoProjection[0][0]) 139 | gl.BindSampler(0, 0) // Rely on combined texture/sampler state. 140 | 141 | // Recreate the VAO every time 142 | // (This is to easily allow multiple GL contexts. VAO are not shared among GL contexts, and 143 | // we don't track creation/deletion of windows so we don't have an obvious key to use to cache them.) 144 | var vaoHandle uint32 145 | gl.GenVertexArrays(1, &vaoHandle) 146 | gl.BindVertexArray(vaoHandle) 147 | gl.BindBuffer(gl.ARRAY_BUFFER, renderer.vboHandle) 148 | gl.EnableVertexAttribArray(uint32(renderer.attribLocationPosition)) 149 | gl.EnableVertexAttribArray(uint32(renderer.attribLocationUV)) 150 | gl.EnableVertexAttribArray(uint32(renderer.attribLocationColor)) 151 | vertexSize, vertexOffsetPos, vertexOffsetUv, vertexOffsetCol := imgui.VertexBufferLayout() 152 | gl.VertexAttribPointerWithOffset(uint32(renderer.attribLocationPosition), 2, gl.FLOAT, false, int32(vertexSize), uintptr(vertexOffsetPos)) 153 | gl.VertexAttribPointerWithOffset(uint32(renderer.attribLocationUV), 2, gl.FLOAT, false, int32(vertexSize), uintptr(vertexOffsetUv)) 154 | gl.VertexAttribPointerWithOffset(uint32(renderer.attribLocationColor), 4, gl.UNSIGNED_BYTE, true, int32(vertexSize), uintptr(vertexOffsetCol)) 155 | indexSize := imgui.IndexBufferLayout() 156 | drawType := gl.UNSIGNED_SHORT 157 | const bytesPerUint32 = 4 158 | if indexSize == bytesPerUint32 { 159 | drawType = gl.UNSIGNED_INT 160 | } 161 | 162 | // Draw 163 | for _, list := range drawData.CommandLists() { 164 | vertexBuffer, vertexBufferSize := list.VertexBuffer() 165 | gl.BindBuffer(gl.ARRAY_BUFFER, renderer.vboHandle) 166 | gl.BufferData(gl.ARRAY_BUFFER, vertexBufferSize, vertexBuffer, gl.STREAM_DRAW) 167 | 168 | indexBuffer, indexBufferSize := list.IndexBuffer() 169 | gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, renderer.elementsHandle) 170 | gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, indexBufferSize, indexBuffer, gl.STREAM_DRAW) 171 | 172 | for _, cmd := range list.Commands() { 173 | if cmd.HasUserCallback() { 174 | cmd.CallUserCallback(list) 175 | } else { 176 | gl.BindTexture(gl.TEXTURE_2D, uint32(cmd.TextureID())) 177 | clipRect := cmd.ClipRect() 178 | gl.Scissor(int32(clipRect.X), int32(fbHeight)-int32(clipRect.W), int32(clipRect.Z-clipRect.X), int32(clipRect.W-clipRect.Y)) 179 | gl.DrawElementsBaseVertexWithOffset(gl.TRIANGLES, int32(cmd.ElementCount()), uint32(drawType), 180 | uintptr(cmd.IndexOffset()*indexSize), int32(cmd.VertexOffset())) 181 | } 182 | } 183 | } 184 | gl.DeleteVertexArrays(1, &vaoHandle) 185 | 186 | // Restore modified GL state 187 | gl.UseProgram(uint32(lastProgram)) 188 | gl.BindTexture(gl.TEXTURE_2D, uint32(lastTexture)) 189 | gl.BindSampler(0, uint32(lastSampler)) 190 | gl.ActiveTexture(uint32(lastActiveTexture)) 191 | gl.BindVertexArray(uint32(lastVertexArray)) 192 | gl.BindBuffer(gl.ARRAY_BUFFER, uint32(lastArrayBuffer)) 193 | gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, uint32(lastElementArrayBuffer)) 194 | gl.BlendEquationSeparate(uint32(lastBlendEquationRgb), uint32(lastBlendEquationAlpha)) 195 | gl.BlendFuncSeparate(uint32(lastBlendSrcRgb), uint32(lastBlendDstRgb), uint32(lastBlendSrcAlpha), uint32(lastBlendDstAlpha)) 196 | if lastEnableBlend { 197 | gl.Enable(gl.BLEND) 198 | } else { 199 | gl.Disable(gl.BLEND) 200 | } 201 | if lastEnableCullFace { 202 | gl.Enable(gl.CULL_FACE) 203 | } else { 204 | gl.Disable(gl.CULL_FACE) 205 | } 206 | if lastEnableDepthTest { 207 | gl.Enable(gl.DEPTH_TEST) 208 | } else { 209 | gl.Disable(gl.DEPTH_TEST) 210 | } 211 | if lastEnableScissorTest { 212 | gl.Enable(gl.SCISSOR_TEST) 213 | } else { 214 | gl.Disable(gl.SCISSOR_TEST) 215 | } 216 | gl.PolygonMode(gl.FRONT_AND_BACK, uint32(lastPolygonMode[0])) 217 | gl.Viewport(lastViewport[0], lastViewport[1], lastViewport[2], lastViewport[3]) 218 | gl.Scissor(lastScissorBox[0], lastScissorBox[1], lastScissorBox[2], lastScissorBox[3]) 219 | } 220 | 221 | func (renderer *OpenGL3) createDeviceObjects() { 222 | // Backup GL state 223 | var lastTexture int32 224 | var lastArrayBuffer int32 225 | var lastVertexArray int32 226 | gl.GetIntegerv(gl.TEXTURE_BINDING_2D, &lastTexture) 227 | gl.GetIntegerv(gl.ARRAY_BUFFER_BINDING, &lastArrayBuffer) 228 | gl.GetIntegerv(gl.VERTEX_ARRAY_BINDING, &lastVertexArray) 229 | 230 | vertexShader := renderer.glslVersion + "\n" + unversionedVertexShader 231 | fragmentShader := renderer.glslVersion + "\n" + unversionedFragmentShader 232 | 233 | renderer.shaderHandle = gl.CreateProgram() 234 | renderer.vertHandle = gl.CreateShader(gl.VERTEX_SHADER) 235 | renderer.fragHandle = gl.CreateShader(gl.FRAGMENT_SHADER) 236 | 237 | glShaderSource := func(handle uint32, source string) { 238 | csource, free := gl.Strs(source + "\x00") 239 | defer free() 240 | 241 | gl.ShaderSource(handle, 1, csource, nil) 242 | } 243 | 244 | glShaderSource(renderer.vertHandle, vertexShader) 245 | glShaderSource(renderer.fragHandle, fragmentShader) 246 | gl.CompileShader(renderer.vertHandle) 247 | gl.CompileShader(renderer.fragHandle) 248 | gl.AttachShader(renderer.shaderHandle, renderer.vertHandle) 249 | gl.AttachShader(renderer.shaderHandle, renderer.fragHandle) 250 | gl.LinkProgram(renderer.shaderHandle) 251 | 252 | renderer.attribLocationTex = gl.GetUniformLocation(renderer.shaderHandle, gl.Str("Texture"+"\x00")) 253 | renderer.attribLocationProjMtx = gl.GetUniformLocation(renderer.shaderHandle, gl.Str("ProjMtx"+"\x00")) 254 | renderer.attribLocationPosition = gl.GetAttribLocation(renderer.shaderHandle, gl.Str("Position"+"\x00")) 255 | renderer.attribLocationUV = gl.GetAttribLocation(renderer.shaderHandle, gl.Str("UV"+"\x00")) 256 | renderer.attribLocationColor = gl.GetAttribLocation(renderer.shaderHandle, gl.Str("Color"+"\x00")) 257 | 258 | gl.GenBuffers(1, &renderer.vboHandle) 259 | gl.GenBuffers(1, &renderer.elementsHandle) 260 | 261 | renderer.createFontsTexture() 262 | 263 | // Restore modified GL state 264 | gl.BindTexture(gl.TEXTURE_2D, uint32(lastTexture)) 265 | gl.BindBuffer(gl.ARRAY_BUFFER, uint32(lastArrayBuffer)) 266 | gl.BindVertexArray(uint32(lastVertexArray)) 267 | } 268 | 269 | func (renderer *OpenGL3) createFontsTexture() { 270 | // Build texture atlas 271 | io := imgui.CurrentIO() 272 | image := io.Fonts().TextureDataAlpha8() 273 | 274 | // Upload texture to graphics system 275 | var lastTexture int32 276 | gl.GetIntegerv(gl.TEXTURE_BINDING_2D, &lastTexture) 277 | gl.GenTextures(1, &renderer.fontTexture) 278 | gl.BindTexture(gl.TEXTURE_2D, renderer.fontTexture) 279 | gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) 280 | gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) 281 | gl.PixelStorei(gl.UNPACK_ROW_LENGTH, 0) 282 | gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RED, int32(image.Width), int32(image.Height), 283 | 0, gl.RED, gl.UNSIGNED_BYTE, image.Pixels) 284 | 285 | // Store our identifier 286 | io.Fonts().SetTextureID(imgui.TextureID(renderer.fontTexture)) 287 | 288 | // Restore state 289 | gl.BindTexture(gl.TEXTURE_2D, uint32(lastTexture)) 290 | } 291 | 292 | func (renderer *OpenGL3) invalidateDeviceObjects() { 293 | if renderer.vboHandle != 0 { 294 | gl.DeleteBuffers(1, &renderer.vboHandle) 295 | } 296 | renderer.vboHandle = 0 297 | if renderer.elementsHandle != 0 { 298 | gl.DeleteBuffers(1, &renderer.elementsHandle) 299 | } 300 | renderer.elementsHandle = 0 301 | 302 | if (renderer.shaderHandle != 0) && (renderer.vertHandle != 0) { 303 | gl.DetachShader(renderer.shaderHandle, renderer.vertHandle) 304 | } 305 | if renderer.vertHandle != 0 { 306 | gl.DeleteShader(renderer.vertHandle) 307 | } 308 | renderer.vertHandle = 0 309 | 310 | if (renderer.shaderHandle != 0) && (renderer.fragHandle != 0) { 311 | gl.DetachShader(renderer.shaderHandle, renderer.fragHandle) 312 | } 313 | if renderer.fragHandle != 0 { 314 | gl.DeleteShader(renderer.fragHandle) 315 | } 316 | renderer.fragHandle = 0 317 | 318 | if renderer.shaderHandle != 0 { 319 | gl.DeleteProgram(renderer.shaderHandle) 320 | } 321 | renderer.shaderHandle = 0 322 | 323 | if renderer.fontTexture != 0 { 324 | gl.DeleteTextures(1, &renderer.fontTexture) 325 | imgui.CurrentIO().Fonts().SetTextureID(0) 326 | renderer.fontTexture = 0 327 | } 328 | } 329 | -------------------------------------------------------------------------------- /internal/renderers/doc.go: -------------------------------------------------------------------------------- 1 | // Package renderers implement the drawing code for specific rendering APIs. 2 | // The renderers in here are dependent on the context the platform provides and 3 | // process the drawing commands from imgui by driving the rendering API. 4 | package renderers 5 | -------------------------------------------------------------------------------- /internal/renderers/gl-shader/main.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D Texture; 2 | 3 | in vec2 Frag_UV; 4 | in vec4 Frag_Color; 5 | 6 | out vec4 Out_Color; 7 | 8 | void main() 9 | { 10 | Out_Color = vec4(Frag_Color.rgb, Frag_Color.a * texture(Texture, Frag_UV.st).r); 11 | } 12 | -------------------------------------------------------------------------------- /internal/renderers/gl-shader/main.vert: -------------------------------------------------------------------------------- 1 | uniform mat4 ProjMtx; 2 | 3 | in vec2 Position; 4 | in vec2 UV; 5 | in vec4 Color; 6 | 7 | out vec2 Frag_UV; 8 | out vec4 Frag_Color; 9 | 10 | void main() 11 | { 12 | Frag_UV = UV; 13 | Frag_Color = Color; 14 | gl_Position = ProjMtx * vec4(Position.xy, 0, 1); 15 | } 16 | -------------------------------------------------------------------------------- /internal/renderers/gl/README.md: -------------------------------------------------------------------------------- 1 | ## Generating OpenGL bindings 2 | 3 | Instead of depending on the pre-generated binding of [go-gl/gl](https://github.com/go-gl/gl), which is not always up to date, the examples application makes use of the code- & binding-generator [go-gl/glow](https://github.com/go-gl/glow). 4 | 5 | To update the bindings with the newest generator, do the following: 6 | 7 | 1. `go get` or install `github.com/go-gl/glow` locally 8 | 1. run binding generator for the necessary versions; For example, within the root directory of `go-gl/glow`: 9 | ``` 10 | go run . generate -out=...path/to/imgui-go-examples/internal/renderers/gl/v3.2-core/gl -api=gl -version=3.2 -profile=core -xml=./xml/ -tmpl=./tmpl/ 11 | go run . generate -out=...path/to/imgui-go-examples/internal/renderers/gl/v2.1/gl -api=gl -version=2.1 -xml=./xml/ -tmpl=./tmpl/ 12 | ``` 13 | -------------------------------------------------------------------------------- /internal/renderers/gl/v2.1/gl/KHR/khrplatform.h: -------------------------------------------------------------------------------- 1 | #ifndef __khrplatform_h_ 2 | #define __khrplatform_h_ 3 | 4 | /* 5 | ** Copyright (c) 2008-2018 The Khronos Group Inc. 6 | ** 7 | ** Permission is hereby granted, free of charge, to any person obtaining a 8 | ** copy of this software and/or associated documentation files (the 9 | ** "Materials"), to deal in the Materials without restriction, including 10 | ** without limitation the rights to use, copy, modify, merge, publish, 11 | ** distribute, sublicense, and/or sell copies of the Materials, and to 12 | ** permit persons to whom the Materials are furnished to do so, subject to 13 | ** the following conditions: 14 | ** 15 | ** The above copyright notice and this permission notice shall be included 16 | ** in all copies or substantial portions of the Materials. 17 | ** 18 | ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 25 | */ 26 | 27 | /* Khronos platform-specific types and definitions. 28 | * 29 | * The master copy of khrplatform.h is maintained in the Khronos EGL 30 | * Registry repository at https://github.com/KhronosGroup/EGL-Registry 31 | * The last semantic modification to khrplatform.h was at commit ID: 32 | * 67a3e0864c2d75ea5287b9f3d2eb74a745936692 33 | * 34 | * Adopters may modify this file to suit their platform. Adopters are 35 | * encouraged to submit platform specific modifications to the Khronos 36 | * group so that they can be included in future versions of this file. 37 | * Please submit changes by filing pull requests or issues on 38 | * the EGL Registry repository linked above. 39 | * 40 | * 41 | * See the Implementer's Guidelines for information about where this file 42 | * should be located on your system and for more details of its use: 43 | * http://www.khronos.org/registry/implementers_guide.pdf 44 | * 45 | * This file should be included as 46 | * #include 47 | * by Khronos client API header files that use its types and defines. 48 | * 49 | * The types in khrplatform.h should only be used to define API-specific types. 50 | * 51 | * Types defined in khrplatform.h: 52 | * khronos_int8_t signed 8 bit 53 | * khronos_uint8_t unsigned 8 bit 54 | * khronos_int16_t signed 16 bit 55 | * khronos_uint16_t unsigned 16 bit 56 | * khronos_int32_t signed 32 bit 57 | * khronos_uint32_t unsigned 32 bit 58 | * khronos_int64_t signed 64 bit 59 | * khronos_uint64_t unsigned 64 bit 60 | * khronos_intptr_t signed same number of bits as a pointer 61 | * khronos_uintptr_t unsigned same number of bits as a pointer 62 | * khronos_ssize_t signed size 63 | * khronos_usize_t unsigned size 64 | * khronos_float_t signed 32 bit floating point 65 | * khronos_time_ns_t unsigned 64 bit time in nanoseconds 66 | * khronos_utime_nanoseconds_t unsigned time interval or absolute time in 67 | * nanoseconds 68 | * khronos_stime_nanoseconds_t signed time interval in nanoseconds 69 | * khronos_boolean_enum_t enumerated boolean type. This should 70 | * only be used as a base type when a client API's boolean type is 71 | * an enum. Client APIs which use an integer or other type for 72 | * booleans cannot use this as the base type for their boolean. 73 | * 74 | * Tokens defined in khrplatform.h: 75 | * 76 | * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. 77 | * 78 | * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. 79 | * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. 80 | * 81 | * Calling convention macros defined in this file: 82 | * KHRONOS_APICALL 83 | * KHRONOS_APIENTRY 84 | * KHRONOS_APIATTRIBUTES 85 | * 86 | * These may be used in function prototypes as: 87 | * 88 | * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( 89 | * int arg1, 90 | * int arg2) KHRONOS_APIATTRIBUTES; 91 | */ 92 | 93 | #if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC) 94 | # define KHRONOS_STATIC 1 95 | #endif 96 | 97 | /*------------------------------------------------------------------------- 98 | * Definition of KHRONOS_APICALL 99 | *------------------------------------------------------------------------- 100 | * This precedes the return type of the function in the function prototype. 101 | */ 102 | #if defined(KHRONOS_STATIC) 103 | /* If the preprocessor constant KHRONOS_STATIC is defined, make the 104 | * header compatible with static linking. */ 105 | # define KHRONOS_APICALL 106 | #elif defined(_WIN32) 107 | # define KHRONOS_APICALL __declspec(dllimport) 108 | #elif defined (__SYMBIAN32__) 109 | # define KHRONOS_APICALL IMPORT_C 110 | #elif defined(__ANDROID__) 111 | # define KHRONOS_APICALL __attribute__((visibility("default"))) 112 | #else 113 | # define KHRONOS_APICALL 114 | #endif 115 | 116 | /*------------------------------------------------------------------------- 117 | * Definition of KHRONOS_APIENTRY 118 | *------------------------------------------------------------------------- 119 | * This follows the return type of the function and precedes the function 120 | * name in the function prototype. 121 | */ 122 | #if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) 123 | /* Win32 but not WinCE */ 124 | # define KHRONOS_APIENTRY __stdcall 125 | #else 126 | # define KHRONOS_APIENTRY 127 | #endif 128 | 129 | /*------------------------------------------------------------------------- 130 | * Definition of KHRONOS_APIATTRIBUTES 131 | *------------------------------------------------------------------------- 132 | * This follows the closing parenthesis of the function prototype arguments. 133 | */ 134 | #if defined (__ARMCC_2__) 135 | #define KHRONOS_APIATTRIBUTES __softfp 136 | #else 137 | #define KHRONOS_APIATTRIBUTES 138 | #endif 139 | 140 | /*------------------------------------------------------------------------- 141 | * basic type definitions 142 | *-----------------------------------------------------------------------*/ 143 | #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) 144 | 145 | 146 | /* 147 | * Using 148 | */ 149 | #include 150 | typedef int32_t khronos_int32_t; 151 | typedef uint32_t khronos_uint32_t; 152 | typedef int64_t khronos_int64_t; 153 | typedef uint64_t khronos_uint64_t; 154 | #define KHRONOS_SUPPORT_INT64 1 155 | #define KHRONOS_SUPPORT_FLOAT 1 156 | 157 | #elif defined(__VMS ) || defined(__sgi) 158 | 159 | /* 160 | * Using 161 | */ 162 | #include 163 | typedef int32_t khronos_int32_t; 164 | typedef uint32_t khronos_uint32_t; 165 | typedef int64_t khronos_int64_t; 166 | typedef uint64_t khronos_uint64_t; 167 | #define KHRONOS_SUPPORT_INT64 1 168 | #define KHRONOS_SUPPORT_FLOAT 1 169 | 170 | #elif defined(_WIN32) && !defined(__SCITECH_SNAP__) 171 | 172 | /* 173 | * Win32 174 | */ 175 | typedef __int32 khronos_int32_t; 176 | typedef unsigned __int32 khronos_uint32_t; 177 | typedef __int64 khronos_int64_t; 178 | typedef unsigned __int64 khronos_uint64_t; 179 | #define KHRONOS_SUPPORT_INT64 1 180 | #define KHRONOS_SUPPORT_FLOAT 1 181 | 182 | #elif defined(__sun__) || defined(__digital__) 183 | 184 | /* 185 | * Sun or Digital 186 | */ 187 | typedef int khronos_int32_t; 188 | typedef unsigned int khronos_uint32_t; 189 | #if defined(__arch64__) || defined(_LP64) 190 | typedef long int khronos_int64_t; 191 | typedef unsigned long int khronos_uint64_t; 192 | #else 193 | typedef long long int khronos_int64_t; 194 | typedef unsigned long long int khronos_uint64_t; 195 | #endif /* __arch64__ */ 196 | #define KHRONOS_SUPPORT_INT64 1 197 | #define KHRONOS_SUPPORT_FLOAT 1 198 | 199 | #elif 0 200 | 201 | /* 202 | * Hypothetical platform with no float or int64 support 203 | */ 204 | typedef int khronos_int32_t; 205 | typedef unsigned int khronos_uint32_t; 206 | #define KHRONOS_SUPPORT_INT64 0 207 | #define KHRONOS_SUPPORT_FLOAT 0 208 | 209 | #else 210 | 211 | /* 212 | * Generic fallback 213 | */ 214 | #include 215 | typedef int32_t khronos_int32_t; 216 | typedef uint32_t khronos_uint32_t; 217 | typedef int64_t khronos_int64_t; 218 | typedef uint64_t khronos_uint64_t; 219 | #define KHRONOS_SUPPORT_INT64 1 220 | #define KHRONOS_SUPPORT_FLOAT 1 221 | 222 | #endif 223 | 224 | 225 | /* 226 | * Types that are (so far) the same on all platforms 227 | */ 228 | typedef signed char khronos_int8_t; 229 | typedef unsigned char khronos_uint8_t; 230 | typedef signed short int khronos_int16_t; 231 | typedef unsigned short int khronos_uint16_t; 232 | 233 | /* 234 | * Types that differ between LLP64 and LP64 architectures - in LLP64, 235 | * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears 236 | * to be the only LLP64 architecture in current use. 237 | */ 238 | #ifdef _WIN64 239 | typedef signed long long int khronos_intptr_t; 240 | typedef unsigned long long int khronos_uintptr_t; 241 | typedef signed long long int khronos_ssize_t; 242 | typedef unsigned long long int khronos_usize_t; 243 | #else 244 | typedef signed long int khronos_intptr_t; 245 | typedef unsigned long int khronos_uintptr_t; 246 | typedef signed long int khronos_ssize_t; 247 | typedef unsigned long int khronos_usize_t; 248 | #endif 249 | 250 | #if KHRONOS_SUPPORT_FLOAT 251 | /* 252 | * Float type 253 | */ 254 | typedef float khronos_float_t; 255 | #endif 256 | 257 | #if KHRONOS_SUPPORT_INT64 258 | /* Time types 259 | * 260 | * These types can be used to represent a time interval in nanoseconds or 261 | * an absolute Unadjusted System Time. Unadjusted System Time is the number 262 | * of nanoseconds since some arbitrary system event (e.g. since the last 263 | * time the system booted). The Unadjusted System Time is an unsigned 264 | * 64 bit value that wraps back to 0 every 584 years. Time intervals 265 | * may be either signed or unsigned. 266 | */ 267 | typedef khronos_uint64_t khronos_utime_nanoseconds_t; 268 | typedef khronos_int64_t khronos_stime_nanoseconds_t; 269 | #endif 270 | 271 | /* 272 | * Dummy value used to pad enum types to 32 bits. 273 | */ 274 | #ifndef KHRONOS_MAX_ENUM 275 | #define KHRONOS_MAX_ENUM 0x7FFFFFFF 276 | #endif 277 | 278 | /* 279 | * Enumerated boolean type 280 | * 281 | * Values other than zero should be considered to be true. Therefore 282 | * comparisons should not be made against KHRONOS_TRUE. 283 | */ 284 | typedef enum { 285 | KHRONOS_FALSE = 0, 286 | KHRONOS_TRUE = 1, 287 | KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM 288 | } khronos_boolean_enum_t; 289 | 290 | #endif /* __khrplatform_h_ */ 291 | -------------------------------------------------------------------------------- /internal/renderers/gl/v2.1/gl/conversions.go: -------------------------------------------------------------------------------- 1 | // Code generated by glow (https://github.com/go-gl/glow). DO NOT EDIT. 2 | 3 | package gl 4 | 5 | import ( 6 | "fmt" 7 | "reflect" 8 | "strings" 9 | "unsafe" 10 | ) 11 | 12 | // #include 13 | import "C" 14 | 15 | // Ptr takes a slice or pointer (to a singular scalar value or the first 16 | // element of an array or slice) and returns its GL-compatible address. 17 | // 18 | // For example: 19 | // 20 | // var data []uint8 21 | // ... 22 | // gl.TexImage2D(gl.TEXTURE_2D, ..., gl.UNSIGNED_BYTE, gl.Ptr(&data[0])) 23 | func Ptr(data interface{}) unsafe.Pointer { 24 | if data == nil { 25 | return unsafe.Pointer(nil) 26 | } 27 | var addr unsafe.Pointer 28 | v := reflect.ValueOf(data) 29 | switch v.Type().Kind() { 30 | case reflect.Ptr: 31 | e := v.Elem() 32 | switch e.Kind() { 33 | case 34 | reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 35 | reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, 36 | reflect.Float32, reflect.Float64: 37 | addr = unsafe.Pointer(e.UnsafeAddr()) 38 | default: 39 | panic(fmt.Errorf("unsupported pointer to type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", e.Kind())) 40 | } 41 | case reflect.Uintptr: 42 | addr = unsafe.Pointer(data.(uintptr)) 43 | case reflect.Slice: 44 | addr = unsafe.Pointer(v.Index(0).UnsafeAddr()) 45 | default: 46 | panic(fmt.Errorf("unsupported type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", v.Type())) 47 | } 48 | return addr 49 | } 50 | 51 | // PtrOffset takes a pointer offset and returns a GL-compatible pointer. 52 | // Originally intended for functions such as glVertexAttribPointer that take pointer 53 | // parameters also for offsets, since Go 1.14 this is no longer recommended. 54 | // 55 | // Use a corresponding offset-compatible variant of the function instead. 56 | // For example, for gl.VertexAttribPointer() there is gl.VertexAttribPointerWithOffset(). 57 | // 58 | // See https://github.com/go-gl/gl#go-114-and-checkptr for more details on the checkptr detector. 59 | // See https://github.com/go-gl/glow#overloads, about adding new overloads. 60 | // 61 | // Deprecated: Use more appropriate overload function instead 62 | func PtrOffset(offset int) unsafe.Pointer { 63 | return unsafe.Pointer(uintptr(offset)) 64 | } 65 | 66 | // Str takes a null-terminated Go string and returns its GL-compatible address. 67 | // This function reaches into Go string storage in an unsafe way so the caller 68 | // must ensure the string is not garbage collected. 69 | func Str(str string) *uint8 { 70 | if !strings.HasSuffix(str, "\x00") { 71 | panic("str argument missing null terminator: " + str) 72 | } 73 | header := (*reflect.StringHeader)(unsafe.Pointer(&str)) 74 | return (*uint8)(unsafe.Pointer(header.Data)) 75 | } 76 | 77 | // GoStr takes a null-terminated string returned by OpenGL and constructs a 78 | // corresponding Go string. 79 | func GoStr(cstr *uint8) string { 80 | return C.GoString((*C.char)(unsafe.Pointer(cstr))) 81 | } 82 | 83 | // Strs takes a list of Go strings (with or without null-termination) and 84 | // returns their C counterpart. 85 | // 86 | // The returned free function must be called once you are done using the strings 87 | // in order to free the memory. 88 | // 89 | // If no strings are provided as a parameter this function will panic. 90 | func Strs(strs ...string) (cstrs **uint8, free func()) { 91 | if len(strs) == 0 { 92 | panic("Strs: expected at least 1 string") 93 | } 94 | 95 | // Allocate a contiguous array large enough to hold all the strings' contents. 96 | n := 0 97 | for i := range strs { 98 | n += len(strs[i]) 99 | } 100 | if n == 0 { 101 | n = 1 // avoid allocating zero bytes in case all strings are empty. 102 | } 103 | data := C.malloc(C.size_t(n)) 104 | 105 | // Copy all the strings into data. 106 | dataSlice := (*[1 << 30]byte)(data)[:n] 107 | css := make([]*uint8, len(strs)) // Populated with pointers to each string. 108 | offset := 0 109 | for i := range strs { 110 | copy(dataSlice[offset:offset+len(strs[i])], strs[i][:]) // Copy strs[i] into proper data location. 111 | css[i] = (*uint8)(unsafe.Pointer(&dataSlice[offset])) // Set a pointer to it. 112 | offset += len(strs[i]) 113 | } 114 | 115 | return (**uint8)(&css[0]), func() { C.free(data) } 116 | } 117 | -------------------------------------------------------------------------------- /internal/renderers/gl/v2.1/gl/debug.go: -------------------------------------------------------------------------------- 1 | // Code generated by glow (https://github.com/go-gl/glow). DO NOT EDIT. 2 | 3 | package gl 4 | 5 | import "C" 6 | import "unsafe" 7 | 8 | type DebugProc func( 9 | source uint32, 10 | gltype uint32, 11 | id uint32, 12 | severity uint32, 13 | length int32, 14 | message string, 15 | userParam unsafe.Pointer) 16 | 17 | var userDebugCallback DebugProc 18 | 19 | //export glowDebugCallback_gl21 20 | func glowDebugCallback_gl21( 21 | source uint32, 22 | gltype uint32, 23 | id uint32, 24 | severity uint32, 25 | length int32, 26 | message *uint8, 27 | userParam unsafe.Pointer) { 28 | if userDebugCallback != nil { 29 | userDebugCallback(source, gltype, id, severity, length, GoStr(message), userParam) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /internal/renderers/gl/v2.1/gl/procaddr.go: -------------------------------------------------------------------------------- 1 | // Code generated by glow (https://github.com/go-gl/glow). DO NOT EDIT. 2 | 3 | // This file implements GlowGetProcAddress for every supported platform. The 4 | // correct version is chosen automatically based on build tags: 5 | // 6 | // windows: WGL 7 | // darwin: CGL 8 | // linux freebsd openbsd: GLX 9 | // 10 | // Use of EGL instead of the platform's default (listed above) is made possible 11 | // via the "egl" build tag. 12 | // 13 | // It is also possible to install your own function outside this package for 14 | // retrieving OpenGL function pointers, to do this see InitWithProcAddrFunc. 15 | 16 | package gl 17 | 18 | /* 19 | #cgo windows CFLAGS: -DTAG_WINDOWS 20 | #cgo !gles2,windows LDFLAGS: -lopengl32 21 | #cgo gles2,windows LDFLAGS: -lGLESv2 22 | #cgo darwin CFLAGS: -DTAG_DARWIN 23 | #cgo !gles2,darwin LDFLAGS: -framework OpenGL 24 | #cgo gles2,darwin LDFLAGS: -framework OpenGLES 25 | #cgo linux freebsd openbsd CFLAGS: -DTAG_POSIX 26 | #cgo !egl,linux !egl,freebsd !egl,openbsd pkg-config: gl 27 | #cgo egl,linux egl,freebsd egl,openbsd egl,windows CFLAGS: -DTAG_EGL 28 | #cgo egl,linux egl,freebsd egl,openbsd pkg-config: egl 29 | #cgo egl,windows LDFLAGS: -lEGL 30 | #cgo egl,darwin LDFLAGS: -lEGL 31 | // Check the EGL tag first as it takes priority over the platform's default 32 | // configuration of WGL/GLX/CGL. 33 | #if defined(TAG_EGL) 34 | #include 35 | #include 36 | void* GlowGetProcAddress_gl21(const char* name) { 37 | return eglGetProcAddress(name); 38 | } 39 | #elif defined(TAG_WINDOWS) 40 | #define WIN32_LEAN_AND_MEAN 1 41 | #include 42 | #include 43 | static HMODULE ogl32dll = NULL; 44 | void* GlowGetProcAddress_gl21(const char* name) { 45 | void* pf = wglGetProcAddress((LPCSTR) name); 46 | if (pf) { 47 | return pf; 48 | } 49 | if (ogl32dll == NULL) { 50 | ogl32dll = LoadLibraryA("opengl32.dll"); 51 | } 52 | return GetProcAddress(ogl32dll, (LPCSTR) name); 53 | } 54 | #elif defined(TAG_DARWIN) 55 | #include 56 | #include 57 | void* GlowGetProcAddress_gl21(const char* name) { 58 | return dlsym(RTLD_DEFAULT, name); 59 | } 60 | #elif defined(TAG_POSIX) 61 | #include 62 | #include 63 | void* GlowGetProcAddress_gl21(const char* name) { 64 | return glXGetProcAddress((const GLubyte *) name); 65 | } 66 | #endif 67 | */ 68 | import "C" 69 | import "unsafe" 70 | 71 | func getProcAddress(namea string) unsafe.Pointer { 72 | cname := C.CString(namea) 73 | defer C.free(unsafe.Pointer(cname)) 74 | return C.GlowGetProcAddress_gl21(cname) 75 | } 76 | -------------------------------------------------------------------------------- /internal/renderers/gl/v3.2-core/gl/KHR/khrplatform.h: -------------------------------------------------------------------------------- 1 | #ifndef __khrplatform_h_ 2 | #define __khrplatform_h_ 3 | 4 | /* 5 | ** Copyright (c) 2008-2018 The Khronos Group Inc. 6 | ** 7 | ** Permission is hereby granted, free of charge, to any person obtaining a 8 | ** copy of this software and/or associated documentation files (the 9 | ** "Materials"), to deal in the Materials without restriction, including 10 | ** without limitation the rights to use, copy, modify, merge, publish, 11 | ** distribute, sublicense, and/or sell copies of the Materials, and to 12 | ** permit persons to whom the Materials are furnished to do so, subject to 13 | ** the following conditions: 14 | ** 15 | ** The above copyright notice and this permission notice shall be included 16 | ** in all copies or substantial portions of the Materials. 17 | ** 18 | ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 25 | */ 26 | 27 | /* Khronos platform-specific types and definitions. 28 | * 29 | * The master copy of khrplatform.h is maintained in the Khronos EGL 30 | * Registry repository at https://github.com/KhronosGroup/EGL-Registry 31 | * The last semantic modification to khrplatform.h was at commit ID: 32 | * 67a3e0864c2d75ea5287b9f3d2eb74a745936692 33 | * 34 | * Adopters may modify this file to suit their platform. Adopters are 35 | * encouraged to submit platform specific modifications to the Khronos 36 | * group so that they can be included in future versions of this file. 37 | * Please submit changes by filing pull requests or issues on 38 | * the EGL Registry repository linked above. 39 | * 40 | * 41 | * See the Implementer's Guidelines for information about where this file 42 | * should be located on your system and for more details of its use: 43 | * http://www.khronos.org/registry/implementers_guide.pdf 44 | * 45 | * This file should be included as 46 | * #include 47 | * by Khronos client API header files that use its types and defines. 48 | * 49 | * The types in khrplatform.h should only be used to define API-specific types. 50 | * 51 | * Types defined in khrplatform.h: 52 | * khronos_int8_t signed 8 bit 53 | * khronos_uint8_t unsigned 8 bit 54 | * khronos_int16_t signed 16 bit 55 | * khronos_uint16_t unsigned 16 bit 56 | * khronos_int32_t signed 32 bit 57 | * khronos_uint32_t unsigned 32 bit 58 | * khronos_int64_t signed 64 bit 59 | * khronos_uint64_t unsigned 64 bit 60 | * khronos_intptr_t signed same number of bits as a pointer 61 | * khronos_uintptr_t unsigned same number of bits as a pointer 62 | * khronos_ssize_t signed size 63 | * khronos_usize_t unsigned size 64 | * khronos_float_t signed 32 bit floating point 65 | * khronos_time_ns_t unsigned 64 bit time in nanoseconds 66 | * khronos_utime_nanoseconds_t unsigned time interval or absolute time in 67 | * nanoseconds 68 | * khronos_stime_nanoseconds_t signed time interval in nanoseconds 69 | * khronos_boolean_enum_t enumerated boolean type. This should 70 | * only be used as a base type when a client API's boolean type is 71 | * an enum. Client APIs which use an integer or other type for 72 | * booleans cannot use this as the base type for their boolean. 73 | * 74 | * Tokens defined in khrplatform.h: 75 | * 76 | * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. 77 | * 78 | * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. 79 | * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. 80 | * 81 | * Calling convention macros defined in this file: 82 | * KHRONOS_APICALL 83 | * KHRONOS_APIENTRY 84 | * KHRONOS_APIATTRIBUTES 85 | * 86 | * These may be used in function prototypes as: 87 | * 88 | * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( 89 | * int arg1, 90 | * int arg2) KHRONOS_APIATTRIBUTES; 91 | */ 92 | 93 | #if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC) 94 | # define KHRONOS_STATIC 1 95 | #endif 96 | 97 | /*------------------------------------------------------------------------- 98 | * Definition of KHRONOS_APICALL 99 | *------------------------------------------------------------------------- 100 | * This precedes the return type of the function in the function prototype. 101 | */ 102 | #if defined(KHRONOS_STATIC) 103 | /* If the preprocessor constant KHRONOS_STATIC is defined, make the 104 | * header compatible with static linking. */ 105 | # define KHRONOS_APICALL 106 | #elif defined(_WIN32) 107 | # define KHRONOS_APICALL __declspec(dllimport) 108 | #elif defined (__SYMBIAN32__) 109 | # define KHRONOS_APICALL IMPORT_C 110 | #elif defined(__ANDROID__) 111 | # define KHRONOS_APICALL __attribute__((visibility("default"))) 112 | #else 113 | # define KHRONOS_APICALL 114 | #endif 115 | 116 | /*------------------------------------------------------------------------- 117 | * Definition of KHRONOS_APIENTRY 118 | *------------------------------------------------------------------------- 119 | * This follows the return type of the function and precedes the function 120 | * name in the function prototype. 121 | */ 122 | #if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) 123 | /* Win32 but not WinCE */ 124 | # define KHRONOS_APIENTRY __stdcall 125 | #else 126 | # define KHRONOS_APIENTRY 127 | #endif 128 | 129 | /*------------------------------------------------------------------------- 130 | * Definition of KHRONOS_APIATTRIBUTES 131 | *------------------------------------------------------------------------- 132 | * This follows the closing parenthesis of the function prototype arguments. 133 | */ 134 | #if defined (__ARMCC_2__) 135 | #define KHRONOS_APIATTRIBUTES __softfp 136 | #else 137 | #define KHRONOS_APIATTRIBUTES 138 | #endif 139 | 140 | /*------------------------------------------------------------------------- 141 | * basic type definitions 142 | *-----------------------------------------------------------------------*/ 143 | #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) 144 | 145 | 146 | /* 147 | * Using 148 | */ 149 | #include 150 | typedef int32_t khronos_int32_t; 151 | typedef uint32_t khronos_uint32_t; 152 | typedef int64_t khronos_int64_t; 153 | typedef uint64_t khronos_uint64_t; 154 | #define KHRONOS_SUPPORT_INT64 1 155 | #define KHRONOS_SUPPORT_FLOAT 1 156 | 157 | #elif defined(__VMS ) || defined(__sgi) 158 | 159 | /* 160 | * Using 161 | */ 162 | #include 163 | typedef int32_t khronos_int32_t; 164 | typedef uint32_t khronos_uint32_t; 165 | typedef int64_t khronos_int64_t; 166 | typedef uint64_t khronos_uint64_t; 167 | #define KHRONOS_SUPPORT_INT64 1 168 | #define KHRONOS_SUPPORT_FLOAT 1 169 | 170 | #elif defined(_WIN32) && !defined(__SCITECH_SNAP__) 171 | 172 | /* 173 | * Win32 174 | */ 175 | typedef __int32 khronos_int32_t; 176 | typedef unsigned __int32 khronos_uint32_t; 177 | typedef __int64 khronos_int64_t; 178 | typedef unsigned __int64 khronos_uint64_t; 179 | #define KHRONOS_SUPPORT_INT64 1 180 | #define KHRONOS_SUPPORT_FLOAT 1 181 | 182 | #elif defined(__sun__) || defined(__digital__) 183 | 184 | /* 185 | * Sun or Digital 186 | */ 187 | typedef int khronos_int32_t; 188 | typedef unsigned int khronos_uint32_t; 189 | #if defined(__arch64__) || defined(_LP64) 190 | typedef long int khronos_int64_t; 191 | typedef unsigned long int khronos_uint64_t; 192 | #else 193 | typedef long long int khronos_int64_t; 194 | typedef unsigned long long int khronos_uint64_t; 195 | #endif /* __arch64__ */ 196 | #define KHRONOS_SUPPORT_INT64 1 197 | #define KHRONOS_SUPPORT_FLOAT 1 198 | 199 | #elif 0 200 | 201 | /* 202 | * Hypothetical platform with no float or int64 support 203 | */ 204 | typedef int khronos_int32_t; 205 | typedef unsigned int khronos_uint32_t; 206 | #define KHRONOS_SUPPORT_INT64 0 207 | #define KHRONOS_SUPPORT_FLOAT 0 208 | 209 | #else 210 | 211 | /* 212 | * Generic fallback 213 | */ 214 | #include 215 | typedef int32_t khronos_int32_t; 216 | typedef uint32_t khronos_uint32_t; 217 | typedef int64_t khronos_int64_t; 218 | typedef uint64_t khronos_uint64_t; 219 | #define KHRONOS_SUPPORT_INT64 1 220 | #define KHRONOS_SUPPORT_FLOAT 1 221 | 222 | #endif 223 | 224 | 225 | /* 226 | * Types that are (so far) the same on all platforms 227 | */ 228 | typedef signed char khronos_int8_t; 229 | typedef unsigned char khronos_uint8_t; 230 | typedef signed short int khronos_int16_t; 231 | typedef unsigned short int khronos_uint16_t; 232 | 233 | /* 234 | * Types that differ between LLP64 and LP64 architectures - in LLP64, 235 | * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears 236 | * to be the only LLP64 architecture in current use. 237 | */ 238 | #ifdef _WIN64 239 | typedef signed long long int khronos_intptr_t; 240 | typedef unsigned long long int khronos_uintptr_t; 241 | typedef signed long long int khronos_ssize_t; 242 | typedef unsigned long long int khronos_usize_t; 243 | #else 244 | typedef signed long int khronos_intptr_t; 245 | typedef unsigned long int khronos_uintptr_t; 246 | typedef signed long int khronos_ssize_t; 247 | typedef unsigned long int khronos_usize_t; 248 | #endif 249 | 250 | #if KHRONOS_SUPPORT_FLOAT 251 | /* 252 | * Float type 253 | */ 254 | typedef float khronos_float_t; 255 | #endif 256 | 257 | #if KHRONOS_SUPPORT_INT64 258 | /* Time types 259 | * 260 | * These types can be used to represent a time interval in nanoseconds or 261 | * an absolute Unadjusted System Time. Unadjusted System Time is the number 262 | * of nanoseconds since some arbitrary system event (e.g. since the last 263 | * time the system booted). The Unadjusted System Time is an unsigned 264 | * 64 bit value that wraps back to 0 every 584 years. Time intervals 265 | * may be either signed or unsigned. 266 | */ 267 | typedef khronos_uint64_t khronos_utime_nanoseconds_t; 268 | typedef khronos_int64_t khronos_stime_nanoseconds_t; 269 | #endif 270 | 271 | /* 272 | * Dummy value used to pad enum types to 32 bits. 273 | */ 274 | #ifndef KHRONOS_MAX_ENUM 275 | #define KHRONOS_MAX_ENUM 0x7FFFFFFF 276 | #endif 277 | 278 | /* 279 | * Enumerated boolean type 280 | * 281 | * Values other than zero should be considered to be true. Therefore 282 | * comparisons should not be made against KHRONOS_TRUE. 283 | */ 284 | typedef enum { 285 | KHRONOS_FALSE = 0, 286 | KHRONOS_TRUE = 1, 287 | KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM 288 | } khronos_boolean_enum_t; 289 | 290 | #endif /* __khrplatform_h_ */ 291 | -------------------------------------------------------------------------------- /internal/renderers/gl/v3.2-core/gl/conversions.go: -------------------------------------------------------------------------------- 1 | // Code generated by glow (https://github.com/go-gl/glow). DO NOT EDIT. 2 | 3 | package gl 4 | 5 | import ( 6 | "fmt" 7 | "reflect" 8 | "strings" 9 | "unsafe" 10 | ) 11 | 12 | // #include 13 | import "C" 14 | 15 | // Ptr takes a slice or pointer (to a singular scalar value or the first 16 | // element of an array or slice) and returns its GL-compatible address. 17 | // 18 | // For example: 19 | // 20 | // var data []uint8 21 | // ... 22 | // gl.TexImage2D(gl.TEXTURE_2D, ..., gl.UNSIGNED_BYTE, gl.Ptr(&data[0])) 23 | func Ptr(data interface{}) unsafe.Pointer { 24 | if data == nil { 25 | return unsafe.Pointer(nil) 26 | } 27 | var addr unsafe.Pointer 28 | v := reflect.ValueOf(data) 29 | switch v.Type().Kind() { 30 | case reflect.Ptr: 31 | e := v.Elem() 32 | switch e.Kind() { 33 | case 34 | reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 35 | reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, 36 | reflect.Float32, reflect.Float64: 37 | addr = unsafe.Pointer(e.UnsafeAddr()) 38 | default: 39 | panic(fmt.Errorf("unsupported pointer to type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", e.Kind())) 40 | } 41 | case reflect.Uintptr: 42 | addr = unsafe.Pointer(data.(uintptr)) 43 | case reflect.Slice: 44 | addr = unsafe.Pointer(v.Index(0).UnsafeAddr()) 45 | default: 46 | panic(fmt.Errorf("unsupported type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", v.Type())) 47 | } 48 | return addr 49 | } 50 | 51 | // PtrOffset takes a pointer offset and returns a GL-compatible pointer. 52 | // Originally intended for functions such as glVertexAttribPointer that take pointer 53 | // parameters also for offsets, since Go 1.14 this is no longer recommended. 54 | // 55 | // Use a corresponding offset-compatible variant of the function instead. 56 | // For example, for gl.VertexAttribPointer() there is gl.VertexAttribPointerWithOffset(). 57 | // 58 | // See https://github.com/go-gl/gl#go-114-and-checkptr for more details on the checkptr detector. 59 | // See https://github.com/go-gl/glow#overloads, about adding new overloads. 60 | // 61 | // Deprecated: Use more appropriate overload function instead 62 | func PtrOffset(offset int) unsafe.Pointer { 63 | return unsafe.Pointer(uintptr(offset)) 64 | } 65 | 66 | // Str takes a null-terminated Go string and returns its GL-compatible address. 67 | // This function reaches into Go string storage in an unsafe way so the caller 68 | // must ensure the string is not garbage collected. 69 | func Str(str string) *uint8 { 70 | if !strings.HasSuffix(str, "\x00") { 71 | panic("str argument missing null terminator: " + str) 72 | } 73 | header := (*reflect.StringHeader)(unsafe.Pointer(&str)) 74 | return (*uint8)(unsafe.Pointer(header.Data)) 75 | } 76 | 77 | // GoStr takes a null-terminated string returned by OpenGL and constructs a 78 | // corresponding Go string. 79 | func GoStr(cstr *uint8) string { 80 | return C.GoString((*C.char)(unsafe.Pointer(cstr))) 81 | } 82 | 83 | // Strs takes a list of Go strings (with or without null-termination) and 84 | // returns their C counterpart. 85 | // 86 | // The returned free function must be called once you are done using the strings 87 | // in order to free the memory. 88 | // 89 | // If no strings are provided as a parameter this function will panic. 90 | func Strs(strs ...string) (cstrs **uint8, free func()) { 91 | if len(strs) == 0 { 92 | panic("Strs: expected at least 1 string") 93 | } 94 | 95 | // Allocate a contiguous array large enough to hold all the strings' contents. 96 | n := 0 97 | for i := range strs { 98 | n += len(strs[i]) 99 | } 100 | if n == 0 { 101 | n = 1 // avoid allocating zero bytes in case all strings are empty. 102 | } 103 | data := C.malloc(C.size_t(n)) 104 | 105 | // Copy all the strings into data. 106 | dataSlice := (*[1 << 30]byte)(data)[:n] 107 | css := make([]*uint8, len(strs)) // Populated with pointers to each string. 108 | offset := 0 109 | for i := range strs { 110 | copy(dataSlice[offset:offset+len(strs[i])], strs[i][:]) // Copy strs[i] into proper data location. 111 | css[i] = (*uint8)(unsafe.Pointer(&dataSlice[offset])) // Set a pointer to it. 112 | offset += len(strs[i]) 113 | } 114 | 115 | return (**uint8)(&css[0]), func() { C.free(data) } 116 | } 117 | -------------------------------------------------------------------------------- /internal/renderers/gl/v3.2-core/gl/debug.go: -------------------------------------------------------------------------------- 1 | // Code generated by glow (https://github.com/go-gl/glow). DO NOT EDIT. 2 | 3 | package gl 4 | 5 | import "C" 6 | import "unsafe" 7 | 8 | type DebugProc func( 9 | source uint32, 10 | gltype uint32, 11 | id uint32, 12 | severity uint32, 13 | length int32, 14 | message string, 15 | userParam unsafe.Pointer) 16 | 17 | var userDebugCallback DebugProc 18 | 19 | //export glowDebugCallback_glcore32 20 | func glowDebugCallback_glcore32( 21 | source uint32, 22 | gltype uint32, 23 | id uint32, 24 | severity uint32, 25 | length int32, 26 | message *uint8, 27 | userParam unsafe.Pointer) { 28 | if userDebugCallback != nil { 29 | userDebugCallback(source, gltype, id, severity, length, GoStr(message), userParam) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /internal/renderers/gl/v3.2-core/gl/procaddr.go: -------------------------------------------------------------------------------- 1 | // Code generated by glow (https://github.com/go-gl/glow). DO NOT EDIT. 2 | 3 | // This file implements GlowGetProcAddress for every supported platform. The 4 | // correct version is chosen automatically based on build tags: 5 | // 6 | // windows: WGL 7 | // darwin: CGL 8 | // linux freebsd openbsd: GLX 9 | // 10 | // Use of EGL instead of the platform's default (listed above) is made possible 11 | // via the "egl" build tag. 12 | // 13 | // It is also possible to install your own function outside this package for 14 | // retrieving OpenGL function pointers, to do this see InitWithProcAddrFunc. 15 | 16 | package gl 17 | 18 | /* 19 | #cgo windows CFLAGS: -DTAG_WINDOWS 20 | #cgo !gles2,windows LDFLAGS: -lopengl32 21 | #cgo gles2,windows LDFLAGS: -lGLESv2 22 | #cgo darwin CFLAGS: -DTAG_DARWIN 23 | #cgo !gles2,darwin LDFLAGS: -framework OpenGL 24 | #cgo gles2,darwin LDFLAGS: -framework OpenGLES 25 | #cgo linux freebsd openbsd CFLAGS: -DTAG_POSIX 26 | #cgo !egl,linux !egl,freebsd !egl,openbsd pkg-config: gl 27 | #cgo egl,linux egl,freebsd egl,openbsd egl,windows CFLAGS: -DTAG_EGL 28 | #cgo egl,linux egl,freebsd egl,openbsd pkg-config: egl 29 | #cgo egl,windows LDFLAGS: -lEGL 30 | #cgo egl,darwin LDFLAGS: -lEGL 31 | // Check the EGL tag first as it takes priority over the platform's default 32 | // configuration of WGL/GLX/CGL. 33 | #if defined(TAG_EGL) 34 | #include 35 | #include 36 | void* GlowGetProcAddress_glcore32(const char* name) { 37 | return eglGetProcAddress(name); 38 | } 39 | #elif defined(TAG_WINDOWS) 40 | #define WIN32_LEAN_AND_MEAN 1 41 | #include 42 | #include 43 | static HMODULE ogl32dll = NULL; 44 | void* GlowGetProcAddress_glcore32(const char* name) { 45 | void* pf = wglGetProcAddress((LPCSTR) name); 46 | if (pf) { 47 | return pf; 48 | } 49 | if (ogl32dll == NULL) { 50 | ogl32dll = LoadLibraryA("opengl32.dll"); 51 | } 52 | return GetProcAddress(ogl32dll, (LPCSTR) name); 53 | } 54 | #elif defined(TAG_DARWIN) 55 | #include 56 | #include 57 | void* GlowGetProcAddress_glcore32(const char* name) { 58 | return dlsym(RTLD_DEFAULT, name); 59 | } 60 | #elif defined(TAG_POSIX) 61 | #include 62 | #include 63 | void* GlowGetProcAddress_glcore32(const char* name) { 64 | return glXGetProcAddress((const GLubyte *) name); 65 | } 66 | #endif 67 | */ 68 | import "C" 69 | import "unsafe" 70 | 71 | func getProcAddress(namea string) unsafe.Pointer { 72 | cname := C.CString(namea) 73 | defer C.free(unsafe.Pointer(cname)) 74 | return C.GlowGetProcAddress_glcore32(cname) 75 | } 76 | --------------------------------------------------------------------------------