When rendering off-screen content with OpenGL I am trying to use a window larger than the current screen resolution. The following code fails to render correctly if so (it renders to a portion of the window), but works OK when the window size is <= the resolution. (Error checks and stuff removed).
void run(int wi2,int he2)
{
glfwInit();
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
win = glfwCreateWindow(wi2, he2, "OpenGL", 0, 0);
glfwMakeContextCurrent(win);
hOpenGL = glfwGetWin32Window(win);
ShowWindow(hOpenGL, SW_HIDE);
if (!loadExtensions())
{
....
}
glEnable(GL_DEPTH_TEST); // Use the Z buffer
glfwSwapInterval(0); // Do not wait for screen refresh between frames
glfwSetWindowSize(win, wi2,he2);
glViewport(0, 0, wi2,he2);
SetEvent(hRun2);
MSG msg;
for (;;)
{
HANDLE he[2] = { hRun1,hRunE };
auto gc = MsgWaitForMultipleObjects(2, he, 0, INFINITE, QS_ALLEVENTS);
if (gc == WAIT_OBJECT_0 + 1)
{
// end
glfwDestroyWindow(win);
win = 0;
break;
}
else
if (gc == WAIT_OBJECT_0)
{
// render
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(runc.bg.r, runc.bg.g, runc.bg.b, runc.bg.a);
// Load uniforms, others are omitted for simplicity
float wh[4] = { wi2,he2,0,0 };
auto uloc =
glGetUniformLocation(runc.prg, "iResolution");
glUniform3fv(uloc, 1, wh);
glLoadIdentity();
glBegin(GL_POLYGON);
glColor3f(1.0, 1.0, 1.0);
glVertex2i(-wi2 / 2, -he2 / 2);
glVertex2i(wi2 / 2, -he2 / 2);
glVertex2i(wi2 / 2, he2 / 2);
glVertex2i(-wi2 / 2, he2 / 2);
glEnd();
auto r = runc.glOut->GetRawData();
memset(r, 0, wi2 * he2 * 4);
glReadPixels(0, 0, wi2, he2, GL_BGRA, GL_UNSIGNED_BYTE, r);
glfwSwapBuffers(win);
SetEvent(hRun2);
}
else { ... }
}
glfwTerminate();
win = 0;
hOpenGL = 0;
SetEvent(hRun2);
}
Is there a way to have a window rendering larger than the current screen size? Even in software rendering.
The screenshot below shows the desired result.
below is the actual result
I used the glutWireSphere API for drawing my sphere, however, it is not showing.
#include <GL/glut.h>
const int RED_COLOR[3] = {255, 0, 0};
const int GREEN_COLOR[3] = { 0, 0, 255};
// color to draw in
void setDrawColor(const int rgb[3]) {
float d = 255.0; // d = max value in an rgb color spectrum
glColor3f(rgb[0]/d, rgb[1]/d, rgb[2]/d); // set draw color R=x/255 G=y/255 B=z/255 where x,y,z are values in rgb channel respectively
}
void drawPlane() {
GLfloat A[3] = { -1, 0, 1 };
GLfloat B[3] = { 1, 0, 1 };
GLfloat C[3] = { 1, 0, -1 };
GLfloat D[3] = { -1, 0, -1 };
glBegin(GL_POLYGON);
glVertex3fv(A);
glVertex3fv(B);
glVertex3fv(C);
glVertex3fv(D);
glEnd();
}
GLfloat CamX = 0, CamY = 2, CamZ = 2;
// Display Call Back
void draw() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear all drawings in buffer
glLoadIdentity();
gluLookAt(CamX, CamY, CamZ, 0, 0, 0, 0, 1, 0);
drawPlane();
setDrawColor(GREEN_COLOR); // sets the drawing color to GREEN
glutWireSphere(0.2, 20, 20);
glutSwapBuffers();// Render Now i.e convert Buffer to Picture
return;
}
// Initialization
void initialize()
{
glClearColor(0.1f, 0.1f, 0.1f, 0.1f); // Set Background Color
setDrawColor(RED_COLOR); // sets the drawing color to red
glEnable(GL_DEPTH_TEST); // enable viewing the 3d
glMatrixMode(GL_PROJECTION); // change to perspective projection
glLoadIdentity(); // what does this do?
glFrustum(-1, 1, -1, 1, 2, 10); // what does this do?
glMatrixMode(GL_MODELVIEW); // what does this do?
}
// Main
int main(int argc, char* argv[])
{
glutInit(&argc, argv); // Initialize GLUT
int x = 512, y = 512; // x and y value
glutInitWindowPosition(
(int)(glutGet(GLUT_SCREEN_WIDTH) - x) / 2,
(int)(glutGet(GLUT_SCREEN_HEIGHT) - y) / 2); // Position the window's center
glutInitWindowSize(x, y); // Set the window's initial width & height
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); // initialise the buffers needed. double buff, one for RGB color the other for x,y, z
glutCreateWindow("3D Bowling Game"); // Create a window with the given title
initialize(); // Custom initialisation
glutDisplayFunc(draw); // Register display callback handler for window re-paint
glutMainLoop(); // Enter the event-processing loop
return 0;
}
what am i doing wrong?
#include <stdio.h> // this library is for standard input and output
#include "glut.h"// this library is for glut the OpenGL Utility Toolkit
#include <math.h>
float squareX = 0.0f;
float squareY = -0.3f;
float squareZ = 0.0f;
static int flag = 1;
void drawShape(void) {
glTranslatef(squareX, squareY, squareZ);
glBegin(GL_POLYGON);
glColor3f(1.0, 0.0, 0.0);
glVertex2f(162, 50);
glVertex2f(162, 10);
glVertex2f(220, 10);
glVertex2f(220, 50);
glVertex2f(162, 50);
glEnd();
}
void initRendering() {
glEnable(GL_DEPTH_TEST);
}
// called when the window is resized
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, (float)w, 0.0f, (float)h, -1.0f, 1.0f);
}
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
drawShape();
glutSwapBuffers();
}
// make the square go up
void update(int value) {
if (flag) {
squareY += 1.0f;
if (squareY > 400.0) {
flag = 0;
}
}
glutPostRedisplay();
glutTimerFunc(25, update, 0);
}
// make the square go right
/* void update(int value) {
if (flag) {
squareX += 1.0f;
if (squareX > 400.0) {
flag = 0;
}
}
glutPostRedisplay();
glutTimerFunc(25, update, 0);
} */
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 400);
glutCreateWindow("Moving Square");
initRendering();
glutDisplayFunc(drawScene);
glutReshapeFunc(handleResize);
glutTimerFunc(25, update, 0);
glutMainLoop();
return(0);
}
I have uploaded this code before but this time I made the square go all the way up. The code just moves the square up, but I don't know how to position it on the left once it reaches the top, so then I can make it move to the right. I have uploaded a demonstration on how I want it to look below.
Preview:
What I want it to do next:
I recommend to initialize the variables squareX, squareY and squareZ with the start position of the rectangle:
float squareX = 162.0f;
float squareY = 0.0f;
float squareZ = 0.0f;
Do not draw a rectangle specific position, but draw a rectangle on the position (0,0) with a length (width, height). Let the model matrix (set by glTranslatef), do the job of the positioning:
void drawShape(void)
{
float width = 58.0f;
float height = 40.0f;
glTranslatef(squareX, squareY, squareZ);
glBegin(GL_POLYGON);
glColor3f(1.0, 0.0, 0.0);
glVertex2f(0, 0);
glVertex2f(width, 0);
glVertex2f(width, height);
glVertex2f(0, height);
glVertex2f(0, 0);
glEnd();
}
Use a variable state, which has stated the direction of the current movement:
int state = 1; // 0: stop; 1: move up; 2: move right
If the rectangle a certain position has reached, then the state has to be changed and a the new start position can be set. At the final position, the rectangle can stop or the process can even be restarted:
void update(int value)
{
if (state == 1) // 1 : move up
{
squareY += 1.0f;
if (squareY > 400.0)
{
state = 2;
squareX = 0.0f;
squareY = 180.0f;
}
}
else if (state == 2) // 2 : move right
{
squareX += 1.0f;
if (squareX > 400.0)
{
state = 0;
// restart
//state = 1;
//squareX = 162.0f;
//squareY = 0.0f;
}
}
glutPostRedisplay();
glutTimerFunc(25, update, 0);
}
I'm really pulling my hair out with this problem. I'm trying to create a simple game where the player rolls a ball around a playing area.
I'm using WinAPI for window management and input handling.
I tried to render some simple quads too, instead of the GLU sphere, but that didn't work either.
I've separated the code across different classes. I present the relevant code below. This code is in my WinMain:
while (running) {
PeekMessage(&msg, hwnd, NULL, NULL, PM_REMOVE);
if (msg.message == WM_QUIT)
running = false;
else {
// handle key presses
// update
gameWorld->update(getDirections());
// render
gameWorld->render(deviceContext);
// I added this block of code for testing, still does not work
glColor4f(1, 1, 1, 1);
glBegin(GL_QUADS);
glVertex3f(10, 10, 0);
glVertex3f(10, -10, 0);
glVertex3f(-10, -10, 0);
glVertex3f(-10, 10, 0);
glEnd();
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Here's GameWorld.cpp:
GameWorld::GameWorld()
{
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
this->ball = new Ball(1, 10, 10);
this->camera = new Camera(ball);
}
GameWorld::~GameWorld()
{
delete this->ball;
}
void GameWorld::render(HDC deviceContext) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
this->ball->draw();
SwapBuffers(deviceContext);
}
void GameWorld::update(Directions dirs) {
glLoadIdentity();
this->ball->handleInput(dirs);
this->ball->update();
this->camera->update();
}
Here's Camera update method:
void Camera::update() {
GLdouble ballX = ball->getLocation()->getX();
GLdouble ballY = ball->getLocation()->getY();
GLdouble ballZ = ball->getLocation()->getZ();
GLdouble x = ballX + cos(90) * this->distanceFromBall;
GLdouble y = ballY + cos(90) * this->distanceFromBall;
GLdouble z = ballZ + cos(90) * this->distanceFromBall;
gluLookAt(
x, y, z,
ballX, ballY, ballZ,
0, 1, 0
);
}
Here's the Ball draw method:
void Ball::draw() {
glPushMatrix();
this->quadric = gluNewQuadric();
glTranslated(this->location->getX(), this->location->getY(), this->location->getZ());
gluQuadricDrawStyle(this->quadric, GLU_FILL);
glColor4f(1, 1, 1, 1);
gluSphere(this->quadric, this->radius, this->slices, this->stacks);
gluDeleteQuadric(this->quadric);
glPopMatrix();
}
What the #!#% is wrong with this code? I should get this thing done in a week, so I really could use some help...
I had to use the gluPerspective() function to make this work. My GameWorld constructor now looks like this:
GameWorld::GameWorld()
{
glViewport(0, 0, WIDTH, HEIGHT); // reset the viewport to new dimensions
glMatrixMode(GL_PROJECTION); // set projection matrix current matrix
glLoadIdentity(); // reset projection matrix
// calculate aspect ratio of window
gluPerspective(54.0f, (GLfloat)WIDTH / (GLfloat)HEIGHT, 1.0f, 1000.0f);
glMatrixMode(GL_MODELVIEW); // set modelview matrix
glLoadIdentity();
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
this->ball = new Ball(1, 20, 20);
this->camera = new Camera(ball);
}
The code is copied from the sample code of Dave Astle's book "OpenGL Game Programming".
I am making changes in the code from this article, to acomplish the same result without need the methods specific for Windows and be able to run the programa in other platforms. I can compile and run the program without errors (with the Main and Render functions listed below), but the result is a blank screen. Someone can find some reason in the code for this issue happen?
Main:
int main(int argc, char **argv)
{
// temp var's
int width = 800;
int height = 600;
int bits = 32;
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(width,height);
glutInit(&argc, argv);
glutCreateWindow("Terrain");
glutDisplayFunc(Render);
glutReshapeFunc(AlteraTamanhoJanela);
glutKeyboardFunc(GerenciaTeclado);
glutMouseFunc(GerenciaMouse);
Initialize();
glutMainLoop();
}
Render:
void Render()
{
radians = float(PI*(angle-90.0f)/180.0f);
// calculate the camera's position
cameraX = lookX + sin(radians)*mouseY; // multiplying by mouseY makes the
cameraZ = lookZ + cos(radians)*mouseY; // camera get closer/farther away with mouseY
cameraY = lookY + mouseY / 2.0f;
// calculate the camera look-at coordinates as the center of the terrain map
lookX = (MAP_X*MAP_SCALE)/2.0f;
lookY = 150.0f;
lookZ = -(MAP_Z*MAP_SCALE)/2.0f;
// clear screen and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// set the camera position
gluLookAt(cameraX, cameraY, cameraZ, lookX, lookY, lookZ, 0.0, 1.0, 0.0);
// set the current texture to the land texture
glBindTexture(GL_TEXTURE_2D, land);
// we are going to loop through all of our terrain's data points,
// but we only want to draw one triangle strip for each set along the x-axis.
for (int z = 0; z < MAP_Z-1; z++)
{
//printf("%s %d\n","Loop FOR para Z = ",z);
glBegin(GL_TRIANGLE_STRIP);
for (int x = 0; x < MAP_X-1; x++)
{
//printf("%s %d\n","Loop FOR para X = ",x);
// for each vertex, we calculate the grayscale shade color,
// we set the texture coordinate, and we draw the vertex.
/*
the vertices are drawn in this order:
0 ---> 1
/
/
|/
2 ---> 3
*/
// draw vertex 0
//printf("%s\n","Primeiro");
glColor3f(terrain[x][z][1]/255.0f, terrain[x][z][1]/255.0f, terrain[x][z][1]/255.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(terrain[x][z][0], terrain[x][z][1], terrain[x][z][2]);
// draw vertex 1
//printf("%s\n","Segundo");
glTexCoord2f(1.0f, 0.0f);
glColor3f(terrain[x+1][z][1]/255.0f, terrain[x+1][z][1]/255.0f, terrain[x+1][z][1]/255.0f);
glVertex3f(terrain[x+1][z][0], terrain[x+1][z][1], terrain[x+1][z][2]);
// draw vertex 2
//printf("%s\n","Terceiro");
glTexCoord2f(0.0f, 1.0f);
glColor3f(terrain[x][z+1][1]/255.0f, terrain[x][z+1][1]/255.0f, terrain[x][z+1][1]/255.0f);
glVertex3f(terrain[x][z+1][0], terrain[x][z+1][1], terrain[x][z+1][2]);
// draw vertex 3
//printf("%s\n","Quarto");
glColor3f(terrain[x+1][z+1][1]/255.0f, terrain[x+1][z+1][1]/255.0f, terrain[x+1][z+1][1]/255.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(terrain[x+1][z+1][0], terrain[x+1][z+1][1], terrain[x+1][z+1][2]);
}
glEnd();
}
// enable blending
glEnable(GL_BLEND);
// enable read-only depth buffer
glDepthMask(GL_FALSE);
// set the blend function to what we use for transparency
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
// set back to normal depth buffer mode (writable)
glDepthMask(GL_TRUE);
// disable blending
glDisable(GL_BLEND);
glFlush();
//SwapBuffers(g_HDC); // bring backbuffer to foreground
}
Update: As requested, here is the other functions from my code.
void InitializeTerrain()
{
// loop through all of the heightfield points, calculating
// the coordinates for each point
for (int z = 0; z < MAP_Z; z++)
{
for (int x = 0; x < MAP_X; x++)
{
terrain[x][z][0] = float(x)*MAP_SCALE;
terrain[x][z][1] = (float)imageData[(z*MAP_Z+x)*3];
terrain[x][z][2] = -float(z)*MAP_SCALE;
}
}
}
void CleanUp()
{
free(imageData);
free(landTexture);
}
// Initialize
// desc: initializes OpenGL
void Initialize()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // clear to black
glShadeModel(GL_SMOOTH); // use smooth shading
glEnable(GL_DEPTH_TEST); // hidden surface removal
glEnable(GL_CULL_FACE); // do not calculate inside of poly's
glFrontFace(GL_CCW); // counter clock-wise polygons are out
glEnable(GL_TEXTURE_2D); // enable 2D texturing
imageData = LoadBitmapFile("terrain2.bmp", &bitmapInfoHeader);
// initialize the terrain data and load the textures
InitializeTerrain();
LoadTextures();
}
// Função callback chamada quando o tamanho da janela é alterado
void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
int width, height;
height = h; // retrieve width and height
width = w;
if (height==0) // don't want a divide by zero
{
height=1;
}
glViewport(0, 0, width, height); // reset the viewport to new dimensions
glMatrixMode(GL_PROJECTION); // set projection matrix current matrix
glLoadIdentity(); // reset projection matrix
// calculate aspect ratio of window
gluPerspective(54.0f,(GLfloat)width/(GLfloat)height,1.0f,1000.0f);
glMatrixMode(GL_MODELVIEW); // set modelview matrix
glLoadIdentity(); // reset modelview matrix
}
// Função callback chamada para gerenciar eventos do mouse
void GerenciaMouse(int button, int state, int x, int y)
{
int oldMouseX, oldMouseY;
// save old mouse coordinates
oldMouseX = mouseX;
oldMouseY = mouseY;
// get mouse coordinates from Windows
mouseX = x;
mouseY = y;
// these lines limit the camera's range
if (mouseY < 200)
mouseY = 200;
if (mouseY > 450)
mouseY = 450;
if ((mouseX - oldMouseX) > 0) // mouse moved to the right
angle += 3.0f;
else if ((mouseX - oldMouseX) < 0) // mouse moved to the left
angle -= 3.0f;
glutPostRedisplay();
}
/* Key press processing */
void GerenciaTeclado(unsigned char c, int x, int y)
{
if(c == 27) exit(0);
}
And, finally, the content from file vkgllib.h, included by source code file above:
#include <iostream>
#include <fstream>
#include <math.h>
#include <stdlib.h>
using namespace std;
#define WINDOW_WIDTH 640 // Window Width Default
#define WINDOW_HEIGHT 480 // Window Height Default
// definition of PI
#define PI 3.14159265
// Used to defien the title of the window
#define WINDOW_TITLE "OpenGL Terrain Generation"
// A simple structure to define a point whose coordinates are integers
/*typedef struct { GLint x, y; } GLintPoint;
// This structure is used to store the vertices of a polyline
typedef struct { int num; GLintPoint pt[100]; } GLintPointArray;
// Data for an Icosahedron
#define ICO_X 0.525731112119133606
#define ICO_Z 0.850650808352039932*/
/*static GLfloat vdataICO[12][3] =
{
{ -ICO_X, 0.0, ICO_Z }, { ICO_X, 0.0, ICO_Z }, { -ICO_X, 0.0, -ICO_Z }, { ICO_X, 0.0, -ICO_Z },
{ 0.0, ICO_Z, ICO_X }, { 0.0, ICO_Z, -ICO_X }, { 0.0, -ICO_Z, ICO_X }, { 0.0, -ICO_Z, -ICO_X },
{ ICO_Z, ICO_X, 0.0 }, { -ICO_Z, ICO_X, 0.0 }, { ICO_Z, -ICO_X, 0.0 }, { -ICO_Z, -ICO_X, 0.0 }
};
static GLuint tindicesICO[20][3] =
{
{ 1, 4, 0 }, { 4, 9, 0 }, { 4, 5, 9 }, { 8, 5, 4 }, { 1, 8, 4 },
{ 1, 10, 8 }, { 10, 3, 8 }, { 8, 3, 5 }, { 3, 2, 5 }, { 3, 7, 2 },
{ 3, 10, 7 }, { 10, 6, 7 }, { 6, 11, 7 }, { 6, 0, 11 }, {6, 1, 0 },
{ 10, 1, 6 }, { 11, 0, 9 }, { 2, 11, 9 }, { 5, 2, 9 }, { 11, 2, 7 }
};*/
// Data for Tetrahedron
static GLfloat P1T[3] = { -2, 3, 0 };
static GLfloat P2T[3] = { -3, 0, 0 };
static GLfloat P3T[3] = { -1, 0, 3 };
static GLfloat P4T[3] = { -4, 0, 0 };
// Calculating the Normalized Cross Product of Two Vectors
void normalize( float v[3] )
{
GLfloat d = sqrt( float(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]) );
if( d==0.0 )
{
cerr<<"zero length vector"<<endl;
return;
}
v[0] /= d;
v[1] /= d;
v[2] /= d;
}
void normcrossprod( float v1[3], float v2[3], float out[3] )
{
out[0] = v1[1]*v2[2] - v1[2]*v2[1];
out[1] = v1[2]*v2[0] - v1[0]*v2[2];
out[2] = v1[0]*v2[1] - v1[1]*v2[0];
normalize( out );
}
////// Defines
#define BITMAP_ID 0x4D42 // the universal bitmap ID
#define MAP_X 32 // size of map along x-axis
#define MAP_Z 32 // size of map along z-axis
#define MAP_SCALE 20.0f // the scale of the terrain map
////// Texture Information
BITMAPINFOHEADER bitmapInfoHeader; // temp bitmap info header
BITMAPINFOHEADER landInfo; // land texture info header
BITMAPINFOHEADER waterInfo; // water texture info header
//AUX_RGBImageRec
unsigned char* imageData; // the map image data
unsigned char* landTexture; // land texture data
unsigned int land; // the land texture object
////// Terrain Data
float terrain[MAP_X][MAP_Z][3]; // heightfield terrain data (0-255); 256x256
// LoadBitmapFile
// desc: Returns a pointer to the bitmap image of the bitmap specified
// by filename. Also returns the bitmap header information.
// No support for 8-bit bitmaps.
unsigned char *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader)
{
FILE *filePtr; // the file pointer
BITMAPFILEHEADER bitmapFileHeader; // bitmap file header
unsigned char *bitmapImage; // bitmap image data
int imageIdx = 0; // image index counter
unsigned char tempRGB; // swap variable
// open filename in "read binary" mode
filePtr = fopen(filename, "rb");
if (filePtr == NULL)
return NULL;
// read the bitmap file header
fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);
// verify that this is a bitmap by checking for the universal bitmap id
if (bitmapFileHeader.bfType != BITMAP_ID)
{
fclose(filePtr);
return NULL;
}
// read the bitmap information header
fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);
// move file pointer to beginning of bitmap data
fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);
// allocate enough memory for the bitmap image data
bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage);
// verify memory allocation
if (!bitmapImage)
{
free(bitmapImage);
fclose(filePtr);
return NULL;
}
// read in the bitmap image data
fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr);
// make sure bitmap image data was read
if (bitmapImage == NULL)
{
fclose(filePtr);
return NULL;
}
// swap the R and B values to get RGB since the bitmap color format is in BGR
for (imageIdx = 0; imageIdx < bitmapInfoHeader->biSizeImage; imageIdx+=3)
{
tempRGB = bitmapImage[imageIdx];
bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
bitmapImage[imageIdx + 2] = tempRGB;
}
// close the file and return the bitmap image data
fclose(filePtr);
return bitmapImage;
}
bool LoadTextures()
{
// load the land texture data
landTexture = LoadBitmapFile("green.bmp", &landInfo);
if (!landTexture)
return false;
// generate the land texture as a mipmap
glGenTextures(1, &land);
glBindTexture(GL_TEXTURE_2D, land);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, landInfo.biHeight, landInfo.biWidth, GL_RGB, GL_UNSIGNED_BYTE, landTexture);
return true;
}
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
^^^^^^^^^^^
You've asked for double-buffering.
And yet your Render() function seems to assume you're using single-buffering:
void Render()
{
...
glFlush();
}
Either switch to GLUT_SINGLE or use glutSwapBuffers() instead of glFlush().