This question has been posed all over the internet yet every code example I try seem to have the same result as all the attempts I have personally pursued towards generating a simple triangle with OpenGL and SDL2. Before switching to a different windowing API my curiosity won't allow me to let this dilemma simply be.
As for my question to be solved, I simply wish to figure out whether the source is my system ( in consideration to the fact that all the code examples I have found all look similar and seems to make itself known on 2 different computers ) or if I'm just doing something wrong myself.
My PC has a GTX 1050m running on ubuntu 18.04 my drivers are the official nvidia drivers on the ubuntu ppa it is capable of OpenGL 4.6
This is display.h my header file for initializing SDL2 and Glew
#ifndef DISPLAY_H
#define DISPLAY_H
#include<SDL2/SDL.h>
#include<string>
class Display
{
public:
//initializes SDL2 and Glew
Display( int width, int height, const std::string& title );
//Clears the screen and creates a triangle
void Clear();
//Calls SDL_GL_SwapWindow()
void Update();
//Determines whether or not SDL_QUIT Event is called
bool IsClosed();
//Destroys application
virtual ~Display();
protected:
private:
Display( const Display& other )
void operator=( const Display& other );
SDL_Window* m_window;
SDL_GLContext m_glContext;
bool m_isClosed;
};
#endif //DISPLAY_H
This is display.cpp
//Constructor and Destructor container
#include"display.h"
//Glew container
#include<GL/glew.h>
//Standard I\0 lib
#include<cstdio>
//Constructor
Display::Display( int width, int height, const std::string& title )
{
//SDL2 initialization and error check
if( SDL_Init( SDL_INIT_VIDEO ) != 0 ){
printf( "Unable to initialize SDL: %s\n", SDL_GetError() );
SDL_ClearError();
}
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
SDL_GL_CONTEXT_PROFILE_COMPATIBILITY );
//SDL Create window stored in variable m_window
m_window = SDL_CreateWindow( title.c_str(),
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
width,
height,
SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE );
// Error checking window
if( !m_window ) {
fprintf( stderr, "Could not create window: %s\n", SDL_GetError() );
return;
}
//Creates OpenGL context
m_glContext = SDL_GL_CreateContext( m_window );
if ( !m_glContext ){
fprintf( stderr, "Couldn't create context: %s\n", SDL_GetError() );
return;
}
//Makes the open window the current context
SDL_GL_MakeCurrent( m_window, m_glContext );
//Checks How OpenGL handled setting
int rs, gs,bs;
SDL_GL_GetAttribute( SDL_GL_RED_SIZE, &rs );
SDL_GL_GetAttribute( SDL_GL_GREEN_SIZE, &gs );
SDL_GL_GetAttribute( SDL_GL_BLUE_SIZE, &bs );
printf( "Red size: %d, Green size: %d, Blue size: %d\n", rs, gs, bs );
//To be implemented
//glewExperimental = GL_TRUE;
//initialization of glew
GLenum status = glewInit();
if(GLEW_OK != status ){
printf( "GLEW Error: ", glewGetErrorString( status ) );
}
printf( "Status: Using GLEW: %s\n", glewGetString( GLEW_VERSION ) );
}
//Destructer
Display::~Display()
{
//Deletes GL context
SDL_GL_DeleteContext( m_glContext );
//Close and destroy the window
SDL_DestroyWindow( m_window );
//Clean up
SDL_Quit();
}
void Display::Clear()
{
//Clears the screen
glClear( GL_COLOR_BUFFER_BIT );
//Creating a triangle
glBegin( GL_POLYGON );
glColor3f( 1, 0, 0 );
glVertex3f( -0.6, -0.75, 0.5 );
glColor3f( 0, 1, 0 );
glVertex3f( 0.6, -0.75, 0 );
glColor3f( 0, 0, 1 );
glVertex3f( -0, -0.75, 0 );
glEnd();
glFlush();
}
//Closes the window on SDL_QUIT event
bool Display::IsClosed()
{
return m_isClosed;
}
void Display::Update()
{
SDL_GL_SwapWindow( m_window );
SDL_Event e;
while( SDL_PollEvent( &e ) )
{
if( e.type == SDL_QUIT )
m_isClosed = true;
}
}
And finally this is my the simple main.cpp
#include<GL/glew.h>
#include<iostream>
#include"display.h"
int main( int argc, char* argv[] )
{
Display display( 640, 480, "flagShip" );
while( !display.IsClosed() )
{
display.Clear();
display.Update();
}
return 0;
}
Handy Makefile
CC=g++
OBJS= main.cpp
LINKER_FLAGS= -lSDL2 -lGL -lGLEW
COMPILER_FLAGS= -w -pedantic
OBJ_NAME=flagShip
$(OBJ_NAME):main.o display.o
$(CC) $(COMPILER_FLAGS) -o $(OBJ_NAME) main.o display.o $(LINKER_FLAGS)
main.o:$(OBJS) display.h
$(CC) $(COMPILER_FLAGS) -c $(OBJS)
display.o: display.cpp display.h
$(CC) $(COMPILER_FLAGS) -c display.cpp
You do not use any view matrix or projection matrix. This means you have to set up the vertex coordinates of the triangle in clip space, respectively in normalized device space.
The normalized device space is a cube where the left, lower, near coordinate is (-1, -1, -1) and the right, upper, far coordinate is (1, 1, 1):
The projection of the x-axis to the viewport, points from the left to the right and the projection of the y-axis points from the bottom to the top.
Since all the y-coordinates of your triangle are equal, the triangle is perpendicular to the viewport:
glVertex3f( -0.6, -0.75, 0.5 );
...
glVertex3f( 0.6, -0.75, 0 );
...
glVertex3f( -0, -0.75, 0 );
Swap the y- and z-component of the vertex coordinates of the triangle, to solve the issue:
glVertex3f( -0.6, 0.5, -0.75 );
...
glVertex3f( 0.6, 0.0, -0.75 );
...
glVertex3f( -0.0, 0.0, -0.75 );
Preview:
Take a piece of graph paper, then draw out the vertex coordinates of your "triangle". Do you notice something?
Hint 1: the area of the triangle you draw is zero.
Hint 2: Look at the y-value of the last glVertex call.
Related
I want to use OpenGL to implement an animation that can be started and paused with mouse clicks. Since I am currently using the GLFW, the functions in GLUT are no longer applicable.
In GLUT, the implementation can be like this:
void windowMouse(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
// start
glutIdleFunc(idleFunction);
}
else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
// pause
glutIdleFunc(NULL);
}
}
However, glutIdleFunc() does not work in GLFW. I just wrote a coding frame to perform my goal but got stuck in finding the proper function to replace glutIdleFunc().
void mouse_button_callback(GLFWwindow* window, int button, int action, int mode)
{
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
{
// start
}
else if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
{
// pause
}
}
Is there any function in GLFW that can replace the previous one? Or is there any way to perform continuous animation with GLFW?
Get creative with glfwPostEmptyEvent() and glfwWaitEventsTimeout():
// g++ main.cpp `pkg-config --cflags --libs glfw3 gl`
#include <GLFW/glfw3.h>
void (*idleFunc)(GLFWwindow*) = nullptr;
void idle( GLFWwindow* aWindow )
{
static float angle = 0.0f;
static double prvTime = glfwGetTime();
const double curTime = glfwGetTime();
const double dt = (curTime - prvTime);
prvTime = curTime;
angle += 60.0 * dt;
int w, h;
glfwGetFramebufferSize( aWindow, &w, &h );
glViewport( 0, 0, w, h );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glPushMatrix();
glRotatef( angle, 0, 0, 1 );
glBegin(GL_TRIANGLES);
glColor3ub( 0, 255, 0 );
glVertex2f( -0.5, -0.5 );
glVertex2f( 0.5, -0.5 );
glVertex2f( 0.0, 0.5 );
glEnd();
glPopMatrix();
glfwSwapBuffers( aWindow );
}
void display( GLFWwindow* aWindow )
{
int w, h;
glfwGetFramebufferSize( aWindow, &w, &h );
glViewport( 0, 0, w, h );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glBegin(GL_TRIANGLES);
glColor3ub( 255, 0, 0 );
glVertex2f( -0.5, -0.5 );
glVertex2f( 0.5, -0.5 );
glVertex2f( 0.0, 0.5 );
glEnd();
glfwSwapBuffers( aWindow );
}
void button( GLFWwindow* window, int button, int action, int mode )
{
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
{
idleFunc = idle;
glfwPostEmptyEvent();
}
else if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
{
idleFunc = nullptr;
glfwPostEmptyEvent();
}
}
int main( int, char** )
{
glfwInit();
GLFWwindow* window = glfwCreateWindow( 640, 480, "GLFW", NULL, NULL );
glfwMakeContextCurrent( window );
glfwSetMouseButtonCallback( window, button );
while( !glfwWindowShouldClose( window ) )
{
if(idleFunc)
{
idleFunc(window);
glfwWaitEventsTimeout(0.016);
}
else
{
display(window);
glfwWaitEvents();
}
}
glfwTerminate();
}
The glfwPostEmptyEvent() along with the structure of the glfwWindowShouldClose() loop in main() lets you simulate the behavior of glutPostRedisplay() and the glfwWaitEventsTimeout() lets the idleFunc() (if any) run every 16 milliseconds or so.
I'm using OpenGl in c++ to draw '+' symbols. My screen has a resolution of 1920x1080, but unfortunately with my method of drawing ("glBegin(GL_LINES)" ) only works on a 1080x1080 rectangle. For x > screen_height everything gets cut off. However, I can still locate text (using Glut) on the full 1920x1080 surface. Could you help me to find what setting is at fault?
I attached a code snippet. This may not compile, as I only included what is used for the drawing of the '+' symbol.
Much appreciated. Thank you in advance.
// Libraries needed for OpenGL and strings
#include <GL/glut.h>
#include <GLFW/glfw3.h>
// header file required for this cpp file
#include "window2.hxx"
int main(int argc, char *argv[])
{
// Start GLFW as main OpenGL frontend
GLFWwindow* window;
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
exit( EXIT_FAILURE );
}
// Later upstream GLut is used for text rendering: thus also initialize GLUT (freeglut3)
glutInit(&argc, argv);
// check the resolution of the monitor and pass it to the create window function
const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
screen_width = mode->width;
screen_height = mode->height;
window = glfwCreateWindow(screen_width , screen_height, "LearnOpenGL", glfwGetPrimaryMonitor(), NULL );
if (!window)
{
fprintf( stderr, "Failed to open GLFW window\n" );
glfwTerminate();
exit( EXIT_FAILURE );
}
glfwMakeContextCurrent(window);
glfwSwapInterval( 1 );
// set up view
glViewport( 0, 0, screen_height, screen_width );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
// see https://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml
glOrtho(0.0,screen_height,0.0,screen_width,0.0,1.0); // this creates a canvas for 2D drawing on
x_1 = 500;
y_1 = 100;
while( !glfwWindowShouldClose(window) ) {
// Draw gears
render_loop();
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
} // glfw while loop
}
//OpenGL Draw function
void render_loop()
{
// white background
glClearColor ( 1.0f, 1.0f, 1.0f, 1.0f );
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPointSize(10);
glLineWidth(1);
// push matrix
glPushMatrix();
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_LINES);
glVertex2i(x_1-10,y_1);
glVertex2i(x_1+10,y_1);
glVertex2i(x_1,y_1-10);
glVertex2i(x_1,y_1+10);
glEnd();
// pop matrix
glPopMatrix();
}
I think you've got your dimensions the wrong way round:
// set up view
glViewport( 0, 0, screen_height, screen_width );
...
glOrtho(0.0,screen_height,0.0,screen_width,0.0,1.0);
Try
glViewport( 0, 0, screen_width, screen_height);
...
glOrtho(0.0,screen_width,0.0,screen_height,0.0,1.0);
I have problem. I wrote the code on clear opengl and c++ without any libraries(glut, glew...) but it doesnt work.
Function displayCB display polygon with
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_POLYGON);
glVertex2f(-0.5f, -0.5f);
glVertex2f( 0.5f, -0.5f);
glVertex2f( 0.5f, 0.5f);
glVertex2f(-0.5f, 0.5f);
glEnd();
and dont display two polygone with
glColor3f(1.0f, 0.0f, 0.0f);
glLoadIdentity(); // Reset The Current Modelview Matrix
glTranslatef(-1.5f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0
glBegin(GL_TRIANGLES); // Drawing Using Triangles
glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glEnd(); // Finished Drawing The Triangle
glTranslatef(3.0f,0.0f,0.0f); // Move Right 3 Units
glBegin(GL_QUADS); // Draw A Quad
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glEnd();
Can you help me?
COMPILE WITH: g++ -g -o opengl1 opengl1.cxx -lGLU -lGL -lX11
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/time.h>
#define GL_GLEXT_PROTOTYPES
#define GLX_GLXEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glx.h>
struct MyWin
{
Display *display;
Window win;
bool displayed;
int width;
int height;
};
const int WIN_XPOS = 256;
const int WIN_YPOS = 64;
const int WIN_XRES = 600;
const int WIN_YRES = 600;
const int NUM_SAMPLES = 4;
MyWin Win;
double elapsedMsec( const struct timeval &start, const struct timeval &stop )
{
return ( ( stop.tv_sec - start.tv_sec ) * 1000.0 +
( stop.tv_usec - start.tv_usec ) / 1000.0 );
}
double elapsedUsec( const struct timeval &start, const struct timeval &stop )
{
return ( ( stop.tv_sec - start.tv_sec ) * 1000000.0 +
( stop.tv_usec - start.tv_usec ) );
}
/// check() - Check for GL errors, and report any queued
void check( const char hdr[] = "" )
{
int err;
while ( ( err = glGetError() ) != GL_NO_ERROR )
fprintf( stderr, "OpenGL Error at %s: %s\n", hdr, gluErrorString(err) );
}
void displayCB()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
//---------------------------------------------------
// FIXME: Insert GL draw code here
//---------------------------------------------------
glColor3f(1.0f, 0.0f, 0.0f);
glLoadIdentity(); // Reset The Current Modelview Matrix
glTranslatef(-1.5f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0
glBegin(GL_TRIANGLES); // Drawing Using Triangles
glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glEnd(); // Finished Drawing The Triangle
glTranslatef(3.0f,0.0f,0.0f); // Move Right 3 Units
glBegin(GL_QUADS); // Draw A Quad
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glEnd();
// glBegin(GL_POLYGON);
// glVertex2f(-0.5f, -0.5f);
// glVertex2f( 0.5f, -0.5f);
// glVertex2f( 0.5f, 0.5f);
// glVertex2f(-0.5f, 0.5f);
// glEnd();
// Display it
glXSwapBuffers( Win.display, Win.win );
check( "displayCB()" );
}
//----------------------------------------------------------------------------
void keyboardCB( KeySym sym, unsigned char key, int x, int y,
bool &setting_change )
{
switch ( tolower( key ) )
{
case 27:
// ESCape - We're done!
exit (0);
break;
case 'k':
printf( "You hit the 'k' key\n" );
break;
case 0:
switch ( sym )
{
case XK_Left :
printf( "You hit the Left Arrow key\n" );
break;
case XK_Right :
printf( "You hit the Right Arrow key\n" );
break;
}
break;
}
}
//----------------------------------------------------------------------------
void reshapeCB( int width, int height )
{
Win.width = width;
Win.height = height;
}
//----------------------------------------------------------------------------
XVisualInfo *chooseVisual( Display *display )
{
int attribs [ 100 ] ;
int n = 0 ;
// Request 24-bit color with alpha
attribs [n++] = GLX_RGBA ;
attribs [n++] = GLX_RED_SIZE ; attribs [n++] = 8 ;
attribs [n++] = GLX_GREEN_SIZE ; attribs [n++] = 8 ;
attribs [n++] = GLX_BLUE_SIZE ; attribs [n++] = 8 ;
// Request 24-bit depth buffer
attribs [n++] = GLX_DEPTH_SIZE ; attribs [n++] = 24 ;
// Request 4 multisamples per pixel
attribs [n++] = GLX_SAMPLE_BUFFERS ; attribs [n++] = 1 ;
attribs [n++] = GLX_SAMPLES ; attribs [n++] = NUM_SAMPLES ;
// Request double-buffering
attribs [n++] = GLX_DOUBLEBUFFER ;
attribs [n++] = None ;
return glXChooseVisual( display, DefaultScreen( display ), attribs );
}
//----------------------------------------------------------------------------
void createWindow()
{
// Init X and GLX
Win.displayed = false;
Display *display = Win.display = XOpenDisplay( ":0.0" );
if ( !display )
printf( "Cannot open X display\n" );
int screen = DefaultScreen( display );
Window root_win = RootWindow( display, screen );
if ( !glXQueryExtension( display, 0, 0 ) )
printf( "X Server doesn't support GLX extension\n" );
// Pick a visual
XVisualInfo *visinfo = chooseVisual( display );
if ( visinfo == 0 )
printf( "glXChooseVisual failed\n" );
// Describe the visual
printf( "Window Visual 0x%.2x\n", unsigned( visinfo->visualid ) );
// Create the X window
XSetWindowAttributes winAttr ;
winAttr.event_mask = StructureNotifyMask | KeyPressMask ;
winAttr.background_pixmap = None ;
winAttr.background_pixel = 0 ;
winAttr.border_pixel = 0 ;
winAttr.colormap = XCreateColormap( display, root_win,
visinfo->visual, AllocNone );
unsigned int mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
Window win = Win.win = XCreateWindow ( display, root_win,
WIN_XPOS, WIN_YPOS,
WIN_XRES, WIN_YRES, 0,
visinfo->depth, InputOutput,
visinfo->visual, mask, &winAttr ) ;
XStoreName( Win.display, win, "My GLX Window");
// Create an OpenGL context and attach it to our X window
GLXContext context = glXCreateContext( display, visinfo, NULL, 1 ) ;
if ( ! glXMakeCurrent( display, win, context ) )
printf( "glXMakeCurrent failed.\n" );
if ( ! glXIsDirect ( display, glXGetCurrentContext() ) )
printf( "Indirect GLX rendering context obtained\n" );
// Display the window
XMapWindow( display, win );
if ( ! glXMakeCurrent( display, win, context ) )
printf( "glXMakeCurrent failed.\n" );
check( "createWindow()" );
printf( "Window Size = %d x %d\n", WIN_XRES, WIN_YRES );
printf( "Window Samples = %d\n", NUM_SAMPLES );
}
//----------------------------------------------------------------------------
void processXEvents( Atom wm_protocols, Atom wm_delete_window )
{
bool setting_change = false;
while ( XEventsQueued( Win.display, QueuedAfterFlush ) )
{
XEvent event;
XNextEvent( Win.display, &event );
if( event.xany.window != Win.win )
continue;
switch ( event.type )
{
case MapNotify:
{
Win.displayed = true;
break;
}
case ConfigureNotify:
{
XConfigureEvent &cevent = event.xconfigure;
reshapeCB( cevent.width, cevent.height );
break;
}
case KeyPress:
{
char chr;
KeySym symbol;
XComposeStatus status;
XLookupString( &event.xkey, &chr, 1, &symbol, &status );
keyboardCB( symbol, chr, event.xkey.x, event.xkey.y,
setting_change );
break;
}
case ClientMessage:
{
if ( event.xclient.message_type == wm_protocols &&
Atom( event.xclient.data.l[0] ) == wm_delete_window )
{
//printf( "Received WM_DELETE_WINDOW\n" );
exit(0);
}
break;
}
}
}
}
//----------------------------------------------------------------------------
void mainLoop()
{
// Register to receive window close events (the "X" window manager button)
Atom wm_protocols = XInternAtom( Win.display, "WM_PROTOCOLS" , False);
Atom wm_delete_window = XInternAtom( Win.display, "WM_DELETE_WINDOW", False);
XSetWMProtocols( Win.display, Win.win, &wm_delete_window, True );
while (1)
{
// Redraw window (after it's mapped)
if ( Win.displayed )
displayCB();
// Update frame rate
static timeval last_xcheck = {0,0};
struct timeval now;
gettimeofday( &now, 0 );
// Check X events every 1/10 second
if ( elapsedMsec( last_xcheck, now ) > 100 )
{
processXEvents( wm_protocols, wm_delete_window );
last_xcheck = now;
}
}
}
//----------------------------------------------------------------------------
int main( int argc, char *argv[] )
{
// Init globals
Win.width = WIN_XRES, Win.height = WIN_YRES;
// Create context and window
createWindow();
// Init OpenGL
glViewport ( 0, 0, Win.width, Win.height );
glColorMask ( 1,1,1,1 );
glClearColor( 0,0,1,1 );
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// Go
printf( "Valid keys: Left, Right, k, ESC\n" );
printf( "Press ESC to quit\n" );
mainLoop();
return 0;
}
There are three problems here.
First: you haven't set up a GL viewport (e.g, using glFrustum() or gluPerspective()), so the perspective matrix isn't set up appropriately to do 3D graphics. As such, trying to draw a model in 3D won't work properly.
Second: The code that you've got here is written against the X11 windowing system, not Mac OS X. While it'll compile and sort-of-run on Mac OS, it will not run natively, nor will it perform particularly well. You will really want to use some interface which allows you to interface with the native Mac OS X GL implementation, such as SDL, GLUT/GLEW, or AGL.
(Keep in mind that there is no such thing as using GL "without libraries". OpenGL is itself a library, as is libX11; there's nothing at all wrong with using extra utility libraries to cut out some of the OS-specific setup and make your application easier to port.)
Third: You are currently learning how to use OpenGL immediate mode, which was used prior to OpenGL 3.0. Modern OpenGL — that is, OpenGL 3.0 or later, as well as OpenGL ES — uses a significantly different API which has very little in common with immediate mode. I'd strongly recommend that you skip immediate mode entirely; it's a dead technology at this point. There are a number of good tutorials out there for OpenGL 3+, including:
http://www.opengl-tutorial.org/
http://www.arcsynthesis.org/gltut/
https://open.gl/
I have a simple program using FreeGLUT, OpenGL, and some nice simplex noise functions from Eliot Eshelman. The goal is to display 2D slices some 3D simplex noise, which I've managed with SDL.
My problem is: I'm getting multiple definition errors that I can't seem to resolve.
I've searched around on Google and these forums for a while. I learned about quite a few things that could cause errors, BUT I can't seem to find the cause of mine. I've been stumped by these errors for many hours.
Here's my relevant sources and error outputs.
Note that there could be more bugs past the errors I'm getting, but I haven't been able to debug far enough to get to them yet.
Output:
-------------- Build: Release in OpenGL Test (compiler: GNU GCC Compiler)---------------
mingw32-g++.exe -Wall -O2 -std=c++11 -IC:\freeglut\include -c "C:\OpenGL Test\OpenGL Test\main.cpp" -o obj\Release\main.o
mingw32-g++.exe -LC:\freeglut\lib -o "bin\Release\OpenGL Test.exe" obj\Release\LUtil.o obj\Release\main.o obj\Release\simplexnoise.o -s -lmingw32 -lOpenGL32 -lglu32 -lfreeglut -mwindows
obj\Release\main.o:main.cpp:(.bss+0x0): multiple definition of `textureName'
obj\Release\LUtil.o:LUtil.cpp:(.bss+0x0): first defined here
obj\Release\main.o:main.cpp:(.bss+0x20): multiple definition of `noiseImage'
obj\Release\LUtil.o:LUtil.cpp:(.bss+0x20): first defined here
obj\Release\main.o:main.cpp:(.bss+0x12c020): multiple definition of `zOffset'
obj\Release\LUtil.o:LUtil.cpp:(.bss+0x12c020): first defined here
collect2.exe: error: ld returned 1 exit status
Process terminated with status 1 (0 minute(s), 0 second(s))
0 error(s), 0 warning(s) (0 minute(s), 0 second(s))
LUtil.h:
/*This source code copyrighted by Lazy Foo' Productions (2004-2013)
and may not be redistributed without written permission.*/
//Version: 001
#ifndef LUTIL_H
#define LUTIL_H
#include "LOpenGL.h"
#include "simplexnoise.h"
//Screen Constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_FPS = 60;
float zOffset = 0;
float noiseImage[640][480];
GLuint textureName;
bool initGL();
/*
Pre Condition:
-A valid OpenGL context
Post Condition:
-Initializes matrices and clear color
-Reports to console if there was an OpenGL error
-Returns false if there was an error in initialization
Side Effects:
-Projection matrix is set to identity matrix
-Modelview matrix is set to identity matrix
-Matrix mode is set to modelview
-Clear color is set to black
*/
void update();
/*
Pre Condition:
-None
Post Condition:
-Does per frame logic
Side Effects:
-None
*/
void render();
/*
Pre Condition:
-A valid OpenGL context
-Active modelview matrix
Post Condition:
-Renders the scene
Side Effects:
-Clears the color buffer
-Swaps the front/back buffer
*/
#endif
LUtil.cpp:
/*This source code copyrighted by Lazy Foo' Productions (2004-2013)
and may not be redistributed without written permission.*/
//Version: 001
#include "LUtil.h"
bool initGL()
{
//Initialize Projection Matrix
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
//Initialize Modelview Matrix
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
//Initialize clear color
glClearColor( 0.f, 0.f, 0.f, 1.f );
//Check for error
GLenum error = glGetError();
if( error != GL_NO_ERROR )
{
printf( "Error initializing OpenGL! %s\n", gluErrorString( error ) );
return false;
}
glGenTextures(1, &textureName);
glBindTexture(GL_TEXTURE_2D, textureName);
return true;
}
void update()
{
for(int y = 0; y < SCREEN_HEIGHT; y++)
{
for(int x = 0; x < SCREEN_WIDTH; x++)
{
noiseImage[x][y] = raw_noise_3d(x, y, zOffset);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCREEN_WIDTH, SCREEN_HEIGHT, 0, GL_RGB, GL_FLOAT, &noiseImage[0][0]);
}
}
}
void render()
{
//Clear color buffer
glClear( GL_COLOR_BUFFER_BIT );
glColor4f(1, 0.5f, 0, 1);
//Render quad
glBegin( GL_QUADS );
glTexCoord2f( -1.f, -1.f );
glTexCoord2f( -1.f, 1.f );
glTexCoord2f( 1.f, -0.f );
glTexCoord2f( 1.f, 1.f );
glEnd();
//Update screen
glutSwapBuffers();
}
main.cpp:
/*This source code copyrighted by Lazy Foo' Productions (2004-2013)
and may not be redistributed without written permission.*/
//Version: 001
#include "LUtil.h"
void runMainLoop( int val );
/*
Pre Condition:
-Initialized freeGLUT
Post Condition:
-Calls the main loop functions and sets itself to be called back in 1000 / SCREEN_FPS milliseconds
Side Effects:
-Sets glutTimerFunc
*/
int main( int argc, char* args[] )
{
//Initialize FreeGLUT
glutInit( &argc, args );
//Create OpenGL 2.1 context
glutInitContextVersion( 4, 4 );
//Create Double Buffered Window
glutInitDisplayMode( GLUT_DOUBLE );
glutInitWindowSize( SCREEN_WIDTH, SCREEN_HEIGHT );
glutCreateWindow( "OpenGL" );
//Do post window/context creation initialization
if( !initGL() )
{
printf( "Unable to initialize graphics library!\n" );
return 1;
}
//Set rendering function
glutDisplayFunc( render );
//Set main loop
glutTimerFunc( 1000 / SCREEN_FPS, runMainLoop, 0 );
//Start GLUT main loop
glutMainLoop();
return 0;
}
void runMainLoop( int val )
{
//Frame logic
update();
render();
//Run frame one more time
glutTimerFunc( 1000 / SCREEN_FPS, runMainLoop, val );
}
As far as I can tell, there are no multiple definitions, but I could be wrong.
Once again, I'm sorry if I'm "That guy" with this question.
Move the definitions of your global variabls to LUtil.cpp:
float zOffset = 0;
float noiseImage[640][480];
GLuint textureName;
Then declare the variabls in LUtil.h:
extern float zOffset;
extern float noiseImage[640][480];
extern GLuint textureName;
Using SCREEN_WIDTH = 1200, and SCREEN_HEIGHT = 800.
First, I draw a box to the screen at (x = 0, y = 0, w = 40, h = 40);
Then I use the handleMouse Function to return the x and y coordinates of where the mouse is clicked.
The problem is, when the program starts in non-Maximized windowed mode, when I click on (What appears to be) the very bottom right corner of the box the coordinates returned are x = 40, y = 32. When I think it should be returning x = 40, y = 40.
I don't know whether the problem is if its not being drawn right, or the functions is returning the wrong x/y.
I believe I understand how openGL rendering, transformation and glOrth work, but I could be completely wrong. I have seen a few suggestions online saying that the Windows Decor(Using windows 7) can cause this problem, but have done very little explaining and provided no solution.
This is my entire source code. I have stripped off everything from my game down to the basics, and the problem still persists :( . I added two pictures so people could see my problem. In NON-MAXIMIZED WINDOW(the top picture), when clicking the bottom-right corner, the coordinates returned are 41,32; The y coordinate is smaller than it should be. And in the MAXIMIZED WINDOW(the bottom picture), when clicking the same corner, It returns the correct coordinates 40, 40. These results occur for both my original source code and genpfault's suggested code.
//Turns out I can't post Pictures :(, links instead.
non-Maximized Windowed!
Maximized Windowed!
main.cpp
int main( int argc, char* args[] )
{
//Initialize FreeGLUT
glutInit( &argc, args );
//Create OpenGL 2.1 context
glutInitContextVersion( 2, 1 );
//Create Double Buffered Window
glutInitDisplayMode( GLUT_DOUBLE );
glutInitWindowSize( SCREEN_WIDTH, SCREEN_HEIGHT );
glutCreateWindow( "OpenGL" );
//Do post window/context creation initialization
if( !initGL() )
{
printf( "Unable to initialize graphics library!\n" );
return 1;
}
//initGame();
glutMouseFunc(handleMouse);
glutDisplayFunc( render );
glutMainLoop();
return 0;
}
Functions.h
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
bool initGL();
void render();
void handleMouse(int button, int state, int x, int y);
#endif
Functions.cpp
bool initGL()
{
//Initialize clear color
glClearColor( 0.f, 0.f, 0.f, 1.f );
//Check for error
GLenum error = glGetError();
if( error != GL_NO_ERROR )
{
//cout <<"Error initializing OpenGL! " << gluErrorString( error ) << endl;
return false;
}
return true;
}
void render()
{
//Clear color buffer
glClear( GL_COLOR_BUFFER_BIT );
glColor3f(1.f,1.f,1.f);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluOrtho2D(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin(GL_QUADS);
glVertex2f(0,0);
glVertex2f(0, 41);
glVertex2f(41, 41);
glVertex2f(41, 0);
glEnd();
glutSwapBuffers();
}
void handleMouse(int button, int state, int x, int y)
{
std::cout << x << '\t' << y << std::endl;
}
constants.h
const int SCREEN_WIDTH = 1200;
const int SCREEN_HEIGHT = 800;
This works fine for me on Windows 7 on Aero and Classic:
#include <GL/glut.h>
#include <iostream>
void render()
{
glClearColor( 0, 0, 0, 1 );
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
glOrtho(0, w, h, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3ub( 255, 255, 255 );
glBegin(GL_QUADS);
glVertex2f(0,0);
glVertex2f(41, 0);
glVertex2f(41, 41);
glVertex2f(0, 41);
glEnd();
glutSwapBuffers();
}
void handleMouse(int button, int state, int x, int y)
{
std::cout << x << '\t' << y << std::endl;
}
int main( int argc, char* args[] )
{
glutInit( &argc, args );
glutInitDisplayMode( GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "OpenGL" );
glutMouseFunc(handleMouse);
glutDisplayFunc( render );
glutMainLoop();
return 0;
}
Most notably I added the runtime glutGet() window size queries to render().
Try moving the quad away from the edge of the display because when I tryed to do something like that the edge of the screen was very odd
glBegin(GL_QUADS);
glVertex2f(20,20);
glVertex2f(20, 61);
glVertex2f(61, 61);
glVertex2f(61, 20);
glEnd();