Here the coordinate plane and the cube are drawn, it is necessary to ensure the movement of the cube. But in this situation, both the cube and the coordinate plane move. What do I need to add to ensure that only the cube moves. As I understand it, I need to zero the matrix, but how can I implement this?
#include <glut.h>
void Reshape(int w, int h);
void Display();
void ProcessNormalKeys(unsigned char key, int x, int y);
void ProcessSpecialKeys(int key, int x, int y);
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(800, 600);
glutReshapeFunc(Reshape);
glutDisplayFunc(Display);
glutKeyboardFunc(ProcessNormalKeys);
glutSpecialFunc(ProcessSpecialKeys);
glutMainLoop();
return 0;
}
void Reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1000, 1000, -1000, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void Display()
{
glClearColor(1, 1, 1, 0);
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_QUADS);
glColor3f(1.0, 1.0, 1.0);
glVertex2i(350, 550);
glColor3f(0.0, 0.0, 1.0);
glVertex2i(350, 150);
glColor3f(0.0, 1.0, 0.0);
glVertex2i(650, 150);
glColor3f(1.0, 0.0, 0.0);
glVertex2i(650, 550);
glEnd();
glBegin(GL_LINES);
glColor3f(0, 0, 0);
glVertex2i(-10000, 0);
glVertex2i(10000, 0);
glVertex2i(0, -10000);
glVertex2i(0, 10000);
glEnd();
glutSwapBuffers();
}
void ProcessNormalKeys(unsigned char key, int x, int y)
{
if (key == 27)
{
exit(0);
}
if (key == 65)
{
glMatrixMode(GL_MODELVIEW);
glTranslated(80, 80, 0);
Display();
}
}
void ProcessSpecialKeys(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_UP:
glMatrixMode(GL_MODELVIEW);
glTranslated(0, 80, 0);
Display();
break;
case GLUT_KEY_DOWN:
glMatrixMode(GL_MODELVIEW);
glTranslated(0, -80, 0);
Display();
break;
case GLUT_KEY_LEFT:
glMatrixMode(GL_MODELVIEW);
glTranslated(-80, 0, 0);
Display();
break;
case GLUT_KEY_RIGHT:
glMatrixMode(GL_MODELVIEW);
glTranslated(80, 0, 0);
Display();
break;
}
}
Store off the cube position in a global/per-window variable and use glPushMatrix()/glPopMatrix() around the glTranslated() + cube draw to ensure the transform doesn't effect later geometry:
// gcc main.c -lglut -lGL -lGLU
#include <GL/glut.h>
float cubePos[3] = {0, 0, 0};
void ProcessNormalKeys(unsigned char key, int x, int y)
{
if (key == 27)
{
exit(0);
}
if (key == 65)
{
cubePos[0] = 80;
cubePos[1] = 80;
cubePos[2] = 0;
glutPostRedisplay();
}
}
void ProcessSpecialKeys(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_UP:
cubePos[0] += 0;
cubePos[1] += 80;
cubePos[2] += 0;
glutPostRedisplay();
break;
case GLUT_KEY_DOWN:
cubePos[0] += 0;
cubePos[1] += -80;
cubePos[2] += 0;
glutPostRedisplay();
break;
case GLUT_KEY_LEFT:
cubePos[0] += -80;
cubePos[1] += 0;
cubePos[2] += 0;
glutPostRedisplay();
break;
case GLUT_KEY_RIGHT:
cubePos[0] += 80;
cubePos[1] += 0;
cubePos[2] += 0;
glutPostRedisplay();
break;
}
}
void Display()
{
glClearColor(1, 1, 1, 0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1000, 1000, -1000, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslated(cubePos[0], cubePos[1], cubePos[2]);
glBegin(GL_QUADS);
glColor3f(1.0, 1.0, 1.0);
glVertex2i(350, 550);
glColor3f(0.0, 0.0, 1.0);
glVertex2i(350, 150);
glColor3f(0.0, 1.0, 0.0);
glVertex2i(650, 150);
glColor3f(1.0, 0.0, 0.0);
glVertex2i(650, 550);
glEnd();
glPopMatrix();
glBegin(GL_LINES);
glColor3f(0, 0, 0);
glVertex2i(-10000, 0);
glVertex2i(10000, 0);
glVertex2i(0, -10000);
glVertex2i(0, 10000);
glEnd();
glutSwapBuffers();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(800, 600);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutCreateWindow("GLUT");
glutDisplayFunc(Display);
glutKeyboardFunc(ProcessNormalKeys);
glutSpecialFunc(ProcessSpecialKeys);
glutMainLoop();
return 0;
}
Related
I have created this code where a plane follow the mouse position.
#include <GL/freeglut_std.h>
#include <GL/gl.h>
#include <GL/glut.h>
#include <stdio.h>
float objX = 100;
float objY = 100;
float objSize = 50;
void motion(int x, int y) {
objX = x;
objY = y;
}
void drawRect(float x, float y, float size) {
glPushMatrix();
glTranslatef(x, y, 0.0f);
glScalef(size, size, 1.0f);
glBegin(GL_QUADS);
glColor3ub(255, 255, 255);
glVertex2f(-1, -1);
glVertex2f(1, -1);
glVertex2f(1, 1);
glVertex2f(-1, 1);
glEnd();
glPopMatrix();
}
void drawStaticRect(float x, float y, float size) {
glPushMatrix();
glTranslatef(x, y, 0.0f);
glScalef(size, size, 1.0f);
glBegin(GL_QUADS);
glColor3ub(255, 255, 255);
glVertex2f(-1, -1);
glVertex2f(1, -1);
glVertex2f(1, 1);
glVertex2f(-1, 1);
glEnd();
glPopMatrix();
}
int c = 0;
void display() {
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
const double w = glutGet(GLUT_WINDOW_WIDTH);
const double h = glutGet(GLUT_WINDOW_HEIGHT);
glOrtho(0, w, h, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
drawRect(objX, objY, objSize);
glutSwapBuffers();
}
void mouseClicks(int button, int state, int x, int y) {
if(button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
drawStaticRect(objX, objY, objSize);
}
glutPostRedisplay();
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(600, 600);
glutCreateWindow("GLUT");
glutDisplayFunc(display);
glutMouseFunc(mouseClicks);
glutPassiveMotionFunc(motion);
glutIdleFunc(display);
glutMainLoop();
return 0;
}
When the left mouse button is pressed i want to draw the object in the actual position, and repeat the operation as many times i want.
void drawStaticRect(float x, float y, float size) {
glPushMatrix();
glTranslatef(x, y, 0.0f);
glScalef(size, size, 1.0f);
glBegin(GL_QUADS);
glColor3ub(255, 255, 255);
glVertex2f(-1, -1);
glVertex2f(1, -1);
glVertex2f(1, 1);
glVertex2f(-1, 1);
glEnd();
glPopMatrix();
}
void mouseClicks(int button, int state, int x, int y) {
if(button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
drawStaticRect(objX, objY, objSize);
}
glutPostRedisplay();
My idea is when the event trigger i just call a function that generate a quads under the actual mouse position and call glutPostRedisplay() to update the scene.
I am having issues making my openGL terrain display in the window. I just get a see-through window, and I'm not sure what I'm missing.
Here is my code:
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <stdlib.h>
#define MAP_SCALE 20.0f
#define MAP_X 5
#define MAP_Z 5
int height[5][5] ={
{ 0, 0, 1, 1, 2 },
{ 0, 1, 2, 2, 3 },
{ 0, 1, 3, 2, 3 },
{ 0, 1, 2, 1, 2 },
{ 0, 0, 1, 1, 1 } };
float terrain[5][5][3];
int x, z;
float aspect = 1.0f;
void initializeTerrain()
{
for (z = 0; z < MAP_Z; z++)
{
for (x = 0; x < MAP_X; x++)
{
terrain[x][z][0] = (float)(x);
terrain[x][z][1] = (float)height[x][z];
terrain[x][z][2] = -(float)(z);
}
}
}
void display(void){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glColor3f(1.0, 0.0, 0.0);
for (z = 0; z < MAP_Z-1; z++)
{
glBegin(GL_TRIANGLE_STRIP);
for (x = 0; x < MAP_X-1; x++)
{
glVertex3f(terrain[x][z][0], terrain[x][z][1], terrain[x][z][2]);
glVertex3f(terrain[x+1][z][0], terrain[x+1][z][1], terrain[x+1][z][2]);
glVertex3f(terrain[x][z+1][0], terrain[x][z+1][1], terrain[x][z+1][2]);
glVertex3f(terrain[x+1][z+1][0], terrain[x+1][z+1][1], terrain[x+1][z+1][2]);
}
glEnd();
}
glFlush();
}
void myInit(){
initializeTerrain();
glMatrixMode(GL_PROJECTION);
glViewport(0, 0, 500, 500);
gluLookAt(1,1,0, 0,0,0, 0.0, 1.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glClearColor(0.0, 0.0, 1.0, 1.0);
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-10.0, 10.0, -5.0 * (GLfloat) h / (GLfloat) w,
15.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0);
else
glOrtho(-10.0 * (GLfloat) w / (GLfloat) h,
10.0 * (GLfloat) w / (GLfloat) h, -5.0, 15.0, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void main(int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutCreateWindow("A3");
myInit();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMainLoop();
}
When I resize, it fills with white, but I don't get the mesh. Can anyone help?
Thanks!
You requested a double buffered window, so you have to do a doublebuffer swap when you're done drawing. Replace that glFinish() in your display function with glutSwapBuffers().
I'm trying to change the sphere position after a mouse click but it doesnt work when using the x and y from glutMouseFunc ,, here is the code :
//
#include "stdafx.h"
#include <stdlib.h>
#include <GL/glut.h>
bool Cone=false , ConeSelected=false,
Cube=false, CubeSelected=false,
Sphere=false, SphereSelected=false,
Teapot=false, TeapotSelected =false,
Torus=false, TorusSelected=false;
static float XSphere=0, YSphere=-1.5 ,ZSphere=0;
void init(void)
{
GLfloat blankMaterial[] = {1.0, 0.0, 0.0};
GLfloat whiteDiffuseLight[] = {30};
glClearColor (0.0, 0.1, 0.2, 0.0);
glClearDepth(1.0);
glShadeModel (GL_FLAT);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, blankMaterial);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, blankMaterial);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, whiteDiffuseLight);
}
void display(void)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
//Drawing Cube
if(Cube)
{
glPushMatrix();
glColor3f(0, 1, 0);
glTranslatef(-3,0,-3);
glRotatef(20, 1,0,0);
glutSolidCube(2);
glPopMatrix() ;
}
//drawing cone
if(Cone)
{
glPushMatrix();
glColor3f (1.0, 0.0, 1.0);
glTranslatef(0,2,0);
glRotatef(50, 1,0,0);
glutSolidCone(.5,1,10,10);
glPopMatrix() ;
}
//Drawing Solid Sphere
if(Sphere)
{
glPushMatrix();
glTranslatef(XSphere,YSphere,ZSphere);
glutSolidSphere(.5, 20, 20);
glPopMatrix();
glDisable(GL_DEPTH_TEST);
}
glColor3f (1.0f, 1.0f, 1.0f);
//drawing Torus
if(Torus)
{
glPushMatrix();
glColor3f (1.0, 1.0, 1.0);
glTranslatef(2,2,0);
glRotatef(60, 1,0,0);
glutSolidTorus(.2,.5,40,30);
glPopMatrix() ;
}
//Drawing teapot
if(Teapot)
{
glPushMatrix ();
glTranslatef (2.0, 0.0, 0.0);
glutSolidTeapot(.5);
glPopMatrix ();
}
glFlush();
glutSwapBuffers();
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
void keyboard (unsigned char key, int x, int y)
{int modifiers = glutGetModifiers();
switch (key) {
case 'A':
Teapot=Cone=Sphere=Cube=Torus=true;
glutPostRedisplay();
break;
case 'D':
Teapot=Cone=Sphere=Cube=Torus=false;
glutPostRedisplay();
break;
case 'S':
Teapot=Cone=Cube=Torus=false;
Sphere=true;
TeapotSelected=ConeSelected=CubeSelected=TorusSelected=false;
SphereSelected=true;
break;
case 27:
exit(0);
break;
default:
break;
}
}
Here in the mouse section I tried to set the gltranslation in the above drawing sphere but when I checked the results for x and y they were large and that's why I couldnt see the sphere after clicking the mouse , how can i fix this ??
void MyMouse(int button, int state, int x, int y)
{
switch (button)
{
case GLUT_LEFT_BUTTON:
if(state == GLUT_UP)
{
if (SphereSelected)
{
Cone=Cube=Torus=Teapot=false;
Sphere=true;
XSphere=x;
YSphere=y;
ZSphere=1;
glutPostRedisplay();
}
}
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize (900, 900);
glutInitWindowPosition (0, 100);
glutCreateWindow ("Scene Modeling and Interaction");
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMouseFunc(MyMouse);
glutMainLoop();
return 0;
}
The x and y that the mouse function gives you are in screen pixel coordinates, not in the coordinates that your scene uses. In order to do this, you have to center your coordinates (by subtracting by half your screen size) and scaling them to about your screen size (by dividing them by something on the order of your screen size).
Thus, you probably want to do something like
XSphere = (x - 450) * 3.0 / 900;
YSphere = (450 - y) * 3.0 / 900;
and play around with the 3.0 until it gives you something reasonable.
I have an openGL program thats using GLUT and I'm stuck with moving it from the top left corner to bottom right when i resize the window. I'm trying to get a ratio down and i cant figure it out.
#include <stdio.h>
#include <stdlib.h>
#include <GLUT/glut.h>
//global variables
GLsizei wh = 500, ww = 500;
double height;
double width;
double top = 500;
double bottom = 450;
int right = 50;
int left = 0;
double ratiowidth = 500/500;
double ratioheight = 500/500;
void myinit(){
glClearColor (0.0, 0.0, 0.0, 0.0);
}
void reshape(int w, int h){
if(h == 0){
h = 1;
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, (GLsizei) w, 0, (GLsizei)h);
glViewport(0,0,w,h);
glMatrixMode(GL_MODELVIEW);
int difference = h - wh;
int difference2 = w - ww;
left = left + difference2;
right = right + difference2;
wh = (GLsizei)h;
ww = (GLsizei)w;
height = h;
width = w;
}
void mouse(int button, int state, int x, int y){
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN){
top = height;
bottom = height - 50;
right = 50;
left = 0;
ratiowidth = width/height;
ratioheight = height/width;
}
if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN){
exit(0);
}
}
void display(){
glClear (GL_COLOR_BUFFER_BIT);
glColor3i (rand(), rand(), rand());
glBegin(GL_POLYGON);
glVertex3f (left,top,0.0);
glVertex3f (right, top, 0.0);
glVertex3f (right, bottom, 0.0);
glVertex3f (left, bottom, 0.0);
glEnd();
if(bottom == 0 || bottom < 0)
bottom = 0;
else{
left = left + ratiowidth;
right = right + ratiowidth;
top = top - ratioheight;
bottom = bottom - ratioheight;
}
glutSwapBuffers();
usleep(10000);
glutPostRedisplay();
}
int main(int argc, char** argv) {
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(ww, wh);
glutInitWindowPosition(100,100);
glutCreateWindow("moving Square");
myinit();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutMainLoop();
return 0;
}
glBegin(GL_POLYGON);
glVertex3f (left,top,0.0);
glVertex3f (right, top, 0.0);
glVertex3f (right, bottom, 0.0);
glVertex3f (left, bottom, 0.0);
glEnd();
Careful with your winding order. glFrontFace() defaults to GL_CCW. Perhaps you meant this:
glBegin(GL_POLYGON);
glVertex3f (left, bottom, 0.0);
glVertex3f (right, bottom, 0.0);
glVertex3f (right, top, 0.0);
glVertex3f (left,top,0.0);
glEnd();
EDIT: This is what I think you were trying to do:
#include <GL/glut.h>
struct State
{
double x; // in units
double y;
double xvel; // in units per second
double yvel;
};
State curState = { 0 };
void myinit()
{
curState.xvel = 100;
curState.yvel = 100;
}
void Integrate( State* state, double dt )
{
state->x += state->xvel * dt;
state->y += state->yvel * dt;
}
double GetSeconds()
{
return glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
}
void reshape(int w, int h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, (GLsizei)w, 0, (GLsizei)h);
}
void mouse(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON && state == GLUT_UP)
{
curState.x = 0;
curState.y = 0;
}
if(button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
{
exit(0);
}
}
void display()
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glClear (GL_COLOR_BUFFER_BIT);
float w = 20;
float h = 20;
float x = curState.x;
float y = curState.y;
glColor3ub(rand()%255, rand()%255, rand()%255);
glBegin(GL_QUADS);
glVertex2f( x - w/2, y - h/2 );
glVertex2f( x + w/2, y - h/2 );
glVertex2f( x + w/2, y + h/2 );
glVertex2f( x - w/2, y + h/2 );
glEnd();
static double lastTime = GetSeconds();
double curTime = GetSeconds();
Integrate( &curState, curTime - lastTime );
lastTime = curTime;
glutSwapBuffers();
}
void timer(int extra)
{
glutPostRedisplay();
glutTimerFunc(16, timer, 0);
}
int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100,100);
glutCreateWindow("moving Square");
myinit();
glutReshapeFunc(reshape);
glutTimerFunc(0, timer, 0);
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutMainLoop();
return 0;
}
Be aware that there are probably some C++-isms in there :)
When I try to resize my glut window, the screen goes blank.
This is the code for the reshape callback funciton:
void Resize(int width, int height)
{
CurrentWidth = width;
CurrentHeight = height;
glViewport(0, 0, (GLsizei)CurrentWidth, (GLsizei)CurrentHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, CurrentWidth, CurrentHeight, 0, NearPlane, FarPlane);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glutPostRedisplay();
}
I am pretty new to the opengl world but from what I have learned this is supposed to work.
And this is all of the code put together:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <gl/glut.h>
#include "Utils.h"
int LEFT = 0;
int RIGHT = 0;
int UP = 0;
int DOWN = 0;
int CurrentWidth = 800,
CurrentHeight = 800,
WindowHandle = 0;
float NearPlane = 1.0f,
FarPlane = 100.0f;
float lightX,
lightY;
void Initialize(int, char*[]);
void InitWindow(int, char*[]);
void Idle(void);
void Resize(int, int);
void KeyPressed(unsigned char, int, int);
void SpecialPressed(int, int, int);
void SpecialReleased(int, int, int);
void Update(void);
void Render(void);
void FillZBuffer(void);
void ClearAlpha(void);
void RenderLightAlpha(float);
void GeometryPass(void);
void Draw(void);
int main (int argc, char* argv[])
{
Initialize(argc, argv);
glutMainLoop();
exit(EXIT_SUCCESS);
}
void Initialize(int argc, char* argv[])
{
InitWindow(argc, argv);
fprintf(
stdout,
"INFO: OpenGL Version: %s\n",
glGetString(GL_VERSION)
);
lightX = 300.0f;
lightY = 300.0f;
}
void InitWindow(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitContextVersion(3, 3);
glutInitContextProfile(GLUT_COMPATIBILITY_PROFILE);
glutSetOption(
GLUT_ACTION_ON_WINDOW_CLOSE,
GLUT_ACTION_GLUTMAINLOOP_RETURNS
);
glutInitWindowSize (CurrentWidth, CurrentHeight);
glutInitWindowPosition (100, 100);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA | GLUT_ALPHA);
WindowHandle = glutCreateWindow ("Shadows");
if(WindowHandle < 1) {
fprintf(
stderr,
"ERROR: Could not create a new rendering window.\n"
);
exit(EXIT_FAILURE);
}
glutDisplayFunc(Render);
glutReshapeFunc(Resize);
glutIdleFunc(Idle);
glutKeyboardFunc(KeyPressed);
glutSpecialFunc(SpecialPressed);
glutSpecialUpFunc(SpecialReleased);
}
void Update()
{
int speed = 10;
if (LEFT)
{
lightX -= speed;
}
if (RIGHT)
{
lightX += speed;
}
if (UP)
{
lightY -= speed;
}
if (DOWN)
{
lightY += speed;
}
}
void Draw()
{
float x = 200;
float y = 200;
float w = 100;
float h = 100;
float depth = 0.0f;
// floor
glColor4f(0.5f, 0.5f, 0.5f, 1.0f);
depth = -10.0f;
glBegin(GL_QUADS);
{
glVertex3f(0, 0, depth);
glVertex3f((float)CurrentWidth, 0, depth);
glVertex3f((float)CurrentWidth, (float)CurrentHeight, depth);
glVertex3f(0, (float)CurrentHeight, depth);
}
glEnd();
// square
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
depth = -5.0;
glBegin(GL_QUADS);
{
glVertex3f( x, y, depth);
glVertex3f( x + w, y, depth);
glVertex3f(x + w, y + h, depth);
glVertex3f(x, y + h, depth);
}
glEnd();
}
void Render()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_CULL_FACE);
Update();
FillZBuffer();
ClearAlpha();
RenderLightAlpha(1.0f);
GeometryPass();
glutSwapBuffers();
glutPostRedisplay();
}
void FillZBuffer()
{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_TRUE);
Draw();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_FALSE);
}
void ClearAlpha()
{
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
glBegin (GL_QUADS);
{
glVertex2f(0, 0);
glVertex2f((float)CurrentWidth, 0);
glVertex2f((float)CurrentWidth, (float)CurrentHeight);
glVertex2f(0, (float)CurrentHeight);
}
glEnd ();
}
void RenderLightAlpha(float intensity)
{
float depth = -1.0f;
float radius = 300.0f;
float angle;
int numSubdivisions = 32;
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glBegin(GL_TRIANGLE_FAN);
{
glColor4f(0.0f, 0.0f, 0.0f, intensity);
glVertex3f(lightX, lightY, depth);
// Set edge colour for rest of shape
glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
for (angle = 0; angle <= (float)PI * 2; angle += (((float)PI * 2) / numSubdivisions))
{
glVertex3f( radius*(float)cos(angle) + lightX, radius*(float)sin(angle) + lightY, depth);
}
glVertex3f(lightX + radius, lightY, depth);
}
glEnd();
}
void GeometryPass()
{
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_BLEND);
glBlendFunc(GL_DST_ALPHA, GL_ONE);
Draw();
}
void Idle()
{
glutPostRedisplay();
}
void Resize(int width, int height)
{
CurrentWidth = width;
CurrentHeight = height;
glViewport(0, 0, (GLsizei)CurrentWidth, (GLsizei)CurrentHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, CurrentWidth, CurrentHeight, 0, NearPlane, FarPlane);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glutPostRedisplay();
}
void KeyPressed(unsigned char key, int x, int y)
{
UNREFERENCED_PARAMETER(x);
UNREFERENCED_PARAMETER(y);
// escape key
if (key == 27)
{
exit(0);
}
}
void SpecialPressed(int keyCode, int x, int y)
{
UNREFERENCED_PARAMETER(x);
UNREFERENCED_PARAMETER(y);
if (keyCode == GLUT_KEY_LEFT)
{
LEFT = 1;
}
else if (keyCode == GLUT_KEY_RIGHT)
{
RIGHT = 1;
}
else if (keyCode == GLUT_KEY_UP)
{
UP = 1;
}
else if (keyCode == GLUT_KEY_DOWN)
{
DOWN = 1;
}
}
void SpecialReleased(int keyCode, int x, int y)
{
UNREFERENCED_PARAMETER(x);
UNREFERENCED_PARAMETER(y);
if (keyCode == GLUT_KEY_LEFT)
{
LEFT = 0;
}
else if (keyCode == GLUT_KEY_RIGHT)
{
RIGHT = 0;
}
else if (keyCode == GLUT_KEY_UP)
{
UP = 0;
}
else if (keyCode == GLUT_KEY_DOWN)
{
DOWN = 0;
}
}
Let me know if you need anymore information.
In the FillZBuffer function the depth mask is disabled at the end and only re-enabled at the beginning of the same function. So when Render is called again, the call to clear the depth buffer bit does nothing because the depth mask is disabled.
To fix this the depth mask must be re-enabled before the call to clear the depth buffer bit.
So this is what Render should look like.
void Render()
{
glDepthMask(GL_TRUE); // insert this line
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_CULL_FACE);
Update();
FillZBuffer();
ClearAlpha();
RenderLightAlpha(1.0f);
GeometryPass();
glutSwapBuffers();
glutPostRedisplay();
}