What's the bare skeleton to get a triangle drawn on an OpenGL window in C on OSX? I've gone through the tutorials at Nehe and tried to get it working, but the CreateGLWindow seems hopelessly tied to win32.
I want to stick to just opengl and glut, etc. I'll be eventually wrapping this in scheme, but I'd like to have a firmer understanding at the c-level beforehand.
Here's what I have thus far:
#include <OpenGL/gl.h>// Header File For The OpenGL32 Library
#include <OpenGL/glu.h>// Header File For The GLu32 Library
#include <GLUT/glut.h>// Header File For The GLut Library
#define kWindowWidth 400;
#define kWindowHeight 300;
HGLRC hRC=NULL;// Permanent Rendering Context
HDC hDC=NULL;// Private GDI Device Context
HWND hWnd=NULL;// Holds Our Window Handle
HINSTANCE hInstance;// Holds The Instance Of The Application
LRESULTCALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);// Declaration For WndProc
boolkeys[256];// Array Used For The Keyboard Routine
boolactive=TRUE;// Window Active Flag Set To TRUE By Default
boolfullscreen=TRUE;// Fullscreen Flag Set To Fullscreen Mode By Default
GLvoid ReSizeGLScene(GLsizei width, GLsizei height)// Resize And Initialize The GL Window
{
if (height==0)// Prevent A Divide By Zero By
{
height=1;// Making Height Equal One
}
glViewport(0, 0, width, height);// Reset The Current Viewport
glMatrixMode(GL_PROJECTION);// Select The Projection Matrix
glLoadIdentity();// Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);// Select The Modelview Matrix
glLoadIdentity();// Reset The Modelview Matrix
}
int InitGL(GLvoid)// All Setup For OpenGL Goes Here
{
glShadeModel(GL_SMOOTH);// Enables Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);// Black Background
glClearDepth(1.0f);// Depth Buffer Setup
glEnable(GL_DEPTH_TEST);// Enables Depth Testing
glDepthFunc(GL_LEQUAL);// The Type Of Depth Test To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);// Really Nice Perspective Calculations
return TRUE;// Initialization Went OK
}
int DrawGLScene(GLvoid)// Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Clear The Screen And The Depth Buffer
glLoadIdentity();// Reset The Current Modelview Matrix
return TRUE;// Everything Went OK
}
GLvoid KillGLWindow(GLvoid)// Properly Kill The Window
{
if (fullscreen)// Are We In Fullscreen Mode?
{
ChangeDisplaySettings(NULL,0);// If So Switch Back To The Desktop
ShowCursor(TRUE);// Show Mouse Pointer
}
if (hRC)// Do We Have A Rendering Context?
{
if (!wglMakeCurrent(NULL,NULL))// Are We Able To Release The DC And RC Contexts?
{
MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
if (!wglDeleteContext(hRC))// Are We Able To Delete The RC?
{
MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
hRC=NULL;// Set RC To NULL
}
if (hDC && !ReleaseDC(hWnd,hDC))// Are We Able To Release The DC
{
MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hDC=NULL;// Set DC To NULL
}
if (hWnd && !DestroyWindow(hWnd))// Are We Able To Destroy The Window?
{
MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hWnd=NULL;// Set hWnd To NULL
}
if (!UnregisterClass("OpenGL",hInstance))// Are We Able To Unregister Class
{
MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hInstance=NULL;// Set hInstance To NULL
}
}
BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
GLuintPixelFormat;// Holds The Results After Searching For A Match
WNDCLASSwc;// Windows Class Structure
DWORDdwExStyle;// Window Extended Style
DWORDdwStyle;// Window Style
RECT WindowRect;// Grabs Rectangle Upper Left / Lower Right Values
WindowRect.left=(long)0;// Set Left Value To 0
WindowRect.right=(long)width;// Set Right Value To Requested Width
WindowRect.top=(long)0;// Set Top Value To 0
WindowRect.bottom=(long)height;// Set Bottom Value To Requested Height
fullscreen=fullscreenflag;// Set The Global Fullscreen Flag
hInstance= GetModuleHandle(NULL);// Grab An Instance For Our Window
wc.style= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;// Redraw On Move, And Own DC For Window
wc.lpfnWndProc= (WNDPROC) WndProc;// WndProc Handles Messages
wc.cbClsExtra= 0;// No Extra Window Data
wc.cbWndExtra= 0;// No Extra Window Data
wc.hInstance= hInstance;// Set The Instance
wc.hIcon= LoadIcon(NULL, IDI_WINLOGO);// Load The Default Icon
wc.hCursor= LoadCursor(NULL, IDC_ARROW);// Load The Arrow Pointer
wc.hbrBackground= NULL;// No Background Required For GL
wc.lpszMenuName= NULL;// We Don't Want A Menu
wc.lpszClassName= "OpenGL";// Set The Class Name
if (!RegisterClass(&wc))// Attempt To Register The Window Class
{
MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;// Exit And Return FALSE
}
if (fullscreen)// Attempt Fullscreen Mode?
{
DEVMODE dmScreenSettings;// Device Mode
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));// Makes Sure Memory's Cleared
dmScreenSettings.dmSize=sizeof(dmScreenSettings);// Size Of The Devmode Structure
dmScreenSettings.dmPelsWidth= width;// Selected Screen Width
dmScreenSettings.dmPelsHeight= height;// Selected Screen Height
dmScreenSettings.dmBitsPerPel= bits;// Selected Bits Per Pixel
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// If The Mode Fails, Offer Two Options. Quit Or Run In A Window.
if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen=FALSE;// Select Windowed Mode (Fullscreen=FALSE)
}
else
{
// Pop Up A Message Box Letting User Know The Program Is Closing.
MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
return FALSE;// Exit And Return FALSE
}
}
}
if (fullscreen)// Are We Still In Fullscreen Mode?
{
dwExStyle=WS_EX_APPWINDOW;// Window Extended Style
dwStyle=WS_POPUP;// Windows Style
ShowCursor(FALSE);// Hide Mouse Pointer
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;// Window Extended Style
dwStyle=WS_OVERLAPPEDWINDOW;// Windows Style
}
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);// Adjust Window To True Requested Size
if (!(hWnd=CreateWindowEx(dwExStyle,// Extended Style For The Window
"OpenGL",// Class Name
title,// Window Title
WS_CLIPSIBLINGS |// Required Window Style
WS_CLIPCHILDREN |// Required Window Style
dwStyle,// Selected Window Style
0, 0,// Window Position
WindowRect.right-WindowRect.left,// Calculate Adjusted Window Width
WindowRect.bottom-WindowRect.top,// Calculate Adjusted Window Height
NULL,// No Parent Window
NULL,// No Menu
hInstance,// Instance
NULL)))// Don't Pass Anything To WM_CREATE
{
KillGLWindow();// Reset The Display
MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;// Return FALSE
}
staticPIXELFORMATDESCRIPTOR pfd=// pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR),// Size Of This Pixel Format Descriptor
1,// Version Number
PFD_DRAW_TO_WINDOW |// Format Must Support Window
PFD_SUPPORT_OPENGL |// Format Must Support OpenGL
PFD_DOUBLEBUFFER,// Must Support Double Buffering
PFD_TYPE_RGBA,// Request An RGBA Format
bits,// Select Our Color Depth
0, 0, 0, 0, 0, 0,// Color Bits Ignored
0,// No Alpha Buffer
0,// Shift Bit Ignored
0,// No Accumulation Buffer
0, 0, 0, 0,// Accumulation Bits Ignored
16,// 16Bit Z-Buffer (Depth Buffer)
0,// No Stencil Buffer
0,// No Auxiliary Buffer
PFD_MAIN_PLANE,// Main Drawing Layer
0,// Reserved
0, 0, 0// Layer Masks Ignored
};
if (!(hDC=GetDC(hWnd)))// Did We Get A Device Context?
{
KillGLWindow();// Reset The Display
MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;// Return FALSE
}
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))// Did Windows Find A Matching Pixel Format?
{
KillGLWindow();// Reset The Display
MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;// Return FALSE
}
if(!SetPixelFormat(hDC,PixelFormat,&pfd))// Are We Able To Set The Pixel Format?
{
KillGLWindow();// Reset The Display
MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;// Return FALSE
}
if (!(hRC=wglCreateContext(hDC)))// Are We Able To Get A Rendering Context?
{
KillGLWindow();// Reset The Display
MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;// Return FALSE
}
if(!wglMakeCurrent(hDC,hRC))// Try To Activate The Rendering Context
{
KillGLWindow();// Reset The Display
MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;// Return FALSE
}
ShowWindow(hWnd,SW_SHOW);// Show The Window
SetForegroundWindow(hWnd);// Slightly Higher Priority
SetFocus(hWnd);// Sets Keyboard Focus To The Window
ReSizeGLScene(width, height);// Set Up Our Perspective GL Screen
if (!InitGL())// Initialize Our Newly Created GL Window
{
KillGLWindow();// Reset The Display
MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;// Return FALSE
}
return TRUE;// Success
}
LRESULT CALLBACK WndProc(HWNDhWnd,// Handle For This Window
UINTuMsg,// Message For This Window
WPARAMwParam,// Additional Message Information
LPARAMlParam)// Additional Message Information
{
switch (uMsg)// Check For Windows Messages
{
case WM_ACTIVATE:// Watch For Window Activate Message
{
if (!HIWORD(wParam))// Check Minimization State
{
active=TRUE;// Program Is Active
}
else
{
active=FALSE;// Program Is No Longer Active
}
return 0;// Return To The Message Loop
}
case WM_SYSCOMMAND:// Intercept System Commands
{
switch (wParam)// Check System Calls
{
case SC_SCREENSAVE:// Screensaver Trying To Start?
case SC_MONITORPOWER:// Monitor Trying To Enter Powersave?
return 0;// Prevent From Happening
}
break;// Exit
}
case WM_CLOSE:// Did We Receive A Close Message?
{
PostQuitMessage(0);// Send A Quit Message
return 0;// Jump Back
}
case WM_KEYDOWN:// Is A Key Being Held Down?
{
keys[wParam] = TRUE;// If So, Mark It As TRUE
return 0;// Jump Back
}
case WM_KEYUP:// Has A Key Been Released?
{
keys[wParam] = FALSE;// If So, Mark It As FALSE
return 0;// Jump Back
}
case WM_SIZE:// Resize The OpenGL Window
{
ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));// LoWord=Width, HiWord=Height
return 0;// Jump Back
}
}
// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
GLvoid InitGL(GLvoid);
GLvoid DrawGLScene(GLvoid);
GLvoid ReSizeGLScene(int Width, int Height);
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (kWindowWidth, kWindowHeight);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
InitGL();
glutDisplayFunc(DrawGLScene);
glutReshapeFunc(ReSizeGLScene);
glutMainLoop();
return 0;
}
As far as I can tell, the NeHe tutorials are specifically for windows and are great for higher level stuff. However, when it comes to the basics, They can become overcomplicated. So here is a simple skeletal program for rendering a triangle using only glut and opengl functionality. If you want to be Apple specific, try using agl.
// The OpenGL libraries, make sure to include the GLUT and OpenGL frameworks
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
// This is just an example using basic glut functionality.
// If you want specific Apple functionality, look up AGL
void init() // Called before main loop to set up the program
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
}
// Called at the start of the program, after a glutPostRedisplay() and during idle
// to display a frame
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glBegin(GL_TRIANGLES);
glVertex3f(0.0, 0.0, -10.0);
glVertex3f(1.0, 0.0, -10.0);
glVertex3f(0.0, 1.0, -10.0);
glEnd();
glutSwapBuffers();
}
// Called every time a window is resized to resize the projection matrix
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-0.1, 0.1, -float(h)/(10.0*float(w)), float(h)/(10.0*float(w)), 0.5, 1000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv); // Initializes glut
// Sets up a double buffer with RGBA components and a depth component
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);
// Sets the window size to 512*512 square pixels
glutInitWindowSize(512, 512);
// Sets the window position to the upper left
glutInitWindowPosition(0, 0);
// Creates a window using internal glut functionality
glutCreateWindow("Hello!");
// passes reshape and display functions to the OpenGL machine for callback
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutIdleFunc(display);
init();
// Starts the program.
glutMainLoop();
return 0;
}
NeHe has a tutorial for setting up an OpenGL window on Mac OS X with GLUT here. They also provide the code for all of the lessons for various different platforms. If you scroll to the bottom of lesson 2, you can download the lesson code ready to go for a number of platforms. You probably want either the GLUT sample or the Mac OS X/Cocoa sample.
Easiest way is to use Objective-C to get everything set up, then use C for drawing. (not the only way, GLUT is also an option.)
Sample code from Apple
Here's the "hello.c" example from the OpenGL Red Book converted to R6RS Scheme:
http://gist.github.com/319363
That program runs in Ikarus Scheme and Ypsilon Scheme.
Notice that the 'import' form is referring to some 'agave' libraries. Those are available at:
http://github.com/dharmatech/agave
Agave is a project which provides a bunch of OpenGL demos and libraries for R6RS Scheme.
Ikarus and Ypsilon are both available for OS X.
Ed
Related
I am a beginner at OpenGL and I am trying to create a game in which as background I have a raw image. When the game starts I display that image and I want to be able to click on it and to display another image afterwards. I tried using the function glutMouseFunc but when I try to run the program I receive a message which says that the program stopped working.
Here are some parts of my code: I have a global variable onMouse; if I click the mouse button the variable takes the value 1 and if it has the value 1 I try to load the second image.
int onMouse;
void mouseClicks(int button, int state, int x, int y) {
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
onMouse = 1;
}
}
And this is the main function:
//load first texture
texture = LoadTextureRAW( "2 Lock screen.raw", TRUE );
glutMouseFunc(mouseClicks);
if(onMouse == 1){
//load second texture
texture = LoadTextureRAW( "in_game.raw", TRUE );
}
What am I doing wrong?
EDIT I have made some changes to the code, but the background image still doesn't change. Here is the new main function:
glutCreateWindow("Game");
texture = LoadTextureRAW( "2 Lock screen.raw", 1 );
glutDisplayFunc(display);
glutMouseFunc(mouseClicks);
glutKeyboardFunc(key);
glutMainLoop();
if(onMouse == 1){
texture = LoadTextureRAW( "in_game.raw", 2 );
glutDisplayFunc(display);
}
And this is the display function in which I map the texture to a quad:
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
glClear( GL_COLOR_BUFFER_BIT );
// setup texture mapping
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, texture );
glPushMatrix();
glBegin( GL_QUADS );
glTexCoord2d(1.0,0.0); glVertex3d(1.0,1.0, 1.0);
glTexCoord2d(0.0,0.0); glVertex3d(-1.0,1.0,1.0);
glTexCoord2d(0.0,1.0); glVertex3d(-1.0,-1.0, -1.0);
glTexCoord2d(1.0,1.0); glVertex3d(1.0,-1.0, 1.0);
glEnd();
glPopMatrix();
glutSwapBuffers();
// free the texture
FreeTexture( texture );
You have the order wrong.
glutMouseFunc(mouseClicks);
Here you register the function to be called when the mouse is clicked.
if(onMouse == 1) {
You immediately check if the mouse had been clicked. It's impossible for the mouse to have been clicked in the brief period between these two lines, and glutMainLoop hasn't been entered yet so your program didn't even have a chance to listen for mouse events.
As for the crash, I can't help you debug it with just the code you have provided. Please try a debugger and find which line causes the crash.
What am I doing wrong?
You're expecting glutMouseFunc to wait for a mouse click. This is not how GLUT works (GLUT is not part of OpenGL BTW). Another callback to be registered is the drawing function (usually called display in GLUT based programs).
Once you enter the GLUT main loop (glutMainLoop() call) user events are processed and if a redisplay is requested the display function is called.
So here's what you do (in simplified pseudocode)
// Define bitmasks for mouse status, we assume mice have less than 17 buttons
#define MB_LEFT 0
#define MB_MIDDLE 1
#define MB_RIGHT 2
#define LMB_PRESSED (1<<0)
#define MMB_PRESSED (1<<1)
#define RMB_PRESSED (1<<2)
#define LMB_CLICKED (1<<16)
#define MMB_CLICKED (1<<17)
#define RMB_CLICKED (1<<18)
#define MB_PRESSED(state, button) (1<<(button))
#define MB_CLICKED(state, button) (1<<((button)+16)))
#define MB_MASK_PRESSED 0x0000ffffL
#define MB_MASK_CLICKED 0xffff0000L
uint32_t mouse_status = 0;
void onMouseButton(int button, int state, int x, int y)
{
int b;
switch(button) {
case GLUT_LEFT_BUTTON: b=MB_LEFT; break;
case GLUT_MIDDLE_BUTTON: b=MB_MIDDLE; break;
case GLUT_RIGHT_BUTTON: b=MB_RIGHT; break;
}
if(mouse_status & MB_PRESSED(b) && GLUT_UP == state) {
mouse_status |= MB_CLICKED(b);
}
if( !(mouse_status & MB_PRESSED(b)) && GLUT_DOWN == state) {
mouse_status = (mouse_status & ~(0L | MB_CLICKED(b))) | MB_PRESSED(b);
}
glutPostRedisplay();
}
void display(void)
{
if(mouse_status & MB_CLICKED(MB_LEFT)) {
/* do something */
…
/* clear the click flag */
mouse_status &= ~MB_MASK_CLICKED;
}
}
int main(…)
{
…
glutCreateWindow(…);
glutDisplayFunc(display);
glutMouseFunc(onMouseButton);
glutMainLoop();
}
You can of course use any other kind of structure you like to pass the mouse button status between program parts. I prefer bitmasks for such. Other people may prefer arrays (personally I don't like arrays for tasks like this, because they're not as easy to look at in a debugger than a simple bitfield).
glutMouseFunc registers a callback: a function to be called on specific events (here mouse events). These events are collected by glutMainLoop, which has not been called yet when you test onMouse.
Another thing, though I cannot tell for sure from the small code excerpt you provide, is that you'd better load the assets from the start of the programme, rather than wait for a user event to do it. Load them first, and simply change texture to whichever id correspond to the texture you wish to display then.
I want to create 2 windows in linux that I'll later draw in from a separate thread. I currently have a non-deterministic bug where the second window that I create sometimes doesn't get created (no errors though).
Here is the code.
static void create_x_window(Display *display, Window *win, int width, int height)
{
int screen_num = DefaultScreen(display);
unsigned long background = WhitePixel(display, screen_num);
unsigned long border = BlackPixel(display, screen_num);
*win = XCreateSimpleWindow(display, DefaultRootWindow(display), /* display, parent */
0,0, /* x, y */
width, height, /* width, height */
2, border, /* border width & colour */
background); /* background colour */
XSelectInput(display, *win, ButtonPressMask|StructureNotifyMask);
XMapWindow(display, *win);
}
int main(void) {
XInitThreads(); // prevent threaded XIO errors
local_display = XOpenDisplay(":0.0");
Window self_win, remote_win;
XEvent self_event, remote_event;
create_x_window(local_display, &remote_win, 640,480);
// this line flushes buffer and blocks so that the window doesn't crash for a reason i dont know yet
XNextEvent(local_display, &remote_event);
create_x_window(local_display, &self_win, 320, 240);
// this line flushes buffer and blocks so that the window doesn't crash for a reason i dont know yet
XNextEvent(local_display, &self_event);
while (1) {
}
return 0;
}
I don't really care for capturing input in the windows, but I found a tutorial that had XSelectInput and XNextEvent (in an event loop) and I was having trouble making this work without either.
It's not a bug, it's a feature. You left out the event loop.
Although you cleverly called XNextEvent twice, the X protocol is asynchronous so the server may still be setting up the actual window while you call XNextEvent, so there is nothing to do.
Tutorial here.
Right now my game is currently just showing an image (bmp) stretched onto a surface.
The problem I'm having is drawing text onto it.
The text is drawn correctly how I want it however, if the game is not in windowed mode, rather, if it's in fullscreen mode, the text will flicker on and off, and I can't for the life of my figure out what's wrong.
int Game::Render(){
HRESULT r;
D3DLOCKED_RECT LockedRect;//locked area of display memory(buffer really) we are drawing to
LPDIRECT3DSURFACE9 pBackSurf = 0;
if(!g_pDevice){
SetError("Cannot render because there is no device");
return E_FAIL;
}
if(g_pDevice->BeginScene()){
//clear the display arera with colour black, ignore stencil buffer
//
g_pDevice->Clear(0,0,D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,25), 1.0f, 0);
//get pointer to backbuffer
r=g_pDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO, &backBuffer); //&pBackSurf
g_pDevice->StretchRect(surface, NULL, backBuffer, NULL, D3DTEXF_NONE);
if(FAILED(r)){
SetError("Couldn't get backbuffer");
}
r=backBuffer->LockRect(&LockedRect, NULL, 0);
if(FAILED(r)){
SetError("Could not lock the back buffer");
}
g_font->DrawText(NULL,fps_string,-1,&font_rect,DT_LEFT|DT_NOCLIP,0xFFAABBCC);
backBuffer->UnlockRect();
//backBuffer->Release();//release lock
g_pDevice->EndScene();
g_pDevice->Present(NULL, NULL, NULL, NULL);//swap over buffer to primary surface
}
return S_OK;
}
I want to display an image in OpenCV in a full screen borderless window.
In other words, only the image pixels will appear, without menu, toolbar, or window background.
Using imshow() or cvShowImage() don't enable it:
The window grows to be full screen
in width but not in height. It misses few pixels.
I could not make it borderless even by changing settings of window
handler.
I think that the problem is rooted in cvNamedWindow() method which creates main WS_OVERLAPPED window, then creates a child and all functions like imshow() or cvGetWindowHandle() operate on the child.
Thus even windows command:
SetWindowLong((HWND)cvGetWindowHandle(winName), GWL_STYLE, WS_VISIBLE | WS_EX_TOPMOST | WS_POPUP);
Doesnt help, since the child cannot become borderless WS_POPUP. Someone got a workaround?
Maybe, showing opencv mat to window
without using opencv built in methods
Or some kind of windows trick
P.S. I tried the following code:
cvMoveWindow("AAA",0,0);
cvSetWindowProperty("AAA", CV_WINDOW_FULLSCREEN, CV_WINDOW_FULLSCREEN);
// Also I tried this:
HWND hwnd = (HWND)cvGetWindowHandle("AAA");
RECT windowRect;
windowRect.left = 0;
windowRect.top = 0;
windowRect.right = cxScreen; //Display resolution
windowRect.bottom = cyScreen; //Display resolution
AdjustWindowRect(&windowRect,WS_VISIBLE,false);
long p_OldWindowStyle = SetWindowLongPtr(hwnd,GWL_STYLE,WS_POPUP);
SetWindowPos(hwnd,HWND_TOP,0,0,windowRect.right,windowRect.bottom,SWP_FRAMECHANGED | SWP_SHOWWINDOW);
SetWindowLong(hwnd, GWL_STYLE, WS_VISIBLE | WS_EX_TOPMOST | WS_POPUP);
Have you issued cvShowImage() to display the window? Because it seems you are not doing it. Anyway, you might want to call the win32 API for this instead, so add a call to ShowWindow(hwnd, SW_SHOW); after SetWindowPos().
If your current call to SetWindowPos() doesn't do the trick, check this answer: Hide border of window, if i know a handle of this window
I recommend you doing your tests without calling cvSetWindowProperty() at first, just to make sure you can find a method that works.
Just a note, if you check modules/highgui/src/window_w32.cpp you can see how OpenCV creates windows on Windows.
EDIT:
The following code implements the tips I gave before and bypasses the problems the OP reported. The trick is NOT using cvGetWindowHandle() to retrieve the windows' handle and use directly win32 API for that: FindWindow()
IplImage* cv_img = cvLoadImage("test.jpg", CV_LOAD_IMAGE_UNCHANGED);
if(!cv_img)
{
printf("Failed cvLoadImage\n");
return -1;
}
cvNamedWindow("main_win", CV_WINDOW_AUTOSIZE);
cvMoveWindow("main_win", 0, 0);
cvSetWindowProperty("main_win", CV_WINDOW_FULLSCREEN, CV_WINDOW_FULLSCREEN);
cvShowImage("main_win", cv_img);
//HWND cv_hwnd = (HWND)cvGetWindowHandle("main_win");
//if (!cv_hwnd)
//{
// printf("Failed cvGetWindowHandle\n");
//}
//printf("cvGetWindowHandle returned %p\n", *cv_hwnd);
HWND win_handle = FindWindow(0, L"main_win");
if (!win_handle)
{
printf("Failed FindWindow\n");
}
SetWindowLong(win_handle, GWL_STYLE, GetWindowLong(win_handle, GWL_EXSTYLE) | WS_EX_TOPMOST);
ShowWindow(win_handle, SW_SHOW);
cvWaitKey(0);
cvReleaseImage(&cv_img);
cvDestroyWindow("main_win");
This code will make the window created by OpenCV borderless, but you still might have to tweak one thing or another to make this operation perfect. You'll see why. One idea is to resize the window and make it the size of the image.
EDIT:
Well, since you stated:
writing a demo might be very hard
I also decided to do this last part for you, since I'm such a nice guy =]
This is a small improvement of the code above:
HWND win_handle = FindWindow(0, L"main_win");
if (!win_handle)
{
printf("Failed FindWindow\n");
}
// Resize
unsigned int flags = (SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER);
flags &= ~SWP_NOSIZE;
unsigned int x = 0;
unsigned int y = 0;
unsigned int w = cv_img->width;
unsigned int h = cv_img->height;
SetWindowPos(win_handle, HWND_NOTOPMOST, x, y, w, h, flags);
// Borderless
SetWindowLong(win_handle, GWL_STYLE, GetWindowLong(win_handle, GWL_EXSTYLE) | WS_EX_TOPMOST);
ShowWindow(win_handle, SW_SHOW);
And on my system it displays exactly what you asked on the question.
In many OpenGL tutorials, e.g. swiftless tutorials and many others, whenever there is an animation in the scene and the window is resized, the speed of the animation changes.
Description of strange behaviour
when the window is small, the animation speeds upwhen the window is large the animation slows downIs there an explanation for this?
#include <GL/glew.h> // Include the GLEW header file
#include <GL/glut.h> // Include the GLUT header file
bool* keyStates = new bool[256]; // Create an array of boolean values of length 256 (0-255)
bool movingUp = false; // Whether or not we are moving up or down
float yLocation = 0.0f; // Keep track of our position on the y axis.
float yRotationAngle = 0.0f; // The angle of rotation for our object
void keyOperations (void) {
if (keyStates[GLUT_KEY_LEFT]) { // If the left arrow key has been pressed
// Perform left arrow key operations
}
}
void display (void) {
keyOperations();
glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our <a title="window" href="http://www.swiftless.com/tutorials/opengl/window.html">window</a> to red
glClear(GL_COLOR_BUFFER_BIT); //Clear the colour buffer (more buffers later on)
glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations
glTranslatef(0.0f, 0.0f, -5.0f); // Push eveything 5 units back into the scene, otherwise we won't see the primitive
glTranslatef(0.0f, yLocation, 0.0f); // Translate our object along the y axis
glRotatef(yRotationAngle, 0.0f, 1.0f, 0.0f); // Rotate our object around the y axis
glutWireCube(2.0f); // Render the primitive
glFlush(); // Flush the OpenGL buffers to the window
if (movingUp) // If we are moving up
yLocation -= 0.005f; // Move up along our yLocation
else // Otherwise
yLocation += 0.005f; // Move down along our yLocation
if (yLocation < -3.0f) // If we have gone up too far
movingUp = false; // Reverse our direction so we are moving down
else if (yLocation > 3.0f) // Else if we have gone down too far
movingUp = true; // Reverse our direction so we are moving up
yRotationAngle += 0.005f; // Increment our rotation value
if (yRotationAngle > 360.0f) // If we have rotated beyond 360 degrees (a full rotation)
yRotationAngle -= 360.0f; // Subtract 360 degrees off of our rotation
}
void reshape (int width, int height) {
glViewport(0, 0, (GLsizei)width, (GLsizei)height); // Set our viewport to the size of our window
glMatrixMode(GL_PROJECTION); // Switch to the projection matrix so that we can manipulate how our scene is viewed
glLoadIdentity(); // Reset the projection matrix to the identity matrix so that we don't get any artifacts (cleaning up)
gluPerspective(60, (GLfloat)width / (GLfloat)height, 1.0, 100.0); // Set the Field of view angle (in degrees), the aspect ratio of our window, and the new and far planes
glMatrixMode(GL_MODELVIEW); // Switch back to the model view matrix, so that we can start drawing shapes correctly
}
void keyPressed (unsigned char key, int x, int y) {
keyStates[key] = true; // Set the state of the current key to pressed
}
void keyUp (unsigned char key, int x, int y) {
keyStates[key] = false; // Set the state of the current key to not pressed
}
int main (int argc, char **argv) {
glutInit(&argc, argv); // Initialize GLUT
glutInitDisplayMode (GLUT_SINGLE); // Set up a basic display buffer (only single buffered for now)
glutInitWindowSize (500, 500); // Set the width and height of the window
glutInitWindowPosition (100, 100); // Set the position of the window
glutCreateWindow ("You’re first OpenGL Window"); // Set the title for the window
glutDisplayFunc(display); // Tell GLUT to use the method "display" for rendering
glutIdleFunc(display); // Tell GLUT to use the method "display" as our idle method as well
glutReshapeFunc(reshape); // Tell GLUT to use the method "reshape" for reshaping
glutKeyboardFunc(keyPressed); // Tell GLUT to use the method "keyPressed" for key presses
glutKeyboardUpFunc(keyUp); // Tell GLUT to use the method "keyUp" for key up events
glutMainLoop(); // Enter GLUT's main loop
}
The way this is written it uses an "as fast as possible" rendering approach. This, together with V-Sync disabled will make the animation speed depend on the time it takes to calculate the pixels of one frame. The larger the window, the more pixels there are to fill (look up the keyword fillrate).
The solution is, to measure the time between rendering frames and advance the animation by this.