Discussion:
Transparent Window Application
Chris Hidden
2014-08-18 15:10:25 UTC
Permalink
Hello again everyone!

I am currently developing an application with a company and we have a challenge. We want our application to run over top of any other application. So in windows our app is basically several graphical elements that will react to input from sensors. So to start with I wanted to see if I could get the cessna model to render to the screen and have nothing else.

I figured I might be able to make use of the layered windows available from the win32 library. Here is a good example of what I mean http://www.dhpoware.com/demos/glLayeredWindows.html

My understanding of how it works is fairly crude, but essentially they create a struct to represent an image and redraw it to the pbuffer and re render it to the layerd window. Thus allowing the image to be the only thing that displays and nothing else of a window.

So I tried to embedd OSG into the transparent window but all that happens is that the entire window is transparent. I believe because the separate thread uses the hwnd handle to take care of the rendering. So I cannot access the variables I need to re render the osg scene to the buffer.

Is there a way to achieve this in osg? Have a model or a group of models displayed only on the scene. Also we want the "window" to not be clickable. this way the user can click through our window onto any application they have under it. I realize I may be obscure here so if there is any confusion please ask me and Ill do my best to explain!

Thanks!

I also tried to get a similar effect using OSG's api to the inherited window data. To no avail:



Code:
LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
TCHAR greeting[] = _T("Hello, World!");

switch (msg)
{
case WM_CREATE:
{
osg::ref_ptr<osg::Referenced> windata =
new osgViewer::GraphicsWindowWin32::WindowData(hWnd);

osg::ref_ptr<osg::GraphicsContext::Traits> traits =
new osg::GraphicsContext::Traits;
traits->x = 0;
traits->y = 0;
traits->width = 800;
traits->height = 600;
traits->windowDecoration = false;
traits->doubleBuffer = true;
traits->inheritedWindowData = windata;
traits->alpha = false;

osg::ref_ptr<osg::GraphicsContext> gc =
osg::GraphicsContext::createGraphicsContext(traits.get()
);
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setGraphicsContext(gc);
camera->setViewport(
new osg::Viewport(0, 0, traits->width, traits->height));
camera->setClearMask(GL_DEPTH_BUFFER_BIT );
camera->setClearColor(osg::Vec4f(0,0,0,0));
camera->setProjectionMatrixAsPerspective(
30.0f, (double)traits->width / (double)traits
->height, 1.0, 1000.0);
g_viewer = new osgViewer::Viewer;
g_viewer->setCamera(camera.get());
g_viewer->setSceneData(osgDB::readNodeFile("cessna.osg"));
g_viewer->setKeyEventSetsDone(0);
g_viewer->setCameraManipulator(
new osgGA::TrackballManipulator);
g_finished = false;





_beginthread(render, 0, NULL);


return 0;
}

case WM_PAINT:

break;

case WM_DESTROY:
g_viewer->setDone(true);
while (!g_finished) Sleep(10);
PostQuitMessage(0);
return 0;
}
}

[/url]

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=60697#60697
Chris Hidden
2014-08-19 16:50:44 UTC
Permalink
Anyone have any ideas?

This is what Im working on so far. I have used the exmaple linked in the above post.

I create a layered window:


Code:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShowCmd)
{
DetectMemoryLeaks();

MSG msg = { 0 };
WNDCLASSEX wcl = { 0 };

wcl.cbSize = sizeof(wcl);
wcl.style = CS_HREDRAW | CS_VREDRAW;
wcl.lpfnWndProc = WindowProc;
wcl.cbClsExtra = 0;
wcl.cbWndExtra = 0;
wcl.hInstance = hInstance;
wcl.hIcon = LoadIcon(0, IDI_APPLICATION);
wcl.hCursor = LoadCursor(0, IDC_ARROW);
wcl.hbrBackground = 0;
wcl.lpszMenuName = 0;
wcl.lpszClassName = _T("GLLayeredWindowClass");
wcl.hIconSm = 0;

if (!RegisterClassEx(&wcl))
return 0;

g_hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST, wcl.lpszClassName,
_T("GL Layered Window Demo"), WS_POPUP, 0, 0, IMAGE_WIDTH,
IMAGE_HEIGHT, 0, 0, wcl.hInstance, 0);

if (g_hWnd)
{

if (Init())
{
ShowWindow(g_hWnd, nShowCmd);
UpdateWindow(g_hWnd);

while (true)
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;

TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
DrawFrame();
}
}
}

Cleanup();
UnregisterClass(wcl.lpszClassName, hInstance);
}

return (int)(msg.wParam);
}




Then I establish the osg reference object for my scene in the WindProc:


Code:

LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static TCHAR szBuffer[32] = { 0 };

switch (msg)
{
case WM_CREATE:
{
osg::ref_ptr<osg::Referenced> windata =
new osgViewer::GraphicsWindowWin32::WindowData(hWnd);

osg::ref_ptr<osg::GraphicsContext::Traits> traits =
new osg::GraphicsContext::Traits;
traits->x = 0;
traits->y = 0;
traits->width = 800;
traits->height = 600;
traits->windowDecoration = false;
traits->doubleBuffer = true;
traits->pbuffer = true;
traits->inheritedWindowData = windata;

osg::ref_ptr<osg::GraphicsContext> gc =
osg::GraphicsContext::createGraphicsContext(traits.get()
);
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setGraphicsContext(gc);
camera->setViewport(
new osg::Viewport(0, 0, traits->width, traits->height));
camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
camera->setClearColor(osg::Vec4f(0.0f, 0.0f, 0.0f, 0.0f));
camera->setProjectionMatrixAsPerspective(
30.0f, (double)traits->width / (double)traits
->height, 1.0, 1000.0);
g_viewer = new osgViewer::Viewer;
g_viewer->setCamera(camera.get());
g_viewer->setSceneData(osgDB::readNodeFile("cessna.osg"));
g_viewer->setKeyEventSetsDone(0);
g_viewer->setCameraManipulator(
new osgGA::TrackballManipulator);


return 0;
}


case WM_DESTROY:
PostQuitMessage(0);
return 0;

case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
{
SendMessage(hWnd, WM_CLOSE, 0, 0);
return 0;
}
break;

case WM_NCHITTEST:
return HTCAPTION; // allows dragging of the window

case WM_TIMER:
_stprintf(szBuffer, _TEXT("%d FPS"), g_frames);
SetWindowText(hWnd, szBuffer);
g_frames = 0;
return 0;

default:
break;
}

return DefWindowProc(hWnd, msg, wParam, lParam);
}




Then in the msg loop in WinMain

Draw frame is called and it looks like this:


Code:

void DrawFrame()
{

g_viewer->frame();

// At this stage the pbuffer will contain our scene. Now we make a system
// memory copy of the pbuffer.
CopyPBufferToImage();

// Then we pre-multiply each pixel with its alpha component. This is how
// the layered windows API expects images containing alpha information.
ImagePreMultAlpha(&g_scene);

// Finally we update our layered window with our scene.
RedrawLayeredWindow();

// Since we're doing off-screen rendering the frame rate will be
// independent of the video display's refresh rate.
g_frames++;
}



He has his own code to establish OpenGL and set up pbuffers. But OSG offers pbuffers, so Im thinking I should be able to draw to the pbuffer, then follow his order of things where we do pre multiplication of each pixel with alpha.

Then call g_viewer->frame() after that maybe and use his g_frames++ to help the refresh rate. Im just lacking the knowledge I need to implement the pbuffer.... or well at least that as a starting point.

Any one who can guide me in the right direction? Or tell me Im going in the completely wrong one?

Thanks!!

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=60720#60720
Sergey Kurdakov
2014-08-19 19:43:58 UTC
Permalink
Hi Chris,

I did not followed your code, sorry, but reading the question I realized
that what you need is a silent renderer

see discussion here http://forum.openscenegraph.org/viewtopic.php?t=7202

just read all the discussion on three forum pages.
then taking rendered images - you can put them into layered windows.

Regards
Sergey
Post by Chris Hidden
Anyone have any ideas?
This is what Im working on so far. I have used the exmaple linked in the above post.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShowCmd)
{
DetectMemoryLeaks();
MSG msg = { 0 };
WNDCLASSEX wcl = { 0 };
wcl.cbSize = sizeof(wcl);
wcl.style = CS_HREDRAW | CS_VREDRAW;
wcl.lpfnWndProc = WindowProc;
wcl.cbClsExtra = 0;
wcl.cbWndExtra = 0;
wcl.hInstance = hInstance;
wcl.hIcon = LoadIcon(0, IDI_APPLICATION);
wcl.hCursor = LoadCursor(0, IDC_ARROW);
wcl.hbrBackground = 0;
wcl.lpszMenuName = 0;
wcl.lpszClassName = _T("GLLayeredWindowClass");
wcl.hIconSm = 0;
if (!RegisterClassEx(&wcl))
return 0;
g_hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST,
wcl.lpszClassName,
_T("GL Layered Window Demo"), WS_POPUP, 0, 0, IMAGE_WIDTH,
IMAGE_HEIGHT, 0, 0, wcl.hInstance, 0);
if (g_hWnd)
{
if (Init())
{
ShowWindow(g_hWnd, nShowCmd);
UpdateWindow(g_hWnd);
while (true)
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
DrawFrame();
}
}
}
Cleanup();
UnregisterClass(wcl.lpszClassName, hInstance);
}
return (int)(msg.wParam);
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static TCHAR szBuffer[32] = { 0 };
switch (msg)
{
{
osg::ref_ptr<osg::Referenced> windata =
new
osgViewer::GraphicsWindowWin32::WindowData(hWnd);
osg::ref_ptr<osg::GraphicsContext::Traits> traits =
new osg::GraphicsContext::Traits;
traits->x = 0;
traits->y = 0;
traits->width = 800;
traits->height = 600;
traits->windowDecoration = false;
traits->doubleBuffer = true;
traits->pbuffer = true;
traits->inheritedWindowData = windata;
osg::ref_ptr<osg::GraphicsContext> gc =
osg::GraphicsContext::createGraphicsContext(traits.get()
);
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setGraphicsContext(gc);
camera->setViewport(
new osg::Viewport(0, 0, traits->width,
traits->height));
camera->setClearMask(GL_DEPTH_BUFFER_BIT |
GL_COLOR_BUFFER_BIT);
camera->setClearColor(osg::Vec4f(0.0f, 0.0f, 0.0f, 0.0f));
camera->setProjectionMatrixAsPerspective(
30.0f, (double)traits->width / (double)traits
->height, 1.0, 1000.0);
g_viewer = new osgViewer::Viewer;
g_viewer->setCamera(camera.get());
g_viewer->setSceneData(osgDB::readNodeFile("cessna.osg"));
g_viewer->setKeyEventSetsDone(0);
g_viewer->setCameraManipulator(
new osgGA::TrackballManipulator);
return 0;
}
PostQuitMessage(0);
return 0;
if (wParam == VK_ESCAPE)
{
SendMessage(hWnd, WM_CLOSE, 0, 0);
return 0;
}
break;
return HTCAPTION; // allows dragging of the window
_stprintf(szBuffer, _TEXT("%d FPS"), g_frames);
SetWindowText(hWnd, szBuffer);
g_frames = 0;
return 0;
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
Then in the msg loop in WinMain
void DrawFrame()
{
g_viewer->frame();
// At this stage the pbuffer will contain our scene. Now we make a system
// memory copy of the pbuffer.
CopyPBufferToImage();
// Then we pre-multiply each pixel with its alpha component. This is how
// the layered windows API expects images containing alpha information.
ImagePreMultAlpha(&g_scene);
// Finally we update our layered window with our scene.
RedrawLayeredWindow();
// Since we're doing off-screen rendering the frame rate will be
// independent of the video display's refresh rate.
g_frames++;
}
He has his own code to establish OpenGL and set up pbuffers. But OSG
offers pbuffers, so Im thinking I should be able to draw to the pbuffer,
then follow his order of things where we do pre multiplication of each
pixel with alpha.
Then call g_viewer->frame() after that maybe and use his g_frames++ to
help the refresh rate. Im just lacking the knowledge I need to implement
the pbuffer.... or well at least that as a starting point.
Any one who can guide me in the right direction? Or tell me Im going in
the completely wrong one?
Thanks!!
------------------
http://forum.openscenegraph.org/viewtopic.php?p=60720#60720
_______________________________________________
osg-users mailing list
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Chris Hidden
2014-08-21 08:27:08 UTC
Permalink
Yes! Ok, I read that forum and it gave me a better idea of how I might do this. To account for transparency though I need to get the current pbuffer and put it into a local byte array.

Something like


Code:

static BYTE pixels[width * height * 4] = {0};

unsigned char* ptr = g_image->data();

for (unsigned int i = 0; i < size; i += 2)
{
pixels[i] = (ptr[i / 2] >> 4);
pixels[i + 1] = (ptr[i / 2] & 0x0F);
}




Now this doens't really work of course, I just get an empy BYTE array.

Normally this could be done with :


Code:

glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels);





I know that OSG has a readPixels method. But I don't really understand how to read the pixels into a byte array. The optional packing parameter is an int in the osg::image::readpixels. I just lack understanding of how to make this conversion.

How would I got about doing this? Is there maybe a better way in this case than readpixels?

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=60728#60728
Sergey Kurdakov
2014-08-22 01:08:38 UTC
Permalink
Hi Chris,

for read pixels there are examples

http://trac.openscenegraph.org/projects/osg//browser/OpenSceneGraph/trunk/examples/osgscreencapture/osgscreencapture.cpp

https://code.google.com/p/osgworks/source/browse/trunk/src/osgwTools/ScreenCapture.cpp

Regards
Sergey
Post by Chris Hidden
Yes! Ok, I read that forum and it gave me a better idea of how I might do
this. To account for transparency though I need to get the current
pbuffer and put it into a local byte array.
Something like
static BYTE pixels[width * height * 4] = {0};
unsigned char* ptr = g_image->data();
for (unsigned int i = 0; i < size; i += 2)
{
pixels[i] = (ptr[i / 2] >> 4);
pixels[i + 1] = (ptr[i / 2] & 0x0F);
}
Now this doens't really work of course, I just get an empy BYTE array.
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, GL_BGRA_EXT,
GL_UNSIGNED_BYTE, pixels);
I know that OSG has a readPixels method. But I don't really understand
how to read the pixels into a byte array. The optional packing parameter
is an int in the osg::image::readpixels. I just lack understanding of how
to make this conversion.
How would I got about doing this? Is there maybe a better way in this
case than readpixels?
------------------
http://forum.openscenegraph.org/viewtopic.php?p=60728#60728
_______________________________________________
osg-users mailing list
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Chris Hidden
2014-08-22 07:55:54 UTC
Permalink
Ok, with your pushes in the right direction I have finally managed to get this working! :D. Its not very performance friendly but that I can optimize later.

Ill break it down so that people who are looking to do somethings similar can see what I did and suggest betters ways of doing it if they want :D.

The first step is to take a look at dhpowares code. His open GL layered window example is the basis for a lot of what I did.
http://www.dhpoware.com/demos/glLayeredWindows.html

Dhpoware defines a bunch of constants to help set up the OpenGL and OpenGL Extensions in his code. A lot of these we don't need however as OSG takes care of a lot of this for us. We also don't need the methods:


Code:

InitChekerPatternTexture();
InitGLExtensions();
InitPBuffer();
InitGL();




These methods do things that OSG takes care of for us. We can also remove the Struct called Vertex and the Vertex object g_cube as we are using our own models.

I changed the Image struct to Scene instead of image just to make things easier for myself. The struct itself remains the same:


Code:

typedef struct
{
int width;
int height;
int pitch;
HDC hdc;
HBITMAP hBitmap;
BITMAPINFO info;
BYTE *pPixels;
} Scene;




I also added a few global variables to make things easier while I was trying to figure this out:


Code:

/**
* Handle to the current Instance
*/
HINSTANCE g_hInst;
/**
* Screen Horizontal x
*/
int sLeft;
/**
* Screen Vertical y
*/
int sTop;
/**
* Width of the screen
*/
int sWidth;
/**
* Height of the screen
*/
int sHeight;

/**
* Viewer for the OSG engine
*/
osg::ref_ptr<osgViewer::Viewer> g_viewer;
/**
* Image for the off screen pbuffer for the osg Scene
*/
osg::ref_ptr<osg::Image> g_image;
/**
* OSG camera object for our scene
*/
osg::ref_ptr<osg::Camera> g_camera;





With WinMain we establish the layered window as shown in the example except I use sTop, sLeft, sWidth and sHeight to set the createWindow x,y,width and height attriubutes:


Code:

g_hWnd = CreateWindowEx(
WS_EX_LAYERED | WS_EX_TOPMOST, // 32 bit value declaring the extended window style
wcl.lpszClassName, // Null terminated string. Class name.
_T("GL Layered Window Demo"), // Null terminated string. Window Name.
WS_POPUP, // 32 but value declaring the style of the window.
sLeft, // int x pos of window
sTop, // int y pos of window.
sWidth, // int width of window
sHeight, // int height of window.
0, // HWND handle to parent window, 0 if none.
0, // HMENU handle to menu
wcl.hInstance, // HINSTANCE handle to the instance of the module.
0);




Then I built a small method to set the full screen:


Code:

void SetToFullScreen()
{
RECT desktop;

const HWND hDesk = GetDesktopWindow();
GetWindowRect(hDesk, &desktop);

sLeft = desktop.left;
sTop = desktop.top;
sWidth = desktop.right - sLeft;
sHeight = desktop.bottom - sTop;
}




Now that the window is full screen and the layered window is established we need to set up the WindowProc method to handle messages:


Code:

LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static TCHAR szBuffer[32] = { 0 };

switch (msg)
{
case WM_CREATE:
initOSG(hWnd);
return 0;

case WM_DESTROY:
PostQuitMessage(0);
return 0;

case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
{
SendMessage(hWnd, WM_CLOSE, 0, 0);
return 0;
}
break;

default:
break;
}

return DefWindowProc(hWnd, msg, wParam, lParam);
}




This looks a bit different as I didn't need the timer functionality any more and in WM_CREATE I used the function initOSG to init the OSG engine.

I also took away the functionality to move around the window as its unnecessary in full screen.
Post by Sergey Kurdakov
see discussion here http://forum.openscenegraph.org/viewtopic.php?t=7202
Code:

void initOSG(HWND &hWnd)
{
osg::ref_ptr<osg::Referenced> windata = new osgViewer::GraphicsWindowWin32::WindowData(hWnd);

g_viewer = new osgViewer::Viewer();
g_camera = new osg::Camera;
g_camera = g_viewer->getCamera();

osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;

initOSGTraits(*traits, windata);

osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());

g_camera->setGraphicsContext (gc);
g_camera->setDrawBuffer (GL_FRONT);
g_camera->setProjectionMatrixAsPerspective (30.0f, (double)traits->width / (double)traits->height, 1.0, 1000.0);
g_camera->setViewport (new osg::Viewport(0, 0, traits->width, traits->height));
g_viewer->setSceneData (osgDB::readNodeFile("cessna.osg"));
g_camera->setClearColor (osg::Vec4f(0, 0, 0, 0));

g_viewer->setCameraManipulator(new osgGA::TrackballManipulator);
g_image = new osg::Image(); // Needed to establish off screen rendering.

g_viewer->setRunMaxFrameRate(30);
}




I also like to split my code up a lot so I establish the traits in a separate method. Its important here to set the pbuffer to true. As well as the alpha if you want the background to be completely transparent.


Code:

void initOSGTraits(osg::GraphicsContext::Traits &traits, osg::ref_ptr<osg::Referenced> &windata)
{
traits.x = sWidth / 2;
traits.y = sHeight / 2;
traits.width = sWidth;
traits.height = sHeight;
traits.windowDecoration = false;
traits.doubleBuffer = true;
traits.pbuffer = true;
traits.alpha = true;
traits.inheritedWindowData = windata;
}




Now to DrawFrame() which gets called every time we move through the message loop in WinMain where WM_QUIT is not true.

Here is the bit that got it all working for me. First we need to call attach on our camera to link the image to the scene. Or I think thats how it works anyways. Im still quite new to OSG. Then we realize and draw our frame.

Now I use dhpoweras CopyPBufferToImage method to create an offscreen render of our frame:


Code:

void CopyPBufferToImage()
{

g_image->readPixels(0, 0, sWidth, sHeight, GL_BGRA_EXT, GL_UNSIGNED_BYTE);


for (int i = 0; i < g_image->t(); ++i)
{
memcpy(&g_scene.pPixels[g_scene.pitch * i],
&g_image->data()[((sHeight - 1) - i) * (sWidth * 4)],
sWidth * 4);
}


}




I took out everything from this method except for the loop that handles copying over the image from the pbuffer to the scene struct we have declared earlier. This way it does exactly what dhpoware did except that we use OSG to handle readPixels. So instead of passing in a byte array we use osg::IMAGE data property to get the byte array. And memcpy it to our struct. Notice here that I don't use a threading method as we want everything to exist in the same thread as the layered window so that we can actually access our image and copy it to the current window context.

Dhpowares redrawLayeredWindow() and ImagePreMultAlpha take care of the nitty gritty redrawing process that I don't fully fuly understand yet.

And voila! Full screen with a model and no background! Very awesome. Now I need to fix a LOT of performance issues as this takes a crap ton of resources, but this is the basic idea anyways. Don't forget to include the osg headers you need and process.h.

PLEASE FEEL FREE to criticize the shit out my methods. I want to make this as performance low and well written as possible. Like I said, I just started using OSG 2 weeks ago so Im stil learning.

Cheers![/code]

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=60738#60738
Sergey Kurdakov
2014-08-22 10:21:23 UTC
Permalink
Hi Chris,

I think that

the use of FBO in place of pbuffer,

and use of async read pixels see my message
https://www.mail-archive.com/osg-users-***@public.gmane.org/msg50831.html
could improve speed a bit in your case.

Regards
Sergey
Post by Chris Hidden
Ok, with your pushes in the right direction I have finally managed to get
this working! :D. Its not very performance friendly but that I can
optimize later.
Ill break it down so that people who are looking to do somethings similar
can see what I did and suggest betters ways of doing it if they want :D.
The first step is to take a look at dhpowares code. His open GL layered
window example is the basis for a lot of what I did.
http://www.dhpoware.com/demos/glLayeredWindows.html
Dhpoware defines a bunch of constants to help set up the OpenGL and OpenGL
Extensions in his code. A lot of these we don't need however as OSG takes
InitChekerPatternTexture();
InitGLExtensions();
InitPBuffer();
InitGL();
These methods do things that OSG takes care of for us. We can also remove
the Struct called Vertex and the Vertex object g_cube as we are using our
own models.
I changed the Image struct to Scene instead of image just to make things
typedef struct
{
int width;
int height;
int pitch;
HDC hdc;
HBITMAP hBitmap;
BITMAPINFO info;
BYTE *pPixels;
} Scene;
I also added a few global variables to make things easier while I was
/**
* Handle to the current Instance
*/
HINSTANCE g_hInst;
/**
* Screen Horizontal x
*/
int sLeft;
/**
* Screen Vertical y
*/
int sTop;
/**
* Width of the screen
*/
int sWidth;
/**
* Height of the screen
*/
int sHeight;
/**
* Viewer for the OSG engine
*/
osg::ref_ptr<osgViewer::Viewer> g_viewer;
/**
* Image for the off screen pbuffer for the osg Scene
*/
osg::ref_ptr<osg::Image> g_image;
/**
* OSG camera object for our scene
*/
osg::ref_ptr<osg::Camera> g_camera;
With WinMain we establish the layered window as shown in the example
except I use sTop, sLeft, sWidth and sHeight to set the createWindow
g_hWnd = CreateWindowEx(
WS_EX_LAYERED | WS_EX_TOPMOST, // 32 bit value declaring
the extended window style
wcl.lpszClassName, // Null
terminated string. Class name.
_T("GL Layered Window Demo"), // Null terminated
string. Window Name.
WS_POPUP, //
32 but value declaring the style of the window.
sLeft, //
int x pos of window
sTop, //
int y pos of window.
sWidth, //
int width of window
sHeight, //
int height of window.
0,
// HWND handle to parent window, 0 if none.
0,
// HMENU handle to menu
wcl.hInstance, //
HINSTANCE handle to the instance of the module.
0);
void SetToFullScreen()
{
RECT desktop;
const HWND hDesk = GetDesktopWindow();
GetWindowRect(hDesk, &desktop);
sLeft = desktop.left;
sTop = desktop.top;
sWidth = desktop.right - sLeft;
sHeight = desktop.bottom - sTop;
}
Now that the window is full screen and the layered window is established
LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static TCHAR szBuffer[32] = { 0 };
switch (msg)
{
initOSG(hWnd);
return 0;
PostQuitMessage(0);
return 0;
if (wParam == VK_ESCAPE)
{
SendMessage(hWnd, WM_CLOSE, 0, 0);
return 0;
}
break;
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
This looks a bit different as I didn't need the timer functionality any
more and in WM_CREATE I used the function initOSG to init the OSG engine.
I also took away the functionality to move around the window as its
unnecessary in full screen.
Post by Sergey Kurdakov
see discussion here http://forum.openscenegraph.org/viewtopic.php?t=7202
void initOSG(HWND &hWnd)
{
osg::ref_ptr<osg::Referenced> windata = new
osgViewer::GraphicsWindowWin32::WindowData(hWnd);
g_viewer = new osgViewer::Viewer();
g_camera = new osg::Camera;
g_camera = g_viewer->getCamera();
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new
osg::GraphicsContext::Traits;
initOSGTraits(*traits, windata);
osg::ref_ptr<osg::GraphicsContext> gc =
osg::GraphicsContext::createGraphicsContext(traits.get());
g_camera->setGraphicsContext (gc);
g_camera->setDrawBuffer
(GL_FRONT);
g_camera->setProjectionMatrixAsPerspective (30.0f,
(double)traits->width / (double)traits->height, 1.0, 1000.0);
g_camera->setViewport
(new osg::Viewport(0, 0, traits->width, traits->height));
g_viewer->setSceneData
(osgDB::readNodeFile("cessna.osg"));
g_camera->setClearColor
(osg::Vec4f(0, 0, 0, 0));
g_viewer->setCameraManipulator(new osgGA::TrackballManipulator);
g_image = new osg::Image(); // Needed to establish off screen rendering.
g_viewer->setRunMaxFrameRate(30);
}
I also like to split my code up a lot so I establish the traits in a
separate method. Its important here to set the pbuffer to true. As well as
the alpha if you want the background to be completely transparent.
void initOSGTraits(osg::GraphicsContext::Traits &traits,
osg::ref_ptr<osg::Referenced> &windata)
{
traits.x = sWidth /
2;
traits.y = sHeight /
2;
traits.width = sWidth;
traits.height = sHeight;
traits.windowDecoration = false;
traits.doubleBuffer = true;
traits.pbuffer = true;
traits.alpha = true;
traits.inheritedWindowData = windata;
}
Now to DrawFrame() which gets called every time we move through the
message loop in WinMain where WM_QUIT is not true.
Here is the bit that got it all working for me. First we need to call
attach on our camera to link the image to the scene. Or I think thats how
it works anyways. Im still quite new to OSG. Then we realize and draw our
frame.
void CopyPBufferToImage()
{
g_image->readPixels(0, 0, sWidth, sHeight, GL_BGRA_EXT, GL_UNSIGNED_BYTE);
for (int i = 0; i < g_image->t(); ++i)
{
memcpy(&g_scene.pPixels[g_scene.pitch * i],
&g_image->data()[((sHeight - 1) - i) * (sWidth * 4)],
sWidth * 4);
}
}
I took out everything from this method except for the loop that handles
copying over the image from the pbuffer to the scene struct we have
declared earlier. This way it does exactly what dhpoware did except that
we use OSG to handle readPixels. So instead of passing in a byte array we
use osg::IMAGE data property to get the byte array. And memcpy it to our
struct. Notice here that I don't use a threading method as we want
everything to exist in the same thread as the layered window so that we can
actually access our image and copy it to the current window context.
Dhpowares redrawLayeredWindow() and ImagePreMultAlpha take care of the
nitty gritty redrawing process that I don't fully fuly understand yet.
And voila! Full screen with a model and no background! Very awesome.
Now I need to fix a LOT of performance issues as this takes a crap ton of
resources, but this is the basic idea anyways. Don't forget to include
the osg headers you need and process.h.
PLEASE FEEL FREE to criticize the shit out my methods. I want to make this
as performance low and well written as possible. Like I said, I just
started using OSG 2 weeks ago so Im stil learning.
Cheers![/code]
------------------
http://forum.openscenegraph.org/viewtopic.php?p=60738#60738
_______________________________________________
osg-users mailing list
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Continue reading on narkive:
Loading...