enablerbr's picture

Leadwerks integration (was: I need help converting method from Tao to OpenTK.)

this is the method i'm trying to convert from Tao to OpenTK.

public static void MakeCurrent()
        {
            Wgl.wglMakeCurrent(Wgl.wglGetCurrentDC(), Wgl.wglGetCurrentContext());
        }

what is the OpenTK versions of the above Tao Wgl methods? if it helps i'm using a gamewindow.

forgot to mention i'm using svn version of OpenTK and coding in c#.


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

GameWindow.MakeCurrent();

OpenTK does not give you raw access to OS-specific functionality (e.g. WGL). This ensures your code remains cross-platform.

enablerbr's picture

that might be why i'm having issues with a game engine c dll. i want to us OpenTK as the OpenGL context. however this means i need to use the following command to create a buffer.

CreateCustomBuffer(byte* getsize, byte* makcurrent); <-- from the game engine c dll.

i'm currently trying a safe approach by doing the following.

CreateCustomBuffer(IntPtr getsize, IntPtr makcurrent);

or maybe i should do it as follows.

CreateCustomBuffer(int[] getsize, int[] makcurrent);

the thing is the makecurrent part is the issue i'm having the most trouble with. if i wasn't using OpenTK for my OpenGL conext. i could use the following command from the game engine c dll.

CreateBuffer(int width, int height, BUFFER_COLOR0 | BUFFER_DEPTH | BUFFER_NORMAL);

the Fiddler's picture

What values do you need to pass to these parameters (getsize and makcurrent)?

In any case, you can still use the game engine to create and manage the context. On the OpenTK side, you will have to call GraphicsContext.CreateDummyContext, which I guess is similar to CreateCustomBuffer from the C dll. You'll also won't be able to use MakeCurrent() / SwapBuffers() from OpenTK, but the C dll should be able to handle those.

Disclaimer: CreateDummyContext may be slightly broken. If OpenTK complains or crashes, post the error message here and I will fix the issue. (In that case, line numbers appreciated - use the debug version of OpenTK.dll / OpenTK.pdb to obtain them.)

enablerbr's picture

i'm not sure where i would place GraphicsContext.CreateDummyContext. heres an example of how the code would look. if i was simply running a console app.

static void Main(string[] args)
        {
            TGraphic gpx = new TGraphic(1024,768,TGraphic.WINDOW);
            TWorld wld = new TWorld(TWorld.CREATENOW);
            TCamera cam = new TCamera();
            TLight spt = new TLight();
            TMesh cube = new TMesh();
            TMesh ground = new TMesh();
            TBuffer gbuffer = new TBuffer();
 
            TMiscellaneous.SetAppTitle("Basic App");
 
            // Create Camera
            cam.Create(IntPtr.Zero);
            cam.Zoom(DFHelper.FPSCameraFOV(60.0));
            cam.Move(new DFVector3D(0f, 0f, -5f), 0);
            //cam.Move(cam.Entity, new DFVector3D(0f, 0f, -5f), 0);
 
            // Create Spotlight
            spt.CreateSpot(10f, IntPtr.Zero);
            spt.Position(new DFVector3D(2f, 2f, -2f), 0);
            spt.Rotate(new DFVector3D(45f, 45f, 0f), 0);
 
            // Create Cube
            cube.CreateCube(IntPtr.Zero);
 
            // Create Ground
            ground.CreateCube(IntPtr.Zero);
            ground.Scale(new DFVector3D(10f, 0.1f, 10f));
            ground.Position(new DFVector3D(0f, -2f, 0f), 0);
 
            // Create Buffer
            gbuffer.Create(gpx.GetWidth(), gpx.GetHeight(), TBuffer.BUFFER_COLOR0 | TBuffer.BUFFER_DEPTH | TBuffer.BUFFER_NORMAL);
            // Main game loop
            while (!Convert.ToBoolean(TInput.KeyHit((int)Keyboard.KEY_ESCAPE)) & !Convert.ToBoolean(TMiscellaneous.AppTerminate()))
            {
                cube.Turn(new DFVector3D(0.5f, 0.5f, 0.5f), 0);
                TWorld.UpdateWorld(1f);
 
                TBuffer.SetBuffer(gbuffer.Buffer);
                TWorld.RenderWorld(TWorld.RENDER_ALL);
                TBuffer.SetBuffer(TBuffer.BackBuffer());
                TLight.RenderLights(gbuffer.Buffer);
                TGraphic.Flip(1);
            }
 
            gbuffer.Free();
            ground.Free();
            cube.Free();
            spt.Free();
            cam.Free();
            wld.Free();
            TGraphic.EndRender();
        }

heres the code trying to do it from within the OnRenderfame.

public override void OnRenderFrame(RenderFrameEventArgs e)
        {
            //TGraphic gpx = new TGraphic();
            TWorld wld = new TWorld();
            TCamera cam = new TCamera();
            TLight spt = new TLight();
            TMesh cube = new TMesh();
            TMesh ground = new TMesh();
            TBuffer buff = new TBuffer();
 
            // Setup Graphics View Size
            //gpx.Create(800, 600, 0, 60, TGraphic.GRAPHICS_BACKBUFFER | TGraphic.GRAPHICS_DEPTHBUFFER);
 
            // Create Engine World
            wld.Create();
 
            //GraphicsContext.CreateDummyContext();
            this.Context.MakeCurrent(this.WindowInfo);
 
            // Create Camera
            cam.Create(IntPtr.Zero);
            cam.Zoom(DFHelper.FPSCameraFOV(90f));
            cam.Move(new DFVector3D(0f, 0f, -5f), 0);
 
            // Create Spotlight
            spt.CreateSpot(10f, IntPtr.Zero);
            spt.Position(new DFVector3D(2f, 2f, -2f), 0);
            spt.Rotate(new DFVector3D(45f, 45f, 0f), 0);
 
            // Create Cube
            cube.CreateCube(IntPtr.Zero);
 
            // Create Ground
            ground.CreateCube(IntPtr.Zero);
            ground.Scale(new DFVector3D(10f, 0.1f, 10f));
            ground.Position(new DFVector3D(0f, -2f, 0f), 0);
 
            // Create Buffer
            //buff.Create(800, 600, TBuffer.BUFFER_COLOR0 | TBuffer.BUFFER_DEPTH | TBuffer.BUFFER_NORMAL);
            buff.CreateCustom(GetSize(this.Width,this.Height), MakeCurrent());
 
            // Main game loop
            while (!Convert.ToBoolean(Keyboard[Key.Escape]))
            {
                cube.Turn(new DFVector3D(0.5f, 0.5f, 0.5f), 0);
                TWorld.UpdateWorld(1f);
 
                TBuffer.SetBuffer(buff.Buffer);
                TWorld.RenderWorld(TWorld.RENDER_ALL);
                TBuffer.SetBuffer(TBuffer.BackBuffer());
                TLight.RenderLights(buff.Buffer);
 
                SwapBuffers();
            }
        }

i should add i'm trying to do this with the gamewindow example code and only changed the OnRenderframe part of it.

the Fiddler's picture

A few suggestions:

  1. Creation stuff belongs to OnLoad
  2. Keyboard, mouse, joystick input goes to OnUpdateFrame
  3. Rendering goes to OnRenderFrame
  4. No need to call MakeCurrent, unless you create more than 1 OpenGL context
  5. You have to decide whether you wish to use OpenTK fully or as a simple OpenGL binding. In the first case, you can use the GameWindow, GraphicsContext and everything else OpenTK has to offer. In the latter case, you cannot use the GameWindow or anything outside of OpenTK.Graphics.GL and OpenTK.Audio.AL: the code would look exactly like your first example.

Here is how the code should look if you use the GameWindow:

public class Game : GameWindow
{
    TWorld wld = new TWorld();
    TCamera cam = new TCamera();
    TLight spt = new TLight();
    TMesh cube = new TMesh();
    TMesh ground = new TMesh();
    TBuffer buff = new TBuffer();
 
    public Game()
       : base(800, 600, "Game Title")
    { }
 
    public override void OnLoad(EventArgs e)
    {
        // Create Engine World
        wld.Create();
 
        // Create Camera
        cam.Create(IntPtr.Zero);
        cam.Zoom(DFHelper.FPSCameraFOV(90f));
        cam.Move(new DFVector3D(0f, 0f, -5f), 0);
 
        // Create Spotlight
        spt.CreateSpot(10f, IntPtr.Zero);
        spt.Position(new DFVector3D(2f, 2f, -2f), 0);
        spt.Rotate(new DFVector3D(45f, 45f, 0f), 0);
 
        // Create Cube
        cube.CreateCube(IntPtr.Zero);
 
        // Create Ground
        ground.CreateCube(IntPtr.Zero);
        ground.Scale(new DFVector3D(10f, 0.1f, 10f));
        ground.Position(new DFVector3D(0f, -2f, 0f), 0);
 
        // I am not sure this is correct, but you can try.
        buff.CreateCustom(GetSize(this.Width,this.Height), MakeCurrent());
    }
 
    public override OnUpdateFrame(UpdateFrameEventArgs e)
    {
        if (Keyboard[Key.Escape])
            Exit();
    }
 
    public override OnRenderFrame(RenderFrameEventArgs e)
    {
        // Multiply by e.Time for framerate-independent movement.
        cube.Turn(new DFVector3D(0.5f, 0.5f, 0.5f), 0);
        TWorld.UpdateWorld(1f);
 
        TBuffer.SetBuffer(buff.Buffer);
        TWorld.RenderWorld(TWorld.RENDER_ALL);
        TBuffer.SetBuffer(TBuffer.BackBuffer());
        TLight.RenderLights(buff.Buffer);
 
        SwapBuffers();
    }
}
enablerbr's picture

thanks for your time and help. the above code doesn't work in creating a custom buffer. this game engine is all about using shaders and deferred lighting renderer. the need for buffers is a must. so not being able to create them won't allow the engine to run. i really hoped it would work. so i could use window forms for creating engine tools. which would allow me to see the results as they would appear in the game engine. i'm to new to coding to go about creating my own similar game engine from scratch using OpenGL or C#.

OpenTK grabbed my attetion cause it was constantly being worked on and kept upto date compared to Tao.

the Fiddler's picture

You'll have to explain more clearly what you wish to do. What is a "custom buffer"? Are you talking about an FBO? What fails? Is there an error message?

It *is* possible to make it work, but we need more information before we can help you.

enablerbr's picture

well theres no error message as such apart from "System.AccessViolationException" after the createcustom buffer part of the code. which tells me that the buffer wasn't created. as i'm new to this. explaining it maybe hard for me.

when i use createworld() that starts the game engine rendering. therefore buffers are created after that command.

here is the introduction giving by the game engine for buffers. you might understand what it is i'm trying to do with the code from this introduction.

"Render buffers are a powerful part of the Leadwerks Engine 2 renderer. Rendering is always performed on a buffer. This can take the form of a texture-based buffer with optional color, depth, and normal components, a custom buffer the user creates and manages, or the graphics window back buffer. Texture-based buffers can be drawn onto other buffers to perform post-processing effects like bloom and depth-of-field. Texture-based buffers can also be used as textures and applied to materials. This technique can be used to render reflections, or a closed-circuit camera system. "

here is what info says about CreateCustomBuffer.

"CreateCustomBuffer
NOTE: CreateCustomBuffer can vary based on which language you use.
CustomBuffers must be managed by the user. Leadwerks will only handle rendering to that buffer.

C: TBuffer CreateCustomBuffer( byte* getsize, byte* makecurrent)
C++:
virtual void Buffer::Create( int width, int height, int type = BUFFER_COLOR0|BUFFER_DEPTH|BUFFER_NORMAL)
virtual void Buffer::CreateCustom( byte* getsize, byte* makecurrent)
Pascal: function CreateCustomBuffer ( GetSize:Pointer; MakeCurrent:Pointer ): THandle;
Creates and returns a new custom buffer. GetSize and MakeCurrent are callback functions for the buffer. "

the Fiddler's picture

Ok, it seems that you have to create a custom buffer. The engine API is a little strange (callback functions), but the following should work:

using Leadwrap;
 
class Game : GameWindow
{
       ...
        static GameWindow Window;
        byte* buffer;
 
        public Game() : base(...)
        {
            Window = this; 
        }
 
        // Callback function for buffer size
        unsafe public static void GetSize(int *width, int *height)
        {
            if (Window != null)
            {
                *width = Window.Width;
                *height = Window.Height;
            }
        }
 
        // Callback function to set the render context to the current buffer
        public static void MakeCurrent()
        {
            if (Window != null)
                Window.MakeCurrent();
        }
 
        // Delegate for GetSize
        unsafe static Leadwerks.GetSize DGetSize = new Leadwerks.GetSize(GetSize);
        // Delegate for MakeCurrent
        static Leadwerks.MakeCurrent DMakeCurrent = new Leadwerks.MakeCurrent(MakeCurrent);
 
        protected override OnLoad(EventArgs e)
        {
             ....
             // Replace the CreateCustom call with
             buffer = Leadwerks.lwCreateCustomBuffer(DGetSize, DMakeCurrent);
        }
        ...
}

I've only listed the parts you need to change, according to the Leadwerks docs. The API is quite involved and the stuff with the callbacks is ugly, but I think this should work.

enablerbr's picture

is there a safe way of doing that? as i was using IntPtr instead of byte*. i hoped to avoid compiling unsafe code.

BTW OpenTK.GameWindow does not contain a definition for MakeCurrent(). least thats what VS2008 is saying.