OpenGL - Not getting background color - c++

I am trying to build a simple OpenGL application in C++. I am using FLTK to build a Window, and within that I am drawing using OpenGL. The following is my code:
// Make the GUI here
#define WIN32
#include <GL/glew.h>
#include <GL/glut.h>
#include <FL/gl.h>
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Color_Chooser.H>
#include <FL/Fl_Gl_Window.H>
#include <FL/Fl_Menu_Bar.H>
#include <FL/fl_draw.H>
#include <FL/Fl_Button.H>
class Block
{
public:
Block(int x, int y, int z)
{
xyz[0] = x;
xyz[1] = y;
xyz[2] = z;
}
int getX(){ return xyz[0];}
int getY(){ return xyz[1];}
int getZ(){ return xyz[2];}
void setX(int x){ xyz[0]=x;}
void setY(int y){ xyz[1]=y;}
void setZ(int z){ xyz[2]=z;}
private:
int xyz[3];
};
// Snake is an array blocks.
Block* snake;
// Mouse is a single block
Block* mouse;
void renderEverything();
class GlWindow : public Fl_Gl_Window
{
public:
// Call back for draw
void draw()
{
glTranslatef(0.0f,0.0f, -10.0f);
// Get the current state of the universe and draw it
glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our window 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
// Render everything
renderEverything();
//glutSolidCube(5);
glFlush(); // Flush the OpenGL buffers to the window
}
// To handle key-events
void handle()
{
}
// Constructor
GlWindow(int X, int Y, int W, int H, const char* L=0): Fl_Gl_Window(X,Y,W,H,L)
{
}
};
void renderEverything()
{
glBegin(GL_QUADS);
glVertex3f(-1.0f,-1.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, 1.0f, 0.0f);
glVertex3f(-1.0f,-1.0f, 0.0f);
glEnd();
}
void buildGUI(int argc, char** argv)
{
// Main Window
Fl_Double_Window *window = new Fl_Double_Window(800,500);
window->label("Snake3D");
window->color(FL_LIGHT3);
window->begin();
// Menu Bar
Fl_Menu_Bar* menubar = new Fl_Menu_Bar(0,0,800,30);
menubar->color(FL_LIGHT3);
menubar->down_color(fl_rgb_color(0,145,255));
menubar->box(FL_THIN_UP_BOX);
menubar->add("File/Exit");
menubar->add("Help/About");
// OpenGL Window
GlWindow* gameWindow = new GlWindow(200,30,600,470);
// Start Button
Fl_Button* startButton = new Fl_Button(50,200,100,30,"Start");
Fl_Button* pauseButton = new Fl_Button(50,300,100,30,"Pause");
window->show();
window->end();
Fl::run();
}
int main(int argc, char ** argv)
{
// Build GUI
buildGUI(argc,argv);
}
According to the tutorial I am following, I should get a red background. But only half of my screen is colored
What might be going wrong?

Related

Gtk/gtkmm glarea queue render doesnt work with dedicated graphics

I started working on a github project (a logic gate simulator) with gtkmm and epoxy. I have an optimus laptop with debian buster and nvidia-bumblebee drivers installed and everything works fine except that if I start the program using optirun or primusrun, neither the glArea->queue_render, nor glArea->queue_draw function seems to work. I have to resize the window in order to rerender the glArea widget. Also sometimes when I restart the system and compile the program it won't start with bumblebee at all and outputs the following error:
311-0-no gl implementation is available
It might be something with my system, but optirun and primusrun usually work fine.
Any Idea what might be the cause of this problem?
the renderer class:
#ifndef RENDERER_DATA_H
#define RENDERER_DATA_H
#include <glm/mat4x4.hpp>
#include <glm/vec3.hpp>
#include <glm/vec2.hpp>
struct scene{ //viewport data
glm::mat4 proj;
glm::mat4 view;
glm::mat4 model;
glm::mat4 mvp;
float zoom = 1.0f;
glm::vec2 dim;
glm::vec3 pos = {0, 0, 1.0f};
};
struct pointer{ //mouse data
int button;
int x, y;
};
struct keyboard{ //keyboard data
};
#endif
#ifndef RENDERER_H
#define RENDERER_H
/*
This is the renderer of the viewport
*/
#include "viewport/shader.hpp"
#include "viewport/vertexbuffer.hpp"
#include "viewport/indexbuffer.hpp"
#include "viewport/vertexarray.hpp"
#include "viewport/objects/grid.hpp"
#include <gtkmm-3.0/gtkmm.h>
#include <gtkmm-3.0/gtkmm/glarea.h>
#include <glm/glm.hpp>
//#include <glm/gtx/transform.hpp>
#include <glm/gtc/matrix_transform.hpp>
//#include <gdkmm-3.0/gdkmm/glcontext.h>
//#include <glibmm-2.4/glibmm/refptr.h>
//#include <epoxy/gl.h>
//#include <epoxy/glx.h>
#include <iostream>
class Renderer{
public:
Renderer(Gtk::GLArea*); //constructor connects the following callbacks:
void realize(); //called when widget glArea is created
void unrealize(); //called when widget glArea is destroyed
void resize(int width, int height); //called when the glArea is resized
bool render(const Glib::RefPtr<Gdk::GLContext>&); //called when the viewport should render itself
bool mouse_move(GdkEventMotion* event); //called when both mouse button pressed and mouse moved
bool mouse_scroll(GdkEventScroll* event); //called when the mouse is wheel is rotated
bool button_press(GdkEventButton* button); //called when a button is pressed
bool button_release(GdkEventButton* button); //called when a button is released
private:
Gtk::GLArea* glArea; //pointer to the glArea widget, created in ui object
GLuint vao;
IndexBuffer* ibptr;
VertexBuffer* vbptr;
VertexArray* vaptr;
VertexBufferLayout* vblptr;
Shader* shader_program;
Grid* grid;
pointer mouse; //mouse variable obj
scene viewport; //viewport variable obj
void update_view(); //This function is resposible for paning and zooming the viewport
glm::vec3 mouse_translate(glm::vec3); //translates screen coords to world coords
};
#endif //
implementation:
//#include <ui.hpp>
#include "./renderer.hpp"
Renderer::Renderer(Gtk::GLArea* glarea)
/*:glArea(glarea)*/{
glArea = glarea;
glArea->add_events(Gdk::BUTTON_MOTION_MASK | Gdk::BUTTON1_MOTION_MASK | Gdk::BUTTON2_MOTION_MASK | Gdk::BUTTON3_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::SCROLL_MASK);
glArea->signal_realize().connect(sigc::mem_fun(*this, &Renderer::realize));
glArea->signal_unrealize().connect(sigc::mem_fun(*this, &Renderer::unrealize), false);
glArea->signal_render().connect(sigc::mem_fun(*this, &Renderer::render), false);
glArea->signal_resize().connect(sigc::mem_fun(*this, &Renderer::resize));
glArea->signal_motion_notify_event().connect(sigc::mem_fun(*this, &Renderer::mouse_move));
glArea->signal_scroll_event().connect(sigc::mem_fun(*this, &Renderer::mouse_scroll));
glArea->signal_button_press_event().connect(sigc::mem_fun(*this, &Renderer::button_press));
glArea->signal_button_release_event().connect(sigc::mem_fun(*this, &Renderer::button_release));
}
void Renderer::realize(){
std::clog<<"realize"<<std::endl;
//glArea->set_required_version(4, 5);
glArea->make_current();
glArea->set_auto_render(true);
std::clog<<"make current"<<std::endl;
//std::clog<<epoxy_gl_version()<<"\n";
//std::clog<<epoxy_glsl_version()<<"\n";
glArea->make_current();
std::cout<<glGetString(GL_VERSION)<<std::endl;
std::cout<<"realize\n";
try{
glArea->throw_if_error();
std::clog<<glGetString(GL_VERSION)<<"\n";
std::clog<<glGetString(GL_VENDOR)<<"\n";
char path[] = "./src/res/shaders";
shader_program = new Shader(path);
shader_program->bind();
//shader_program = Shader::create_shader_program(nullptr);
//glUseProgram(shader_program);
GLfloat pos[] = {
-0.5f, -0.5f, -1,
0.5f, -0.5f, -1,
0.5f, 0.5f, -1,
-0.5f, 0.5f, -1
};
GLuint ind[] = {
0, 1, 2,
2, 3, 0
};
vaptr = new VertexArray();
//glGenVertexArrays(1, &vao);
//glBindVertexArray(vao);
vbptr = new VertexBuffer(pos, 4 * 3 * sizeof(GLfloat));
vblptr = new VertexBufferLayout;
vblptr->add(3, GL_FLOAT);
//vblptr->add(3, GL_FLOAT);
//vblptr->add(2, GL_FLOAT);
vaptr->addBuffer(*vbptr, *vblptr);
//glEnableVertexAttribArray(0);
//glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, 0);
ibptr = new IndexBuffer(ind, 6);
//int location = epoxy_glGetUniformLocation(shader_program->get_program(), "u_Color");
//glUniform4f(location, 0.2f, 0.3f, 0.8f, 1.0f);
//glm::vec4 data = {0.2f, 0.3f, 0.8f, 1.0f};
shader_program->set_uniform4f ("u_Color", {0.2f, 0.3f, 0.8f, 1.0f});
//viewport.proj = glm::ortho(-width/height/2, width/height/2, -height/width/2, height/width/2);
//shader_program->set_uniform_mat4f ("mvp", viewport.proj);
//glBindVertexArray(0);
//glUseProgram(0);
//glBindBuffer(GL_ARRAY_BUFFER, 0);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}catch(const Gdk::GLError& gle){
std::cerr << "An error occured making the context current during realize:" << std::endl;
std::cerr << gle.domain() << "-" << gle.code() << "-" << gle.what() << std::endl;
}
grid = new Grid(glm::vec3(-3.0, 0.0, -1.0), glm::vec3(3.0, 0.0, -1.0));
}
void Renderer::unrealize(){
glArea->make_current();
delete vbptr;
delete ibptr;
delete vaptr;
delete vblptr;
delete shader_program;
try
{
glArea->throw_if_error();
}
catch(const Gdk::GLError& gle)
{
std::cerr << "An error occured making the context current during unrealize" << std::endl;
std::cerr << gle.domain() << "-" << gle.code() << "-" << gle.what() << std::endl;
}
}
void Renderer::resize(int width, int height){
viewport.dim.x = width;
viewport.dim.y = height;
}
bool Renderer::render(const Glib::RefPtr<Gdk::GLContext>& context ){
std::clog<<"render\n";
update_view();
//glArea->attach_buffers();
glClear(GL_COLOR_BUFFER_BIT);
grid->draw();
grid->m_shader->set_uniform_mat4f("mvp", viewport.mvp);
grid->draw();
shader_program->bind();
vaptr->bind();
//ibptr->bind();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glBindVertexArray(0);
glUseProgram(0);
return true;
}
bool Renderer::mouse_move(GdkEventMotion* event){
glm::vec3 diff = mouse_translate(glm::vec3(mouse.x, mouse.y, 0.0)) - mouse_translate(glm::vec3(event->x, event->y, 0.0));
std::clog<<diff.x<<" "<<diff.y<<"\n";
if(mouse.button == 1){
viewport.pos = viewport.pos - diff;
std::clog<<viewport.pos .x<<" "<<viewport.pos.y<<" "<<viewport.pos.z<<"\n";
//glArea->queue_draw();
//glArea->queue_draw();
glArea->queue_render();
//glArea->signal_render();
}
mouse.x = event->x;
mouse.y = event->y;
return true;
}
bool Renderer::mouse_scroll(GdkEventScroll* event){
if(event->direction == GDK_SCROLL_DOWN && viewport.zoom>1){
viewport.zoom = viewport.zoom - 0.1;
}else if(event->direction == GDK_SCROLL_UP && viewport.zoom<10){
viewport.zoom = viewport.zoom + 0.1;
}
glArea->queue_render();
std::clog<<viewport.zoom<<"\n";
return true;
}
bool Renderer::button_press(GdkEventButton* event){
std::clog<<event->button<<"\n";
mouse.button = event->button;
mouse.x = event->x;
mouse.y = event->y;
//if(event->mouse.button == 1){ //left mouse button
//
//}
return true;
}
bool Renderer::button_release(GdkEventButton* button){
mouse.button = 0;
return true;
}
void Renderer::update_view(){
std::clog<<"update view\n";
viewport.view = glm::translate(glm::mat4(1.0f), glm::vec3(viewport.pos.x, -viewport.pos.y, -viewport.pos.z));
viewport.model = glm::translate(glm::mat4(1.0f), glm::vec3( 0, 0, 1.0));
if(viewport.dim.x<viewport.dim.y){
viewport.proj = glm::ortho(-viewport.dim.x/viewport.dim.y/viewport.zoom, viewport.dim.x/viewport.dim.y/viewport.zoom, -1.0f/viewport.zoom, 1.0f/viewport.zoom);
}else{
viewport.proj = glm::ortho(-1.0f/viewport.zoom, 1.0f/viewport.zoom, -viewport.dim.y/viewport.dim.x/viewport.zoom, viewport.dim.y/viewport.dim.x/viewport.zoom);
}
viewport.mvp = viewport.proj * viewport.view * viewport.model;
shader_program->bind();
shader_program->set_uniform_mat4f ("mvp", viewport.mvp);
}
glm::vec3 Renderer::mouse_translate(glm::vec3 pos){
return glm::unProject(pos, viewport.model, viewport.proj, glm::vec4(0.0f, 0.0f, viewport.dim.x, viewport.dim.y));
}
Full project on github: LinuxGameGeek/logix
OpenGL is poorly integrated with GTK+3, for example on OS X, you'll have this error displayed because OpenGL is simply not implemented. Maybe this is the same case for you
In addition in gtkmm-3.18 a bug (fixed since this version) displaying this error when GLArea class was derived. But this is not your case.
If that may help you I have a similar application mixing OpenGL/GTKmm in Lecrapouille/SimTaDyn I guess this will give you the same error.

QOpenGLWidget's resizeGL is NOT the place to call glViewport?

I am experimenting with the new QOpenGLWidget class (note that this is not the QGLWidget class).
I am drawing a triangle. I have a trivial vertex shader which receives coordinates in clip space, so no matrices or projections are involved. One of the vertices has coordinates -1, -1, 0, 1, and another one has coordinates 1, 1, 0, 1.
When I have no call to glViewport whatsoever, the program renders as if I am calling glViewport(0, 0, w, h); in my resizeGL function, which I am not. Namely, the two vertices of the triangle are attached to the lowerleft and upperright corners of the window no matter how I resize the window.
When I actually add a call to glViewport in my resizeGL function, it is apparently ignored - doesn't matter if I pass w/2, h/2 or any other value, the rendering is exactly the same as it would be if I called glViewport(0, 0, w, h); (for instance, I would expect the triangle to appear in the lower-left quarter of the window in case of glViewport(0, 0, w/2, h/2);)
When I call glViewport(0, 0, width()/2, height()/2) in paingGL function, the rendering is as expected - everything is drawn in the lower-left quarter of the window.
So it seems that the glViewport is overridden somewhere between resizeGL and paintGL. What is going on and how do I fix it? Do I have to resort to doing viewport transformations in my paintGL function?
One of the differences between QGLWidget and QOpenGLWidgets listed in the documentation is that the latter renders to a framebuffer rather than directly to the screen. Could this hold the key to the explanation?
Just in case, I'm attaching the complete code for reference.
//triangle.h
#ifndef TRIANGLE_H
#define TRIANGLE_H
#include <QOpenGLBuffer>
#include <QOpenGLFunctions>
class Triangle
{
public:
Triangle();
void render();
void create();
private:
QOpenGLBuffer position_vbo;
QOpenGLFunctions *glFuncs;
};
#endif // TRIANGLE_H
//triangle.cpp
#include "triangle.h"
Triangle::Triangle()
:position_vbo(QOpenGLBuffer::VertexBuffer)
{
}
void Triangle::create()
{
glFuncs = QOpenGLContext::currentContext()->functions();
position_vbo.create();
float val[] = {
-1.0f, -1.0f, 0.0f, 1.0f,
0.0f, -0.366f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
};
position_vbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
position_vbo.bind();
position_vbo.allocate(val, sizeof(val));
position_vbo.release();
}
void Triangle::render()
{
position_vbo.bind();
glFuncs->glEnableVertexAttribArray(0);
glFuncs->glEnableVertexAttribArray(1);
glFuncs->glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glFuncs->glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)(3*4*sizeof(float)));
glFuncs->glDrawArrays(GL_TRIANGLES, 0, 3);
glFuncs->glDisableVertexAttribArray(0);
glFuncs->glDisableVertexAttribArray(1);
position_vbo.release();
}
//widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include "triangle.h"
class Widget : public QOpenGLWidget
, protected QOpenGLFunctions
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
protected:
virtual void initializeGL() override;
virtual void paintGL() override;
virtual void resizeGL(int w, int h) override;
private:
QOpenGLShaderProgram* program;
Triangle t;
};
#endif // WIDGET_H
//widget.cpp
#include "widget.h"
#include <exception>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QOpenGLWidget(parent)
{
}
Widget::~Widget()
{
}
void Widget::initializeGL()
{
initializeOpenGLFunctions();
program = new QOpenGLShaderProgram(this);
if(!program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/vertexshader.vert"))
{
throw std::exception(("Vertex Shader compilation error: " + program->log()).toLocal8Bit().constData());
}
if(!program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/fragmentshader.frag"))
{
throw std::exception(("Fragment Shader compilation error: " + program->log()).toLocal8Bit().constData());
}
if(!program->link())
{
throw std::exception(("Program Link error: " + program->log()).toLocal8Bit().constData());
}
t.create();
}
void Widget::paintGL()
{
glClearColor(0.f, 0.15f, 0.05f, 0.f);
glClear(GL_COLOR_BUFFER_BIT);
//glViewport(0, 0, width()/2, height()/2); //works!!
program->bind();
t.render();
program->release();
}
void Widget::resizeGL(int w, int h)
{
glViewport(0, 0, w/2, h/2); //doesn't work
}
//main.cpp
#include "widget.h"
#include <exception>
#include <QApplication>
#include <QMessageBox>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
try
{
Widget w;
w.show();
return a.exec();
}
catch(std::exception const & e)
{
QMessageBox::warning(nullptr, "Error", e.what());
}
}
//vertex shader
#version 330
layout (location = 0) in vec4 position;
layout (location = 1) in vec4 color;
smooth out vec4 theColor;
void main()
{
gl_Position = position;
theColor = color;
}
//fragment shader
#version 330
out vec4 fragColor;
smooth in vec4 theColor;
void main()
{
fragColor = theColor;
}
So it seems that the glViewport is overridden somewhere between resizeGL and paintGL. What is going on and how do I fix it? Do I have to resort to doing viewport transformations in my paintGL function?
Qt5 may use OpenGL for its own drawing. Also the content of widgets being children to a QOpenGLWindow are rendered to FBOs. So that means, that a lot of glViewport calls are made between your code and what Qt does.
When I actually add a call to glViewport in my resizeGL function, it is apparently ignored (…)
yes. And your expectation is what exactly? The only valid place to call glViewport for a OpenGL program to be robust is in the drawing code. Each and every tutorial out there, that places glViewport in the window resize handler is wrong and should be burned.
When I call glViewport(0, 0, width()/2, height()/2) in paingGL function, the rendering is as expected
Yes, that's how you're supposed to use it.

Using glfw and glew

I have problem understanding some opengl stuff using GLFW and GLEW.
i have 3 files shown below:
main.cpp:
#include "gamewindow.h"
int main() {
GameWindow *gameWindow = new GameWindow(1024, 768, "FirstOpenGLGame");
/* Loop until the user closes the window */
while (gameWindow->getRunning()) {
/* Render here */
gameWindow->render();
gameWindow->update();
gameWindow->setRunning();
}
delete gameWindow;
glfwTerminate();
return 0;
}
This is where the problem is, gamewindow.cpp:
#include "gamewindow.h"
GameWindow::GameWindow(int width, int height, const char* title) : _running(true), _height(1024), _width(1024 * (16/9))
{
/* Initialize the library */
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(width, height, title, NULL, NULL);
if(!window) {
glfwTerminate();
exit(0);
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
if(!glewInit()){ // <-- problem is this
glfwTerminate();
exit(EXIT_FAILURE);
}
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
coordSettings();
}
void GameWindow::setRunning() {
_running = !glfwWindowShouldClose(window);
}
bool GameWindow::getRunning() {
return _running;
}
void GameWindow::render() {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_QUADS);
glVertex2d(0.0f, 0.0f);
glVertex2d(100.0f, 0.0f);
glVertex2d(100.0f, 800.0f);
glVertex2d(0.0f, 800.0f);
glEnd();
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
void GameWindow::update() {
}
void GameWindow::coordSettings() {
glViewport( 0, 0, _width, _height );
glMatrixMode(GL_PROJECTION);
glOrtho(0.0, _width, 0.0, _height, 0.0, -1.0);
glMatrixMode(GL_MODELVIEW);
}
and last the header file gamewindow.h:
#ifndef GAMEWINDOW_H
#define GAMEWINDOW_H
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
class GameWindow
{
private:
GLFWwindow* window;
bool _running;
GLfloat _width;
GLfloat _height;
void coordSettings();
public:
GameWindow(int width, int height, const char* title);
void setRunning();
bool getRunning();
void render();
void update();
};
#endif // GAMEWINDOW_H
everything works fine, but then i try to call glewInit() (without really understanding is i need to, or when i need to) but then nothing works. the program starts, but there is no window with a quad in it, like before. why is this? how is GLEW even used, and do i need it?

Display images on a transparent background with no border in C++ / OpenGL

I am looking for a way to display two png images (in fact, it will be numbers, my aim is to create an overlay for live streaming to display players score and some further additional content) on a window with transparent background with no border. So that we just see the score over the window placed behind.
Is there any way to do something like that ? I have already tried many things with SDL, textures, but nothing led me to any satisfying result. The best I found was some dirty code almost working but completely unusable.
If possible, the solution may let possible to add the functionality that when you click left or right on one of the 2 scores, it is incremented or decremented.
Edit: Here is my current code. I started new without any bit of the dirty code I had before, because I would like to understand what I am doing. I have my 2 numbers displayed as textures, now I would like to remove borders and title bar of my window, and make my background transparent.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <windows.h>
#include <windowsx.h>
#include <math.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include "sdlglutils.h"
#include <assert.h>
#include <tchar.h>
using namespace std;
int overlay;
int TimerEnabled;
GLfloat posX, posY, posZ;
GLuint texture_0, texture_1, texture_2, texture_3;
void Initialize()
{
glEnable(GL_ALPHA_TEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0, 0, 0, 0);
glEnable(GL_TEXTURE_2D);
}
void Reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)w/(GLfloat)h,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
texture_0 = loadTexture("0.png");
texture_1 = loadTexture("1.png");
texture_2 = loadTexture("2.png");
texture_3 = loadTexture("3.png");
return;
}
void Draw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glTranslatef(posX,posY,posZ);
glScalef(1.0f,1.0f,1.0f);
glPushMatrix();
glTranslated(-6, 8, 0);
glBindTexture(GL_TEXTURE_2D, texture_1);
glBegin(GL_QUADS);
glTexCoord2d(0,0); glVertex2d(0,0);
glTexCoord2d(1,0); glVertex2d(1,0);
glTexCoord2d(1,1); glVertex2d(1,1);
glTexCoord2d(0,1); glVertex2d(0,1);
glEnd();
glPopMatrix();
glPushMatrix();
glTranslated(6, 8, 0);
glBindTexture(GL_TEXTURE_2D, texture_2);
glBegin(GL_QUADS);
glTexCoord2d(0,0); glVertex2d(0,0);
glTexCoord2d(1,0); glVertex2d(1,0);
glTexCoord2d(1,1); glVertex2d(1,1);
glTexCoord2d(0,1); glVertex2d(0,1);
glEnd();
glPopMatrix();
glFlush();
}
void Display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
Draw();
glutSwapBuffers();
}
void KeyboardSpecialEvent( int key, int x, int y)
{
switch(key)
{
case(GLUT_KEY_UP) :
{
posY += 0.3;
}break;
case(GLUT_KEY_DOWN) :
{
posY -= 0.3;
}break;
case(GLUT_KEY_LEFT) :
{
posX -= 0.3;
}break;
case(GLUT_KEY_RIGHT) :
{
posX += 0.3;
}break;
}
}
void MouseEvent( int button, int state, int x, int y){ };
void MotionMouseEvent( int x, int y ){ };
void IdleEvent(){ };
void TimerEvent(int time)
{
glutPostRedisplay();
if(TimerEnabled)
glutTimerFunc(10, TimerEvent, time);
}
void KeyboardEvent( unsigned char key, int x, int y)
{
switch(key)
{
case ' ' :
{
TimerEnabled = !TimerEnabled;
if (TimerEnabled)
glutTimerFunc(40, TimerEvent, 0);
}
break;
case 'q' :
{
exit(0);
}
break;
}
}
int main(int argc, char** argv)
{
posX = 0;
posY = 0;
posZ = -25;
TimerEnabled = 1;
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGBA);
glutInitWindowSize(1600,900);
glutInitWindowPosition(0,0);
overlay = glutCreateWindow("ScoreOverlay");
//glutFullScreen();
Initialize();
glutDisplayFunc(Display);
glutReshapeFunc(Reshape);
glutKeyboardFunc(KeyboardEvent);
glutSpecialFunc(KeyboardSpecialEvent);
glutMouseFunc(MouseEvent);
glutMotionFunc(MotionMouseEvent);
glutIdleFunc(IdleEvent);
glutTimerFunc(40, TimerEvent, 0);
glutMainLoop();
return 0;
}
Here is a working base sample (using c++ with clr support) that could help you.
You need to adapt it to your need (for example use DrawImage instead of FillEllipse)
using namespace System;
using namespace System::Drawing;
using namespace System::Windows::Forms;
ref class MyForm : public Form
{
public:
MyForm()
{
this->m_brush = gcnew SolidBrush(Color::Blue);
this->m_canvas = gcnew System::Windows::Forms::Panel();
this->m_canvas->BackColor = Color::Pink;
this->m_canvas->Dock = System::Windows::Forms::DockStyle::Fill;
this->m_canvas->Location = System::Drawing::Point(0, 0);
this->m_canvas->Margin = System::Windows::Forms::Padding(0);
this->m_canvas->Name = "Canvas";
this->m_canvas->Paint += gcnew System::Windows::Forms::PaintEventHandler(this, &MyForm::canvas_Paint);
this->m_canvas->TabIndex = 0;
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->BackColor = Color::Pink;
this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::None;
this->ClientSize = System::Drawing::Size(200, 200);
this->Controls->Add(this->m_canvas);
this->KeyDown += gcnew System::Windows::Forms::KeyEventHandler(this, &MyForm::form_KeyDown);
this->TransparencyKey = Color::Pink;
this->Name = "MyForm";
this->Text = "MyForm";
}
private:
void canvas_Paint(Object^ sender, PaintEventArgs^ e) {
e->Graphics->FillEllipse(this->m_brush, Rectangle(50, 50, 100, 100));
}
void form_KeyDown(System::Object^ sender, System::Windows::Forms::KeyEventArgs^ e) {
// Test key ...
this->m_canvas->Invalidate();
// ...
}
Brush^ m_brush;
Panel^ m_canvas;
};
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
// Enabling Windows XP visual effects before any controls are created
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
// Create the main window and run it
Application::Run(gcnew MyForm());
return 0;
}
It looks like you need this on Windows. Have you looked at Layered Windows?
Unless you need OpenGL for the graphics for some reason I think you'll be better off loading your images as regular bitmaps and blitting them to the layered window directly. Using OpenGL you would need to draw to a texture map, then take that texture and blit it to the layered window.

Drawing an array of objects in Open GL Glut

I have been trying to draw multiple balls for a game I am making, I have tried to get this working but there are problems in my init class and display method class, I have commented it where the errors are.
Ball.h:
#pragma once
#include "Vector2f.h"
#include "Vector3f.h"
class Ball
{
private:
Vector3f position;
Vector3f velocity;
public:
Ball(void);
~Ball(void);
void Draw();
void SetPos(Vector3f New_position);
void SetVel(Vector3f New_velocity);
Vector3f GetPos();
};
Ball.cpp
#include "Ball.h"
#include "Vector2f.h"
#include "Vector3f.h"
#include "Glut/glut.h"
#include "GL/gl.h"
#include "GL/glu.h"
Ball::Ball(void)
{
Vector3f Temp_position;
position = Temp_position;
Vector3f Temp_velocity;
velocity = Temp_velocity;
}
Ball::~Ball(void)
{
}
void Ball::SetPos(Vector3f New_position)
{
position = New_position;
}
void Ball::Draw()
{
glPushMatrix();
glTranslatef(position.X(), position.Y(), position.Z());
glColor3d(1, 0, 0);
glutSolidSphere(0.3, 50, 50);
glPopMatrix();
}
void Ball::SetVel(Vector3f New_velocity)
{
velocity = New_velocity;
}
Vector3f Ball::GetPos()
{
Vector3f temp;
temp = position;
return temp;
}
I want the be able to draw an array of the balls in Main.cpp
Main.cpp
#include "Display.h"
#include "Vector3f.h"
#include "Ball.h"
#include "Glut/glut.h"
#include "GL/gl.h"
#include "GL/glu.h"
#include <math.h>
static float TableWidth = 4; // Z axis normal = 4
float Display::eyeX = -7.5; //-7.5
float Display::eyeY = 3; //3
float Display::eyeZ = 5; //5
float Display::Position[4] = { 1.0f, 0.0f, -3.5, 1.0f };
float Display::translateZ = -3.5;
float Display::translateX = 0.0;
//Timer Display::m_Timer = Timer();
float Display::lightX = 5.0; //5 2.5
float Display::lightY = 5.0;
float Display::lightZ = 2.5;
float m_TableX = -5.0f;
float m_TableZ = -2.5f;
float m_TableWidth = 2.5f;
float m_TableLength = 5.0f;
float ballx = 0.7;
float bally = 0.1;
float ballz = -0.7;
Ball Redball;
float BALL_RED_START = 0;
float RADIUS_OF_BALL = 0.3;
float BALL_RED_END = 8;
float m_ball;
void Display::Init(int argc, char ** argv)
{
glutInit(&argc, argv); // initializes glut
// sets display mode. These parameter set RGB colour model
// and double buffering.
glutInitWindowSize(500,500);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("Pool Version 1.0");
// Set glut callback functions
glutDisplayFunc(Display::DisplayScene);
glutIdleFunc(Display::Idle);
glutReshapeFunc(Display::Resize);
glutKeyboardFunc(Display::KeyboardInput);
//m_Timer.getSeconds();
glEnable(GL_DEPTH_TEST);
glPointSize(5);
glEnable(GL_NORMALIZE);
glEnable(GL_LIGHTING);
glClearColor(0,0,0,1);
glEnable(GL_COLOR_MATERIAL);
float white[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glLightfv(GL_LIGHT0, GL_DIFFUSE, white);
glEnable(GL_LIGHT0);
Redball.SetPos(Vector3f(0.0,0.3,0.0));
for(int i = BALL_RED_START; i < BALL_RED_START; i++)
{
glColor3f(1,0,0);
Redball[i]->SetPos(Vector3f (i+128,RADIUS_OF_BALL,45)); //I tried this but it doesn't work Error C2227
}
// Begin glut main loop
glutMainLoop();
}
void BallMovement()
{
//Vector3f position(0.0,0.3,0.0);
/*Redball.SetPos(Vector3f(0.0,0.3,0.0));*/
Vector3f New_velocity(0.01,0,0);
Redball.SetVel(New_velocity);
Vector3f New_position;
Vector3f Old_position;
Old_position = Redball.GetPos();
//New_position = Old_position + New_velocity;
New_position.SetX(Old_position.X() + New_velocity.X());
New_position.SetY(Old_position.Y() + New_velocity.Y());
New_position.SetZ(Old_position.Z() + New_velocity.Z());
Redball.SetPos(New_position);
}
void Display::DisplayScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the back buffer
glPushMatrix();
glLoadIdentity();
glNormal3f(0,1,0);
Vector3f didums = Redball.GetPos();
gluLookAt(eyeX, eyeY, eyeZ, // eye position
0, 0, 0, // what I'm looking at
0.0, 1.0, 0); // Up direction
float Position[] = {lightX, lightY, lightZ, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, Position);
DrawLight(0, Position);
/* Rendering code goes here */
for (int i = BALL_RED_START; i<BALL_RED_END;i++)
{
glColor3f(1,0,0);
Redball[i]->Draw(); //I tried this but it doesn't work Error C2227
}
drawTable();
drawTableLegFrontLeft();
drawTableLegFrontRight();
drawTableLegBackLeft();
drawTableLegBackRight();
drawCushions();
//drawCircle();
//drawHCircle();
Table(-2,-4.5,2,4.5); // Draws the table top in trianglestrip -4.5, 0.5, -0.5, 9.5
glPopMatrix();
glutSwapBuffers(); // Swap the front and back buffers
}
void Display::Resize(int w, int h)
{
/* Resize is called when window is resized */
glMatrixMode(GL_PROJECTION); // set matrix mode to profection
// this dictates how the 3d scene is "squashed" onto the 2d screen
glLoadIdentity();
glViewport(0, 0, w, h); // Set the part of the window to use.
gluPerspective(45, // field of view
(float)w/(float)h, // ration of window
1, // front clipping plane
1000 // back clipping plane
); // set the area in the 3d scene to draw
glMatrixMode(GL_MODELVIEW); // Setthe matrix mode to model view
// the matrix specifies how the 3d scene is viewed
/*glLoadIdentity();
gluLookAt(-3.5, 2, eyeZ, // eye position
1, 1, 0, // what I'm looking at
0.0, 1.0, 0); // Up direction*/
}
void Display::Idle()
{
/* When nothing else is happening, idle is called.
* Simulation should be done here and then
* the display method should be called
*/
BallMovement();
glutPostRedisplay();
}
I see you have declared Ball as Ball Redball; which will create a single Ball on the stack.
Then you attempt to treat it as a collection of Balls with Redball[i]->SetPos(...) and Redball[i]->Draw(). It appears you are attempting to work with 8 of them.
What you want to do is create an array of Balls, with a max size of 8 (according to BALL_RED_END). For simplicity, you could do
Ball RedBall[8];
for( //some conditions here )
{
RedBall[i].Draw();
}
as your declaration and usage.
Remember that anytime you use Redball.SetPos(...) will no longer be valid.