Last active
July 7, 2020 21:54
-
-
Save wsphillips/1948b31ff23b00a303112e60ea518545 to your computer and use it in GitHub Desktop.
CImGui.jl : Attempt to load and display a random array of numbers as an image
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using CImGui | |
using CImGui.CSyntax | |
using CImGui.CSyntax.CStatic | |
using CImGui.GLFWBackend | |
using CImGui.OpenGLBackend | |
using CImGui.GLFWBackend.GLFW | |
using CImGui.OpenGLBackend.ModernGL | |
using Printf | |
import CImGui.OpenGLBackend.ModernGL: glGenTextures | |
import CImGui: ImVec2, ImVec4, ImTextureID | |
# Extra dispatch for GenTextures for convenience (as in GLExtendedFunctions.jl) | |
function glGenTextures() | |
result = UInt32[0] | |
glGenTextures(1, result) | |
id = result[1] | |
if id <= 0 | |
error("glGenTextures returned invalid id. OpenGL Context active?") | |
end | |
return id | |
end | |
# image loading similar to imgui example for OpenGL | |
function load_texture(tex_id, img::AbstractArray{UInt16,2}) | |
height::Cint = size(img, 1) | |
width::Cint = size(img, 2) | |
glBindTexture(GL_TEXTURE_2D, tex_id) | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) | |
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) | |
# Here we are loading a single pixel value image so GL_R16 = UInt16 (common grayscale | |
# format) | |
glTexImage2D(GL_TEXTURE_2D, GLint(0), GL_RGBA, width, height, | |
GLint(0), GL_RED, GL_UNSIGNED_SHORT, img) | |
end | |
# OpenGL 3.0 + GLSL 130 | |
const glsl_version = 130 | |
GLFW.WindowHint(GLFW.CONTEXT_VERSION_MAJOR, 3) | |
GLFW.WindowHint(GLFW.CONTEXT_VERSION_MINOR, 0) | |
# setup GLFW error callback | |
error_callback(err::GLFW.GLFWError) = @error "GLFW ERROR: code $(err.code) msg: $(err.description)" | |
GLFW.SetErrorCallback(error_callback) | |
# create window | |
window = GLFW.CreateWindow(1280, 720, "Image Demo") | |
@assert window != C_NULL | |
GLFW.MakeContextCurrent(window) | |
GLFW.SwapInterval(0) # enable vsync | |
# setup Dear ImGui context | |
ctx = CImGui.CreateContext() | |
# setup Dear ImGui style | |
CImGui.StyleColorsDark() | |
# load Fonts | |
fonts_dir = joinpath(@__DIR__, "..", "fonts") | |
fonts = CImGui.GetIO().Fonts | |
CImGui.AddFontFromFileTTF(fonts, joinpath(fonts_dir, "Roboto-Medium.ttf"), 16) | |
# setup Platform/Renderer bindings | |
ImGui_ImplGlfw_InitForOpenGL(window, true) | |
ImGui_ImplOpenGL3_Init(glsl_version) | |
try | |
show_image_window = false | |
clear_color = Cfloat[0.45, 0.55, 0.60, 1.00] | |
img = rand(UInt16, 700, 700) | |
img_tex_id = glGenTextures() | |
while !GLFW.WindowShouldClose(window) | |
GLFW.PollEvents() | |
# start the Dear ImGui frame | |
ImGui_ImplOpenGL3_NewFrame() | |
ImGui_ImplGlfw_NewFrame() | |
CImGui.NewFrame() | |
# we use a Begin/End pair to created a named window. | |
@cstatic f=Cfloat(0.0) counter=Cint(0) begin | |
CImGui.Begin("Hello, world!") # create a window called "Hello, world!" and append into it. | |
CImGui.Text("Click to stream images.") # display some text | |
@c CImGui.Checkbox("Image Window", &show_image_window) | |
CImGui.Text(@sprintf("Application average %.3f ms/frame (%.1f FPS)", 1000 / CImGui.GetIO().Framerate, CImGui.GetIO().Framerate)) | |
CImGui.End() | |
end | |
# show another simple window. | |
if show_image_window | |
@c CImGui.Begin("Image Window", &show_image_window) | |
img .= rand(UInt16, 700, 700) | |
load_texture(img_tex_id, img) | |
CImGui.Image(ImTextureID(Int(img_tex_id)), ImVec2(700,700),ImVec2(0,0), ImVec2(1,1), ImVec4(255,255,255,255), ImVec4(255,255,255,128)) | |
CImGui.End() | |
end | |
# rendering | |
CImGui.Render() | |
GLFW.MakeContextCurrent(window) | |
display_w, display_h = GLFW.GetFramebufferSize(window) | |
glViewport(0, 0, display_w, display_h) | |
glClearColor(clear_color...) | |
glClear(GL_COLOR_BUFFER_BIT) | |
ImGui_ImplOpenGL3_RenderDrawData(CImGui.GetDrawData()) | |
GLFW.MakeContextCurrent(window) | |
GLFW.SwapBuffers(window) | |
end | |
catch e | |
@error "Error in renderloop!" exception=e | |
Base.show_backtrace(stderr, catch_backtrace()) | |
finally | |
ImGui_ImplOpenGL3_Shutdown() | |
ImGui_ImplGlfw_Shutdown() | |
CImGui.DestroyContext(ctx) | |
GLFW.DestroyWindow(window) | |
end |
Works now! With some added code for handling different image types and pixel swizzling/color mapping this could be really neat! (I intend to use for streaming monochrome camera video.)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This works, but I have a feeling I am quickly filling VRAM via not freeing textures or re-using the initial texture ID. Comments appreciated!