Open Brohammer5 opened 9 months ago
You can render your scene onto ImGui using ImGui.Image(); this requires a Frame Buffer which takes in the texture ID of your Frame Buffer as the first argument
ImGui.image(framebuffer.getTextureId(), regionAvail.x, regionAvail.y, 0, 1, 1, 0);
you can dig around my code below for a better example
Here's how I did it for threekt:
package com.displee.imgui.threekt.texture
import org.lwjgl.opengl.GL30.*
import org.lwjgl.opengl.GL32.GL_PROGRAM_POINT_SIZE
import java.nio.ByteBuffer
class ThreeKtTexture {
var texture_id = -1
var FBO = -1
var RBO = -1
var width = 0
var height = 0
fun create_framebuffer(width: Int, height: Int)
{
this.width = width
this.height = height
// threekt defaults
glEnable(GL_PROGRAM_POINT_SIZE)
glEnable(GL_POINT_SPRITE)
FBO = glGenFramebuffers()
glBindFramebuffer(GL_FRAMEBUFFER, FBO)
texture_id = glGenTextures()
glBindTexture(GL_TEXTURE_2D, texture_id)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null as ByteBuffer?)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0)
RBO = glGenRenderbuffers()
glBindRenderbuffer(GL_RENDERBUFFER, RBO)
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height)
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, RBO)
// if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
// std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!\n";
glBindFramebuffer(GL_FRAMEBUFFER, 0)
glBindTexture(GL_TEXTURE_2D, 0)
glBindRenderbuffer(GL_RENDERBUFFER, 0)
}
// here we bind our framebuffer
fun bind_framebuffer()
{
glBindFramebuffer(GL_FRAMEBUFFER, FBO)
}
// here we unbind our framebuffer
fun unbind_framebuffer()
{
glBindFramebuffer(GL_FRAMEBUFFER, 0)
}
// and we rescale the buffer, so we're able to resize the window
fun rescale_framebuffer(width: Int, height: Int)
{
this.width = width
this.height = height
glBindTexture(GL_TEXTURE_2D, texture_id)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null as ByteBuffer?)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0)
glBindRenderbuffer(GL_RENDERBUFFER, RBO)
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height)
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, RBO)
}
}
Then in your ImGui window:
ImGui.text("This a demo for ImGui Canvas editor")
ImGui.sameLine()
ImGui.text("Mouse Left: drag to add lines,\nMouse Right: drag to scroll, click for context menu.")
if (firstFrame) {
initThreeKt()
firstFrame = false
}
ImGui.image(threektTexture.texture_id, threektTexture.width.toFloat(), threektTexture.height.toFloat(), 0F, 1F, 1F, 0F)
controlsEventSource.handleMouseEvents()
val windowSize = ImGui.getWindowSize()
ImGui.end()
threektTexture.bind_framebuffer()
// threekt clear is called once and while imgui calls it every frame, so we have to call it ourselves
val bg = Color(Color.skyblue)
GL32.glClearColor(bg.r, bg.g, bg.b, 1F)
GL32.glClear(GL32.GL_COLOR_BUFFER_BIT or GL32.GL_DEPTH_BUFFER_BIT)
onResizeThreeKt(windowSize)
val dt = clock.getDelta()
box.rotation.x += 0.5f * dt
box.rotation.y += 0.5f * dt
renderer.render(scene, camera)
threektTexture.unbind_framebuffer()
Init OpenGL/threekt and only resize if needed
private fun initThreeKt() {
val imguiWindowSize = ImGui.getWindowSize()
val windowSize = WindowSize(imguiWindowSize.x.toInt(), imguiWindowSize.y.toInt())
camera = PerspectiveCamera(75, windowSize.aspect, 0.1, 1000).also {
it.translateZ(10f)
}
controlsEventSource = ImGuiEventSource(windowSize)
controls = OrbitControls(camera, controlsEventSource)
renderer = GLRenderer(windowSize)
threektTexture.create_framebuffer(imguiWindowSize.x.toInt(), imguiWindowSize.y.toInt())
}
private fun onResizeThreeKt(windowSize: ImVec2) {
val width = windowSize.x.toInt()
val height = windowSize.y.toInt()
if (width == lastWidth && height == lastHeight) {
return
}
camera.aspect = width.toFloat() / height.toFloat()
camera.updateProjectionMatrix()
camera.updateWorldMatrix()
renderer.setSize(width, height)
threektTexture.rescale_framebuffer(width, height)
lastWidth = width
lastHeight = height
}
Version
1.86.4
What happened?
I am trying to render an OpenGL scene into an ImGui Window. How would I achieve this as there seems to be no documentation on this repository? I have only seen C++ examples to implement this.
Reproduction
No Documentation
Relevant log output
No response