http://www.perlmonks.org?node_id=11149365

haj has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks,

Occasionally I am playing with 3D graphics. I had some fun doing it in a Tk::Canvas, but ... as the complexity of the 3D objects increases, that's getting painfully slow. So I've been looking for alternatives, starting with OpenGL.

I could not fail noticing that the Perl OpenGL project is a bit stale, with a newsfeed ending in 2007. On the plus side, I succeeded in translating the examples from The Official Guide to Learning OpenGL, Version 1.1 from C to Perl rather easily. Fortunately, this guide is about the same age as the Perl module.

Things get a bit murky when I want to integrate OpenGL drawing into my Tk application. The examples directory in the OpenGL distribution contains a tk_demo.pl script, and hooray, this script works out of the box.

But: This script integrates the OpenGL window with a subroutine glpOpenWindow. This subroutine is part of the Perl module OpenGL, but not exactly documented, and also not part of any OpenGL standard. The C examples in the Guide (and many other examples I found online) use GLUT functions like glutCreateWindow: this function is well documented in OpenGL, and also offered by the OpenGL module. Unfortunately glutCreateWindow creates a top-level window, whereas I would like to use it within my Tk widget. Windows created with glpOpenWindow can use a Tk widget as "parent", but I have no idea how to do the equivalent of GLUT functions like glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); for this window. The call doesn't fail, it just doesn't do anything. Some GLUT functions, e.g. glutFullScreen, bail out with a freeglut message ERROR: Function <glutFullScreen> called with no current window defined.

So that's the question: Has someone a pointer or example how to use the GLUT window subroutines within a Tk widget? Or, as an alternative, how to get a depth buffer activated with a glpOpenWindow window?

BTW: Prima offers Prima::GLWidget which is a direct widget for OpenGL drawing. This works nicely, and I could re-write my Tk applicaton for Prima. Only, I'm not familiar with Prima, and would prefer to avoid the effort.

Replies are listed 'Best First'.
Re: Graphics: OpenGL in Perl/Tk ... with GLUT
by NERDVANA (Deacon) on Jan 06, 2023 at 06:16 UTC
    This is an interesting question. It's been a very long time since I wanted to have an OpenGL widget within a standard user interface, and back then I was using Delphi. I don't really have an answer for your specific question, but just some general thoughts you might find helpful.

    GLUT is a very old attempt at making a cross-platform API for writing purely OpenGL applications. GLUT has a lot of limitations, and there is a sort of spiritual successor called GLFW that you should probably look at first before doing GLUT (and yes it has a perl module ). However, this spiritual successor also focuses on being a top-level-window standalone type of environment, so it might not meet your needs either.

    If you happened to be running on X11 (or wayland with the compatibility layer) and don't care about cross-platform, I think my X11::GLX::DWIM module should have everything you need. Just create your X11 window with Tk and then use that as the target for creating the OpenGL context.

    If you are running Windows and don't care about cross-platform, I think you can just change the parent of the OpenGL window after it is created and hopefully make TK aware of that change. I would guess that GLUT or GLFW wouldn't mind if their window is suddenly the child of another window.

    I have no idea what is involved on Mac to do this.

    Once you have a working OpenGL context, you might find my OpenGL::Sandbox module useful. It has GL 1.4 support in OpenGL::Sandbox::V1, and font support in OpenGL::Sandbox::V1::FTGLFont. If you want to do modern shader stuff, it has really handy wrappers for Programs, Shaders, and uniforms. To see how it all fits together, there is a commandline implementation of shadertoy.com. It can be a bit of work to get these modules working, especially if you are on Windows and need to round up various DLLs. Sorry about that.

    (patches welcome :-) especially build documentation for platforms other than my own)

      Many thanks for these pointers!

      I am aware that GLUT is somewhat outdated. But then - OpenGL as a whole is about to be spelled Vulkan today. The funny thing is that GLUT still works fine, and it fits the OpenGL Programming Guide quite nicely. This ~15 year old guide comprehensively covers OpenGL and window management. I'll definitely try GLFW and its Perl module. I'll also check out your X11 module and the Sandbox.

      Installing OpenGL::Sandbox from CPAN on my Machine (Debian bullseye) gives one test failure:

      Writing directly to a foreign buffer is not recommended at t/35-buffer.t line 39.

      This might be an issue of my box because the CPAN Testers Matrix for OpenGL::Sandbox is clean.

      BTW: I also tried OpenGL::Modern and was not convinced. It seems to cover "modern" OpenGL, but it needs some guessing around which export tags are needed for which interface, which interfaces are available and how interfaces using C pointers need to be rewritten. Plain old OpenGL comes with an examples directory which got myself started, the "Modern" thing has nothing like it, not even tests to steal from.

        The CPAN testers matrix for OpenGL::Sandbox can be misleading because it can use either OpenGL or OpenGL::Modern, and when it uses OpenGL it skips some of the tests because (for example) buffer objects aren't available from the OpenGL module.

        I just checked with my current install of 5.36, and t/35 and t/36 are both crashing. I'll take a look at it. If you aren't using new stuff it won't matter for you.

        I agree that OpenGL::Modern is less friendly. The author took a more "exactly the same as the C API" approach, and while that makes it easier to port C code to Perl, I doubt anyone wants to write C code in Perl if Perl isn't adding "friendly" wrappers. That was sort of why I made the OpenGL::Sandbox. If you look at the source code of the shadertoy script, it is massively simpler than the corresponding C code, and a lot safer than manipulating raw pointers in Perl.

        The downside of modern / shaders is that I never wrote a Font module for it. So, the only way to get text is to use ::V1 and the matrix stack and all that.

Re: Graphics: OpenGL in Perl/Tk ... with GLUT
by cavac (Parson) on Jan 12, 2023 at 11:28 UTC

    A little off topic, but: If you like OpenGL, you could try out WebGL in a browser. Yes, you'd have to use JavaScript, but you could still do a lot of the data munching in Perl and push data on thy fly to the browser side using Websockets+JSON.It's easy enough for a single threaded Perl script (or fork-on-demand if you so choose) to serve multiple clients, so you can even push you real time data to multiple computers all at once ;-)

    I can't help you with 3D graphics stuff, but if you ever want to go the route of networking, i'm certainly one of the brains you can pick ;-)

    PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP

      Thanks for this suggestion! My browser experiments so far were focused on Web3D (and the X3D format to store 3D models).

      I understand that WebGL is similar to OpenGL as a low-level graphics API, targeted at the HTML5 canvas. But like with "pure" OpenGL ... it doesn't come with an event loop and GUI toolkit. That's what I use Tk for, and what I would have to rewrite for the HTML canvas.

      Also, being based on OpenGL ES which is "a well-defined subset of desktop OpenGL suitable for low-power devices", it seems to lack the interactive glRenderMode feature which I need to use. Or maybe I just failed to find it?

        JavaScript doesn't have what you would call an "event loop", it uses callbacks to react to events. As for cyclic stuff (rendering, physics, etc), you just use setInterval().

        As far as communication with the Perl backend, i make extensive use of Websockets. It really depends on your webserver setup on how you do that, but with my own webserver i use a (slightly adapted) version of Protocol::WebSocket::Frame

        PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP
Re: Graphics: OpenGL in Perl/Tk ... with GLUT ( tk zinc)
by Anonymous Monk on Jan 06, 2023 at 13:07 UTC

      Tk::Zinc is nicely integrated into Tk, that's good. But I recall that when I tried Tk::Zinc in the past, I wasn't all that convinced. Things have not improved since then.

      As of today, it doesn't install cleanly on my current machine (Debian Bullseye) from CPAN. I can force-install (i.e. skip tests), but then the zinc-demos application dies for all OpenGL related demos. The current CPAN testers report doesn't look promising as well. The URL http://www.tkzinc.org/ mentioned in the manual has been grabbed by someone else. So, apparently it is a somewhat ... dry area.

      I see that Tk::Zinc tries to make use of OpenGL: It calls OpenGL functions in its own C sources. However, there's no indication in the documentation nor in the demo sources that it offers using OpenGL interfaces through Perl.

      So, unfortunately, the Tk::Zinc canvas is not what I want.