OpenGL 4.0 and WxWidgets 3.1.0

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
m0rr0w
In need of some credit
In need of some credit
Posts: 6
Joined: Wed Aug 16, 2017 4:25 pm

OpenGL 4.0 and WxWidgets 3.1.0

Post by m0rr0w »

Hey I'm trying to use openGL 4.0 and wxWidgets 3.1.0. I have this code:

Code: Select all

#include "wx/wx.h";
#include "wx/notebook.h";
#include <GL/glew.h>;
#include "wx/glcanvas.h";
#include <GL/GL.h>;
#include <GL/glu.h>;

// Declare the application class
class MyApp : public wxApp
{
public:
	// Called on application startup
	virtual bool OnInit();
};
// Declare our main frame class
class MyFrame : public wxFrame
{
public:
	wxNotebook* nbHierarchy = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(200, 300));
	wxNotebook* nbScene = new wxNotebook(this, wxID_ANY, wxDefaultPosition , wxSize(800, 600));
	wxNotebook* nbInspector = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(200, 300));
	wxGLCanvas* myCanvas;
	wxGLContext* myContext;
	// Constructor
	MyFrame(const wxString& title);
	// Event handlers
	void OnQuit(wxCommandEvent& event);
	void OnAbout(wxCommandEvent& event);
private:
	// This class handles events
	DECLARE_EVENT_TABLE()
};
// Implements MyApp& GetApp()
DECLARE_APP(MyApp)
// Give wxWidgets the means to create a MyApp object
IMPLEMENT_APP(MyApp)
// Initialize the application
bool MyApp::OnInit()
{
	// Create the main application window
	MyFrame *frame = new MyFrame(wxT("War Engine Version 0"));
	// Show it
	frame->Show(true);
	// Start the event loop
	return true;
}
// Event table for MyFrame
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
EVT_MENU(wxID_EXIT, MyFrame::OnQuit)
END_EVENT_TABLE()
void MyFrame::OnAbout(wxCommandEvent& event)
{
	wxString msg;
	msg.Printf(wxT("Hello and welcome to %s."),
		"War Engine Version 0");

	wxMessageBox(msg, wxT("About War Engine"),
		wxOK | wxICON_INFORMATION, this);
}
void MyFrame::OnQuit(wxCommandEvent& event)
{
	// Destroy the frame
	Close();
}

MyFrame::MyFrame(const wxString& title)
	: wxFrame(NULL, wxID_ANY, title)
{
	// Create a menu bar
	wxMenu *fileMenu = new wxMenu;
	// The “About” item should be in the help menu
	wxMenu *helpMenu = new wxMenu;
	helpMenu->Append(wxID_ABOUT, wxT("&About...\tF1"),
		wxT("ABout this program."));
	fileMenu->Append(wxID_EXIT, wxT("E&xit\tAlt - X"),
		wxT("Quit this program"));
	// Now append the freshly created menu to the menu bar...
	wxMenuBar *menuBar = new wxMenuBar();
	menuBar->Append(fileMenu, wxT("&File"));
	menuBar->Append(helpMenu, wxT("&Help"));
	// ... and attach this menu bar to the frame
	SetMenuBar(menuBar);
	// Create a status bar just for fun
	CreateStatusBar(2);
	SetStatusText(wxT("Welcome to War Engine!"));

	wxPanel* hierarchyWindow = new wxPanel(nbHierarchy, wxID_ANY);
	nbHierarchy->AddPage(hierarchyWindow, "Hierarchy", false);

	wxPanel* sceneWindow = new wxPanel(nbScene, wxID_ANY);
	wxGLAttributes canvasAttrib;
	canvasAttrib.PlatformDefaults().Defaults().EndList();

	bool accepted = wxGLCanvas::IsDisplaySupported(canvasAttrib);

	if (accepted)
	{
		myCanvas = new wxGLCanvas(this, canvasAttrib);
	}
	else
	{
		wxMessageBox(wxT("Visual attributes not supported."), wxT("Error"));
	}

	wxGLContextAttrs contextAttr;
	contextAttr.PlatformDefaults().OGLVersion(4, 0).EndList();
	myContext = new wxGLContext(myCanvas, NULL, &contextAttr);

	if(!myContext->IsOK() )
	{
		wxMessageBox(wxT("Failed to set OpenGL 4.0"), wxT("Error"));
	}

	myCanvas = new wxGLCanvas(nbScene, canvasAttrib, wxID_ANY, wxDefaultPosition, wxSize(800, 600));
	myContext = new wxGLContext(myCanvas);

	myCanvas->SetCurrent(*myContext);

	nbScene->AddPage(myCanvas, "Scene", false);
	nbScene->AddPage(sceneWindow, "Game", false);

	//glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
	//glClear(GL_COLOR_BUFFER_BIT);

	wxPanel* inspectorWindow = new wxPanel(nbInspector, wxID_ANY);
	nbInspector->AddPage(inspectorWindow, "Inspector", false);

	wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
	sizer->Add(nbHierarchy, 0, wxEXPAND, 0);
	sizer->Add(nbScene, 1, wxEXPAND, 0);
	sizer->Add(nbInspector, 0, wxEXPAND, 0);
	sizer->SetSizeHints(this);
	SetSizer(sizer);

	if (glewInit() != GLEW_OK)
	{
		wxMessageBox(wxT("GLEW cant initialize."), wxT("Error"));
	}
}
I'm trying to put a canvas in the wxNotebook page. All that shows up on the page that my wxGLCanvas is in is a grey bar on the right side. Trying to adjust the size of the canvas doesn't do anything as far as the grey bar goes so is this the canvas or some type of error?

What I have so far I got from openGL/notebook samples and the wxwidgets book. I don't wanna deal with shaders yet but I just want to get a blank red window to show then I'll move onto a triangle, then 3d models, etc. IS anyone familiar enough with this to provide some basic code to show the red window? I think I pulled all I can from the sample...I don't know what else to do.
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: OpenGL 4.0 and WxWidgets 3.1.0

Post by doublemax »

You're creating two wxGLCanvas instances and assign them to the same pointer without deleting the first. That can't be right.
You should base your code on the "pyramid" sample that comes with wxWidgets, it's the newest one.

First try to get the drawing to appear in a plain window, if that works, put it into a wxNoteBook.
Use the source, Luke!
m0rr0w
In need of some credit
In need of some credit
Posts: 6
Joined: Wed Aug 16, 2017 4:25 pm

Re: OpenGL 4.0 and WxWidgets 3.1.0

Post by m0rr0w »

Do u know how to setup opengl with this wxwidgets though? This code here gives a little white box like 5 pixels in width and height in the upper left corner (even without the drawing code) of the frame and the window goes unresponsive. I know it goes unresponsive because of the do while loop but shouldn't it atleast be displaying the triangle? I know I'm doing something wrong but I have no idea what. Please help! [-o<

Code: Select all

#include "wx/wx.h";
#include "wx/notebook.h";
#include <GL/glew.h>;
#include "wx/glcanvas.h";
#include <GL/GL.h>;
#include <GL/glu.h>;

static const GLfloat g_vertex_buffer_data[] = {
	-1.0f, -1.0f, 0.0f,
	1.0f, -1.0f, 0.0f,
	0.0f,  1.0f, 0.0f,
};

// Declare the application class
class MyApp : public wxApp
{
public:
	// Called on application startup
	virtual bool OnInit();
	void Render();
};

void MyApp::Render()
{
	// This will identify our vertex buffer
	GLuint vertexbuffer;
	// Generate 1 buffer, put the resulting identifier in vertexbuffer
	glGenBuffers(1, &vertexbuffer);
	// The following commands will talk about our 'vertexbuffer' buffer
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
	// Give our vertices to OpenGL.
	glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);

	do
	{
		// 1rst attribute buffer : vertices
		glEnableVertexAttribArray(0);
		glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
		glVertexAttribPointer(
			0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
			3,                  // size
			GL_FLOAT,           // type
			GL_FALSE,           // normalized?
			0,                  // stride
			(void*)0            // array buffer offset
		);
		// Draw the triangle !
		glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle
		glDisableVertexAttribArray(0);



	} while (true);
}
// Declare our main frame class
class MyFrame : public wxFrame
{
public:
	/*wxNotebook* nbHierarchy = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(200, 300));
	wxNotebook* nbScene = new wxNotebook(this, wxID_ANY, wxDefaultPosition , wxSize(800, 600));
	wxNotebook* nbInspector = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(200, 300));  */
	wxGLCanvas* myCanvas;
	wxGLContext* myContext;
	// Constructor
	MyFrame(const wxString& title);
	// Event handlers
	void OnQuit(wxCommandEvent& event);
	void OnAbout(wxCommandEvent& event);
private:
	// This class handles events
	DECLARE_EVENT_TABLE()
};
// Implements MyApp& GetApp()
DECLARE_APP(MyApp)
// Give wxWidgets the means to create a MyApp object
IMPLEMENT_APP(MyApp)
// Initialize the application
bool MyApp::OnInit()
{
	// Create the main application window
	MyFrame *frame = new MyFrame(wxT("War Engine Version 0"));
	// Show it
	frame->Show(true);
	// Start the event loop
	Render();
	return true;
}
// Event table for MyFrame
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
EVT_MENU(wxID_EXIT, MyFrame::OnQuit)
END_EVENT_TABLE()
void MyFrame::OnAbout(wxCommandEvent& event)
{
	wxString msg;
	msg.Printf(wxT("Hello and welcome to %s."),
		"War Engine Version 0");

	wxMessageBox(msg, wxT("About War Engine"),
		wxOK | wxICON_INFORMATION, this);
}
void MyFrame::OnQuit(wxCommandEvent& event)
{
	// Destroy the frame
	Close();
}

MyFrame::MyFrame(const wxString& title)
	: wxFrame(NULL, wxID_ANY, title)
{
	// Create a menu bar
	wxMenu *fileMenu = new wxMenu;
	// The “About” item should be in the help menu
	wxMenu *helpMenu = new wxMenu;
	helpMenu->Append(wxID_ABOUT, wxT("&About...\tF1"),
		wxT("ABout this program."));
	fileMenu->Append(wxID_EXIT, wxT("E&xit\tAlt - X"),
		wxT("Quit this program"));
	// Now append the freshly created menu to the menu bar...
	wxMenuBar *menuBar = new wxMenuBar();
	menuBar->Append(fileMenu, wxT("&File"));
	menuBar->Append(helpMenu, wxT("&Help"));
	// ... and attach this menu bar to the frame
	SetMenuBar(menuBar);
	// Create a status bar just for fun
	CreateStatusBar(2);
	SetStatusText(wxT("Welcome to War Engine!"));

	wxGLAttributes canvasAttrib;
	canvasAttrib.PlatformDefaults().Defaults().EndList();

	bool accepted = wxGLCanvas::IsDisplaySupported(canvasAttrib);

	if (accepted)
	{
		myCanvas = new wxGLCanvas(this, canvasAttrib);
	}
	else
	{
		wxMessageBox(wxT("Visual attributes not supported."), wxT("Error"));
	}

	wxGLContextAttrs contextAttr;
	contextAttr.PlatformDefaults().OGLVersion(4, 0).EndList();
	myContext = new wxGLContext(myCanvas, NULL, &contextAttr);

	if (!myContext->IsOK())
	{
		wxMessageBox(wxT("Failed to set OpenGL 4.0"), wxT("Error"));
		return;
	}

	myCanvas->SetCurrent(*myContext);

	if (glewInit() != GLEW_OK)
	{
		wxMessageBox(wxT("GLEW cant initialize."), wxT("Error"));
	}

	/*wxPanel* hierarchyWindow = new wxPanel(nbHierarchy, wxID_ANY);
	nbHierarchy->AddPage(hierarchyWindow, "Hierarchy", false);

	wxPanel* sceneWindow = new wxPanel(nbScene, wxID_ANY);
	wxGLAttributes canvasAttrib;
	canvasAttrib.PlatformDefaults().Defaults().EndList();

	bool accepted = wxGLCanvas::IsDisplaySupported(canvasAttrib);

	if (accepted)
	{
	myCanvas = new wxGLCanvas(this, canvasAttrib);
	}
	else
	{
	wxMessageBox(wxT("Visual attributes not supported."), wxT("Error"));
	}

	wxGLContextAttrs contextAttr;
	contextAttr.PlatformDefaults().OGLVersion(4, 0).EndList();
	myContext = new wxGLContext(myCanvas, NULL, &contextAttr);

	if(!myContext->IsOK() )
	{
	wxMessageBox(wxT("Failed to set OpenGL 4.0"), wxT("Error"));
	}

	myContext = new wxGLContext(myCanvas);

	myCanvas->SetCurrent(*myContext);

	nbScene->AddPage(myCanvas, "Scene", false);
	nbScene->AddPage(sceneWindow, "Game", false);

	//glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
	//glClear(GL_COLOR_BUFFER_BIT);

	wxPanel* inspectorWindow = new wxPanel(nbInspector, wxID_ANY);
	nbInspector->AddPage(inspectorWindow, "Inspector", false);

	wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
	sizer->Add(nbHierarchy, 0, wxEXPAND, 0);
	sizer->Add(nbScene, 1, wxEXPAND, 0);
	sizer->Add(nbInspector, 0, wxEXPAND, 0);
	sizer->SetSizeHints(this);
	SetSizer(sizer);

	if (glewInit() != GLEW_OK)
	{
	wxMessageBox(wxT("GLEW cant initialize."), wxT("Error"));
	}

	*/
}
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: OpenGL 4.0 and WxWidgets 3.1.0

Post by doublemax »

Does the pyramid sample work for you? If yes, then it should contain everything you need.
Use the source, Luke!
coderrc
Earned some good credits
Earned some good credits
Posts: 141
Joined: Tue Nov 01, 2016 2:46 pm

Re: OpenGL 4.0 and WxWidgets 3.1.0

Post by coderrc »

I dont see where you set up the sizers, added the canvas to the sizer, called the appropriate gui layout functions, etc.
Nor do I see where you have given the canvas fixed size/position.

So, it seems reasonable that you just get a 5x5 canvas in the top left corner since thats where bad children must go when they dont tell their parents where they are.
Manolo
Can't get richer than this
Can't get richer than this
Posts: 827
Joined: Mon Apr 30, 2012 11:07 pm

Re: OpenGL 4.0 and WxWidgets 3.1.0

Post by Manolo »

You are doing several things in a wrong way.

First, you don't need to generate two wxGLCanvas nor two wxGLContext. Just create a wxGLCanvas as a child of other window, like a wxFrame, a wxNoteBook panel, etc. Use the visual attributes you need (RGBA, depth buffer, etc) or get a default ones. You can check if those visual attributes are accepted without creating a wxGLCanvas, using the static wxGLCanvas::IsDisplaySupported().
Next create a wxGLContext with the version required. Using the attribute CoreProfile is recomended (even required in OSX to get a OGL version >= 3.2). If you are learning OpenGL forget the old "fixed pipeline" commands (only available with no CoreProfile).

Set the ViewPort. The default GL uses is the first size of the associated window. Your code uses wxSizer's (advice: use them), and thus the window size will change before its first redraw. Use an event handler to set the ViewPort every time the window changes its size (typically in wx samples "OnSize" handler).

With CoreProfile you must use VAOs and shaders (Vertex and Fragment as a minimum).

Why do you have a forever loop in MyApp::Render()?. It seems you are following some tutorial based in other API (SDL by chance?).
There are two main tasks with OGL: updating data to the GPU (e.g. triangles) and rendering them. You can upload when you want: at window creation, as a response to user action, or whatever. The thing you must observe is that the context must be set as current before any GL-command.
With wxWidgets you do rendering when the window needs to be repainted (a paint-event). You can force a repaint because the data have changed.

And now study the pyramid sample and find there the points I'm taking about.
Post Reply