openGL Rotate Sphere with fix light - opengl

i want to rotate a Sphere. And the light should be on a fix position in the room.
But it seems that the light is not on a fix position but rotate with the sphere.
I tried to put everything in push/popmatrix. Doesn't help.
I read about normal but I also read that glut does it automaticlly with spheres.
How can I fix the light position?
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glut.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
float angletest = 1;
float winwidth, winheight;
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case'\033':
exit(0);
break;
}
}
void reshape(w, h)
GLsizei w;
GLsizei h;
{
int size;
winwidth = w;
winheight = h;
size = w>h ? h : w;
glViewport(0, 0, size, size);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(40, 1.0, 1.0f, 20.0f);
glutPostRedisplay();
}
void display(void)
{
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glLoadIdentity();
GLUquadricObj *quadric;
quadric = gluNewQuadric();
glPushMatrix();
glColor3f(0, 0, 1);
glTranslatef(0.5, 0, 0);
glRotatef(angletest, 0, 0, 1);
gluSphere(quadric, 0.2, 50, 50);
glPopMatrix();
glPushMatrix();
glColor3f(0, 1, 0);
glRotatef(angletest, 0, 0, 1);
glTranslatef(0, 0.5, 0);
glutSolidSphere(0.2, 50, 50);
glPopMatrix();
glFlush();
glutSwapBuffers();
}
void init()
{
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
glClearColor(0, 0, 0, 0);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shininess[] = { 50.0 };
GLfloat light_position[] = { 0, 0.5, 0, 1.0f };
glShadeModel(GL_SMOOTH);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHT0);
}
void idle(void)
{
angletest = angletest + 0.05;
glutPostRedisplay();
}
void main(int argc, char** argv)
{
glutInitWindowSize(400, 400);
glutInitWindowPosition(100, 100);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("test");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutIdleFunc(idle);
init();
glutMainLoop();
}
Tried to do it like mentioned below and put the
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
between glRotatef(angletest, 0, 0, 1); and gluSphere(quadric, 0.2, 50, 50);
But that didn't do it as well.
glPushMatrix();
glColor3f(0, 0, 1);
glTranslatef(0.5, 0, 0);
glRotatef(angletest, 0, 0, 1);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
gluSphere(quadric, 0.2, 50, 50);
glPopMatrix();
Actually, i wanted the lightsource to be in the middle. But if i put it in the position 0,0,0 there is no light at all.
To make clear what I mean by moving light, I have three pictures here.
light is in the right corner
light is in the left down corner
So you can see it seems like the light is moving with the objects.
But what I want is the light to stay in the middle and give lights to the object like if it was a sun.

Sorry, my comment was wrong. I just realized that you don't use the matrix stack to transform the camera (the view part in model-view) but the object space (the model part). glLightfv() should be called after you change the view part and before you change the model part. But you never change the view part in your code, so setting up the light once is sufficient.
There is another subtle problem in your code, which causes this behavior. Take a look at your reshape() function. You change the matrix mode to projection and never change it back to model-view. Hence, all matrix transformations that you apply are applied to the projection matrix. Lighting is calculated in view space. And since you do not change the model-view matrix, all lighting is done in the object's coordinate system (assuming the light position in this system). The projection matrix then rotates the already illuminated object, possibly away from the light.
So the solution is simple: Switch the matrix mode back to model-view in your reshape() function.

Related

OpenGL - Load mutliple texures in one function

I've already constructed a 15x15 grid of cubes with glutSolidCube(). Then i have a menu handler in which when I click "Start Game", loads the texture I used to all of the cubes, calling a custom glutSolidCube and having glTexCoord2d before each declaration of vertices, cause we can't have textures on the latter I think. For uploading the texture from an image, I'm using a STB_IMAGE_IMPLEMENTATION implementation having also a header file included. The function loadTextureFromFile(const char *filename) does the loading part.
How can I upload more textures (I want 2 more, in the same loadTextureFromFile() function preferably) and how to handle each texture with the glTexCoord2d()?
Here's my entire code:
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/gl.h> // openGL header
#include <GL/glu.h> // glut header
#include <GL/glut.h> // glut header
#define STB_IMAGE_IMPLEMENTATION
/////////////////////////////////////Textures==============================================/////////////////////////////////////
#include "stb_image.h"
GLuint texture; //the array for our texture
void loadTextureFromFile(const char *filename)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
//glShadeModel(GL_FLAT);
//glEnable(GL_DEPTH_TEST);
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
// set the texture wrapping/filtering options (on the currently bound texture object)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// load and generate the texture
int width, height, nrChannels;
unsigned char *data = stbi_load("paper.bmp", &width, &height, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
//glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
}
void FreeTexture(GLuint texture)
{
glDeleteTextures(1, &texture);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void
drawBox(GLfloat size, GLenum type)
{
static GLfloat n[6][3] =
{
{-1.0, 0.0, 0.0},
{0.0, 1.0, 0.0},
{1.0, 0.0, 0.0},
{0.0, -1.0, 0.0},
{0.0, 0.0, 1.0},
{0.0, 0.0, -1.0}
};
static GLint faces[6][4] =
{
{0, 1, 2, 3},
{3, 2, 6, 7},
{7, 6, 5, 4},
{4, 5, 1, 0},
{5, 6, 2, 1},
{7, 4, 0, 3}
};
GLfloat v[8][3];
GLint i;
v[0][0] = v[1][0] = v[2][0] = v[3][0] = -size / 2;
v[4][0] = v[5][0] = v[6][0] = v[7][0] = size / 2;
v[0][1] = v[1][1] = v[4][1] = v[5][1] = -size / 2;
v[2][1] = v[3][1] = v[6][1] = v[7][1] = size / 2;
v[0][2] = v[3][2] = v[4][2] = v[7][2] = -size / 2;
v[1][2] = v[2][2] = v[5][2] = v[6][2] = size / 2;
for (i = 5; i >= 0; i--) {
glBegin(type);
glNormal3fv(&n[i][0]);
glTexCoord2d(0.0,0.0);
glVertex3fv(&v[faces[i][0]][0]);
glTexCoord2d(0.0,1.0);
glVertex3fv(&v[faces[i][1]][0]);
glTexCoord2d(1.0,1.0);
glVertex3fv(&v[faces[i][2]][0]);
glTexCoord2d(1.0,0.0);
glVertex3fv(&v[faces[i][3]][0]);
glEnd();
}
}
void APIENTRY
myglutSolidCube(GLdouble size)
{
drawBox(size, GL_QUADS);
}
//int red_color[]={255,0,0};
//int blue_colot[]={0,0,255};
//////////////////////////////=========MENU============/////////////
enum MENU_TYPE //menu options-values
{
MENU_START,
MENU_EXIT,
};
//create the menu - Prototype
void my_createmenu(void);
// Menu handling function declaration - Prototype
void menu(int);
void init()
{ //for 3d lighting
glEnable(GL_DEPTH_TEST); //depth test
glEnable(GL_LIGHTING); //enable light from a single source
glEnable(GL_LIGHT0); //enable white light , diffuse and specular components
glEnable(GL_COLOR_MATERIAL); //track the current color
}
void display()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); //Black and opaque
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//define the projection matrix just once and use the modelview matrix all other times
glMatrixMode(GL_PROJECTION); //Applies subsequent matrix operations to the projection matrix stack
glLoadIdentity();//Reset
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport); //The params parameter returns four values: the x and y window coordinates of the viewport, followed by its width and height
double aspect = (double)viewport[2] / (double)viewport[3]; // y/width would be 1.0
gluPerspective(60,aspect, 1, 100); //using perspective projection
//gluOrtho2D(0.0,600.0,-60.0,600.0);
glMatrixMode(GL_MODELVIEW); //for trasformations - Applies subsequent matrix operations to the texture matrix stack
glLoadIdentity();
// move back a bit for viewer , cause of gluPerspective
glTranslatef( 0, 0, -35 );
float e=0,f=0;
//construct the grid with reference the central cube
for(int i=0;i<8;i++) {
for(int j=0;j<8;j++) {
glPushMatrix();
glTranslatef(0.0f+e,0.0f+f,0.0f); //right and below
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
glColor3ub(245, 245, 220); //Beige
glutSolidCube(2.25);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0f-e,0.0f+f,0.0f); //left and below
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
glColor3ub(245, 245, 220); //Beige
glutSolidCube(2.25);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0f+e,0.0f-f,0.0f); //right and up
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
glColor3ub(245, 245, 220); //Beige
glutSolidCube(2.25);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0f-e,0.0f-f,0.0f); //left and up
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
glColor3ub(245, 245, 220); //Beige
glutSolidCube(2.25);
glPopMatrix();
f += -2.63;
}
f=0;
e+=2.63;
}
glutSwapBuffers(); //implicit glFlush
}
//for the second part of program
void display_game()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); //Black and opaque
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//define the projection matrix just once and use the modelview matrix all other times
glMatrixMode(GL_PROJECTION); //Applies subsequent matrix operations to the projection matrix stack
glLoadIdentity();//Reset
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport); //The params parameter returns four values: the x and y window coordinates of the viewport, followed by its width and height
double aspect = (double)viewport[2] / (double)viewport[3]; // y/width would be 1.0
gluPerspective(60,aspect, 1, 100); //using perspective projection
//glOrtho(0.0f, 600.0f, 600.0f, 0.0f, 0.0f, 1.0f);
glMatrixMode(GL_MODELVIEW); //for trasformations - Applies subsequent matrix operations to the texture matrix stack
glLoadIdentity();
// move back a bit for viewer , cause of gluPerspective
glTranslatef( 0, 0, -35 );
float e=0,f=0;
glEnable(GL_TEXTURE_2D);
//construct the grid with reference the central cube
for(int i=0;i<8;i++) {
for(int j=0;j<8;j++) {
glPushMatrix();
glTranslatef(0.0f+e,0.0f+f,0.0f); //right and below
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
//glColor3ub(245, 245, 220); //Beige
//glColor3ub( rand()%255,rand()%255, rand()%255 );
myglutSolidCube(2.25);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0f-e,0.0f+f,0.0f); //left and below
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
//glColor3ub( rand()%255,rand()%255, rand()%255 );
myglutSolidCube(2.25);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0f+e,0.0f-f,0.0f); //right and up
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
myglutSolidCube(2.25);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0f-e,0.0f-f,0.0f); //left and up
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
myglutSolidCube(2.25);
glPopMatrix();
f += -2.63;
}
f=0;
e+=2.63;
}
//SEED to some constant value for 2nd part of the program. If it is not used , cubes would change color in runtime
//srand(0x98765432);
glutSwapBuffers(); //implicit glFlush
glDisable(GL_TEXTURE_2D);
}
void reshape(GLsizei width, GLsizei height) {
// GLsizei for non-negative integer // Compute aspect ratio of the new window
if (height == 0) height = 1; // To prevent divide by 0
GLfloat aspect = (GLfloat)width / (GLfloat)height; // Set the viewport to cover the new window
glViewport(0, 0, width, height); // Set the aspect ratio of the clipping volume glMatrixMode(GL_PROJECTION); // To operate on the Projection matrix
glLoadIdentity(); // Reset // Enable perspective projection with fovy, aspect, zNear and zFar
gluPerspective(45.0f, aspect, 0.1f, 100.0f);
}
void timer(int extra)
{
glutPostRedisplay();
glutTimerFunc(16, timer, 0);
}
void mouseEscape( int button, int state, int x, int y )
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN &&button==MENU_EXIT)
{
int windowID = glutCreateWindow("CUBES");
glutDestroyWindow(windowID);
exit(0);
}
glutPostRedisplay();
}
//for loading the texture
const char* filename = "salt_on_spoon.bmp";
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitWindowSize(600,600);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE| GLUT_MULTISAMPLE);
glEnable(GL_MULTISAMPLE); //anti-alliasing
glutCreateWindow("CUBES");
//create and handle the menu
my_createmenu();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutTimerFunc(0, timer, 0);
init();
//glEnable(GL_TEXTURE_2D); //for texture
//glutMouseFunc(mouseEscape);
//glutKeyboardFunc(keyEscape);
//Load our texture
//loadTextureFromFile(filename);
glutMainLoop();
//Free our texture
//FreeTexture(texture);
return 0;
}
//create the menu-entries
void my_createmenu(void) {
// Create a menu
glutCreateMenu(menu);
// Add menu items
glutAddMenuEntry("Start Game", MENU_START);
glutAddMenuEntry("Exit", MENU_EXIT);
// Associate a mouse button with menu
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
// Menu handling function-what to do in each value
void menu(int item)
{
switch (item)
{
case MENU_START: {
//glEnable(GL_TEXTURE_2D); //for texture
//Load our texture
loadTextureFromFile(filename);
glutDisplayFunc(display_game);
}
break;
case MENU_EXIT:
{
int windowID = glutCreateWindow("CUBES"); //exit game
glutDestroyWindow(windowID);
exit(0);
}
break;
default:
{ /* Nothing */ }
break;
}
glutPostRedisplay();
return;
}
I'm doing the texture loading part in the menu function. How will I be able to handle three textures? The ultimate goal is to make a rand call also for the three textures to be rendered on the cubes.
I also have two pictures: 1st: when the program begins:
2nd: after clicking "Star Game" where you can see the texture rendered in all of the cubes:
The goal is for more 2 types of textures and all of them render in random cubes.
You can create more than 1 texture object.
glBindTexture binds a named texture to a texturing target, that is a global state. glTexImage2D specify a two-dimensional texture image for the texture, which is currently bound to the specified target. glTexParameter set parameter to the texture object.
I recommend to write a function which loads a texture form a file to a given texture object (name id):
void loadTextureFromFile(const char *filename, unsigned int texture)
{
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// load and generate the texture
int width, height, nrChannels;
unsigned char *data = stbi_load(filename, &width, &height, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
GL_RGB, GL_UNSIGNED_BYTE, data);
//glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
}
const char* filename1 = "salt_on_spoon.bmp";
const char* filename2 = ...;
const char* filename3 = ...;
unsigned int tob[3];
int main(int argc, char **argv)
{
// [...]
glGenTextures(3, &tob[0]);
loadTextureFromFile(filename1, tob[0]);
loadTextureFromFile(filename2, tob[1]);
loadTextureFromFile(filename3, tob[2]);
// [...]
}
When two-dimensional texturing is enabled, then the image of the texture object, which is currently bound to the target GL_TEXTURE_2D is wrapped on the mesh.
You've to bind the proper texture object, before you draw the geometry. e.g:
for(int i=0;i<8;i++) {
for(int j=0;j<8;j++) {
glBindTexture(GL_TEXTURE_2D, tob[0]);
glPushMatrix();
glTranslatef(0.0f+e,0.0f+f,0.0f); //right and below
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
myglutSolidCube(2.25);
glPopMatrix();
glBindTexture(GL_TEXTURE_2D, tob[1]);
glPushMatrix();
glTranslatef(0.0f-e,0.0f+f,0.0f); //left and below
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
myglutSolidCube(2.25);
glPopMatrix();
glBindTexture(GL_TEXTURE_2D, tob[2]);
glPushMatrix();
glTranslatef(0.0f+e,0.0f-f,0.0f); //right and up
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
myglutSolidCube(2.25);
glPopMatrix();
glBindTexture(GL_TEXTURE_2D, tob[0]);
glPushMatrix();
glTranslatef(0.0f-e,0.0f-f,0.0f); //left and up
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
myglutSolidCube(2.25);
glPopMatrix();
f += -2.63;
}
f=0;
e+=2.63;
}
Note, the distribution of the textures is just an example. You've to ensure that unsigned int tob[3]; is declared before, in global namespace.

How to make the background of my texture transparent? (My image is already backgroundless)

I have a backgroundless image of a gun. I am trying to build a first person shooter game with the help of this 2D image of a gun. I have loaded the texture in my program but I am unable to make the background of the gun transparent. Moreover, why should I even have to do that when my image is already backgroundless. I used clippingmagic.com to remove the background of my image. The code is:
#include <iostream>
#include <stdlib.h> //Needed for "exit" function
#include<SOIL/SOIL.h>
//Include OpenGL header files, so that we can use OpenGL
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
using namespace std;
const float A = 1366.0; //width of the computer screen
const float B = 768.0; //height of the computer screen
//Called when a key is pressed
void handleKeypress(unsigned char key, //The key that was pressed
int x, int y) { //The current mouse coordinates
switch (key) {
case 27: //Escape key
exit(0); //Exit the program
}
}
//Initializes 3D rendering
void initRendering() {
//Makes 3D drawing work when something is in front of something else
glEnable(GL_DEPTH_TEST);
}
//Called when the window is resized
void handleResize(int w, int h) {
//Tell OpenGL how to convert from coordinates to pixel values
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); //Switch to setting the camera perspective
//Set the camera perspective
glLoadIdentity(); //Reset the camera
gluPerspective(45.0, //The camera angle
(double)w / (double)h, //The width-to-height ratio
1.0, //The near z clipping coordinate
200.0); //The far z clipping coordinate
}
//Draws the 3D scene
void drawScene() {
//Clear information from last draw
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
glLoadIdentity(); //Reset the drawing perspective
glTranslatef(0.0,0.0,-10.0);
//DRAW WALL OF ROOM
glBegin(GL_QUADS);
glColor3f(0.0, 1.0, 1.0);
glVertex3f(-100.0, -100.0, -100.0);
glVertex3f(-100.0, 100.0, -100.0);
glVertex3f( 100.0, 100.0, -100.0);
glVertex3f( 100.0, -100.0, -100.0);
glEnd();
//DRAW GUN
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GLuint gun_tex_id = SOIL_load_OGL_texture
(
"GUN.png",
SOIL_LOAD_RGB, //I even tried SOIL_LOAD_AUTO and SOIL_LOAD_RGBA but it didn't help
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_MULTIPLY_ALPHA
);
glBindTexture(GL_TEXTURE_2D, gun_tex_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTranslatef(2.0,0.0,0.0);
glColor3f(1.0,1.0,1.0);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-4.1,-4.15, 0.0);
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 3.0,-4.15, 0.0);
glTexCoord2f(1.0f, 1.0f);
glVertex3f( 3.0, 1.2, 0.0);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-4.1, 1.2, 0.0);
glEnd();
glDisable(GL_BLEND);
glutSwapBuffers(); //Send the 3D scene to the screen
}
void myinit(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0); /* gray background */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( -A/2, A/2, -B/2, B/2, -200, 200);
/* In World coordinates:position the "clipping rectangle" at -A/2, its right edge at +A/2, its bottom edge at -B/2 and its top edge at +B/2 */
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv) {
//Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(A, B); //Set the window size
//Create the window
glutCreateWindow("My shooting game");
initRendering(); //Initialize rendering
//Set handler functions for drawing, keypresses, and window resizes
glutDisplayFunc(drawScene);
glutKeyboardFunc(handleKeypress);
glutReshapeFunc(handleResize);
myinit();
glutMainLoop(); //Start the main loop. glutMainLoop doesn't return.
return 0; //This line is never reached
}
You can do it using glBlendFunc function.
Try adding the following code snippet before you bind texture to the object.
glEnable(GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Read this for more information.

OpenGL Teapot drawing error

I've been working on an object model but it seems that something is wrong. This is what I get when I draw a teapot:
As you can see, background objects appear in foreground like the ring at the top. I've been working on everything I can changing things like the clipping plane and the the depth buffer but I just can't seem to get the model to appear solid. I have depth enabled along with cull face and I'm clearing the depth buffer and color buffer. I can't tell what's wrong.
Here is my code listing:
void displayLighting() {
if ( specular )
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
else
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_FRONT, GL_SHININESS, shininess);
lightPos[0] = lightDist*sinf(lightAngle);
lightPos[1] = lightDist;
lightPos[2] = lightDist*cosf(lightAngle);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos );
}
void drawTeapot() {
float diffuseMaterial[] = { 1.f, 1.f, 1.f };
glTranslatef(0.f, -0.f, -0.f);
glShadeModel(GL_SMOOTH);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuseMaterial);
glutSolidTeapot(20.0f);
}
void renderScene(void) {
glClearColor(0.f,0.f,0.f,1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt( zDist*(sinf(yAngle)),zDist*(sinf(xAngle)),zDist*(cosf(xAngle))*(cosf(yAngle)),0,0,0,0,1,0 );
displayLighting();
drawTeapot();
glutSwapBuffers();
}
void changeSize(int width, int height) {
float ratio;
ratio = w * 1.0f / h;
glMatrixMode(GL_PROJECTION);
glViewport(0, 0, w, h);
glLoadIdentity();
gluPerspective(45.0f, ratio, 100.0f, 1000.0f);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char **argv) {
// init GLUT and create window
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(0,0);
glutInitWindowSize(800,600);
glutCreateWindow("Teapot");
initLighting();
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
glutIdleFunc(renderScene);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glutMainLoop();
}
I'm pretty sure it's a simple fix but I hope you guys can help out.
According to the manpage of glutSolidTeapot, the generated normals are oriented in the opposite direction than the expected one. As suggested, use glFrontFace(GL_CW) / glFrontFace(GL_CCW) to temporarily change the default front-facing orientation for faces.

OpenGL offscreen rendered texture not displaying on screen

I am having difficulty getting a offscreen rendered texture to to be displayed. I have checked round the web and other questions and am clearly missing something.
I am new to OpenGL so may well be making some naive errors. It is part of a routine to add post processing using a shader to modify the firestor/secondlife viewer project to an equifisheye projection. My test code is based around the GLEW and GLUT framework using OpenGL 1.3 as the viewer is designed to run on older platforms.
The approach is:
set up and initialise the FBO, Render buffers and textures to draw to.
initilise various default settings for drawing the glutCube and glutTeapot :)
The display function
a) using the default framebuffer draws a rotating cube (works fine)
b) the texture is then drawn to
OUTPUT: all black and not the rotating cube.
My code is:
GLuint buffer_fbo;
GLuint bufferColtexture;
GLuint depthBuffer_rb;
typedef struct {
int width;
int height;
char* title;
float field_of_view_angle;
float z_near;
float z_far;
} glutWindow;
glutWindow win;
//
void ShutDown(void)
{
glDeleteFramebuffersEXT(1, &buffer_fbo);
glDeleteRenderbuffersEXT(1, &depthBuffer_rb);
glDeleteTextures(1,&bufferColtexture);
}
float g_potrotation = 0;
float g_potrotation_speed = 0.2f;
float xrot =0;
float yrot = 0;
float zrot = 0;
GLenum g_Drawbuffers[2] = {GL_COLOR_ATTACHMENT0_EXT };
void setupFBO(void)
{
// *********** set up scene FBO including dept buffers and their textures ****************
glGenFramebuffersEXT(1, &buffer_fbo);
// set up render buffers for depth info
glGenRenderbuffersEXT(1, &depthBuffer_rb);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer_rb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, win.width, win.height);
// Genrate texture to render to
glGenTextures(1, &bufferColtexture);
glBindTexture(GL_TEXTURE_2D, bufferColtexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, win.width, win.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// attach texture to render to to fbo
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, buffer_fbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, bufferColtexture, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer_rb);
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); // check frame buffer
if(status != GL_FRAMEBUFFER_COMPLETE_EXT)
{
printf("FRAMEBUFFER status error %i \n",status);
exit(1);
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // bind back to default
}
void initialise()
{
setupFBO();
// select projection matrix
glMatrixMode(GL_PROJECTION);
// set the viewport
glViewport(0, 0, win.width, win.height);
// set matrix mode
glMatrixMode(GL_PROJECTION);
// reset projection matrix
glLoadIdentity();
GLfloat aspect = (GLfloat) win.width / win.height;
// set up a perspective projection matrix
gluPerspective(win.field_of_view_angle, aspect, win.z_near, win.z_far);
// specify which matrix is the current matrix
glMatrixMode(GL_MODELVIEW);
glShadeModel( GL_SMOOTH );
// specify the clear value for the depth buffer
glClearDepth( 1.0f );
glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LEQUAL );
// specify implementation-specific hints
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
GLfloat amb_light[] = { 0.1, 0.1, 0.1, 1.0 };
GLfloat diffuse[] = { 0.6, 0.6, 0.6, 1 };
GLfloat specular[] = { 0.7, 0.7, 0.3, 1 };
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, amb_light );
glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse );
glLightfv( GL_LIGHT0, GL_SPECULAR, specular );
glEnable( GL_LIGHT0 );
glEnable( GL_COLOR_MATERIAL );
glShadeModel( GL_SMOOTH );
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE );
glDepthFunc( GL_LEQUAL );
glEnable( GL_DEPTH_TEST );
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glClearColor(0.5, 0.5, 0.5, 1.0);
}
void drawquad(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glDisable(GL_LIGHTING); // This was the cause of the problem, disable lighting worked!
glLoadIdentity(); // Reset The View
glTranslatef(0.0f,0.0f,-5.0f);
glTranslatef(0.0f,0.0f,-5.0f);
glRotatef(xrot,1.0f,0.0f,0.0f);
glRotatef(yrot,0.0f,1.0f,0.0f);
glRotatef(zrot,0.0f,0.0f,1.0f);
glBindTexture(GL_TEXTURE_2D, bufferColtexture);
glBegin(GL_QUADS);
// Front Face
glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f);
glEnd();
xrot+=0.3f;
yrot+=0.2f;
zrot+=0.4f;
glEnable(GL_LIGHTING); // now reenabling the lighting. after adding to fix code.
}
void display(void)
{
// set red background
// draw to fbo
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
// Clear Screen and Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
// set drawing a rotating cube as per default
glLoadIdentity();
// Define a viewing transformation
gluLookAt( 3,1,0, 0,0,0, 0,1,0);
// Push and pop the current matrix stack.
// This causes that translations and rotations on this matrix wont influence others.
glPushMatrix();
glColor3f(0,1,0);
glTranslatef(0,0,0);
glRotatef(g_potrotation,0,1,0);
glRotatef(90,0,1,0);
// Draw the solid cube
glutSolidCube(1);
glPopMatrix();
// draw teapot to fbo
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, buffer_fbo);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,depthBuffer_rb);
// Clear Screen and Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// Define a viewing transformation
gluLookAt( 4,2,0, 0,0,0, 0,1,0);
// Push and pop the current matrix stack.
// This causes that translations and rotations on this matrix wont influence others.
glPushMatrix();
glColor3f(1,0,0);
glTranslatef(0,0,0);
glRotatef(g_potrotation,0,1,0);
glRotatef(90,0,1,0);
// Draw the teapot
glutSolidTeapot(1);
glPopMatrix();
g_potrotation += g_potrotation_speed;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0); // reset to default Frame and Render buffer
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,0);
drawquad();
glutSwapBuffers();
}
// informs OpenGL that window size has changed.
void reshape(int width, int height)
{
}
void idle(void)
{
glutPostRedisplay();
}
int checkglewOK()
{
if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
printf("Ready for GLSL\n");
else {
printf("Not totally ready :( \n");
exit(1);
};
}
void keyboard (unsigned char key, int mousePositionX, int mousePositionY)
{
switch (key)
{
case KEY_ESCAPE:
exit (0);
break;
default:
break;
}
}
int main(int argc, char** argv)
{
// set window values
win.width = 640;
win.height = 480;
win.title = "Shader Test";
win.field_of_view_angle = 45;
win.z_near = 1.0f;
win.z_far = 500.0f;
////////////////////////////////////////////////////////
// Initialise and Create Window
////////////////////////////////////////////////////////
glutInit(&argc, argv);
// set modes RGB-Alpha, doble bufferedd (prevent flickering)
// has a depth buffer to ensure that 3D object overlp OK
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); // set display mode
// define window size
glutInitWindowSize(win.width, win.height);
glutCreateWindow(win.title); // create the window
glewInit(); // Glew Init occurs after Create Window !!!
checkglewOK();
glutDisplayFunc(display); // register display function
//glutReshapeFunc(reshape); // register resize function
glutIdleFunc(idle); // register idel function
glutKeyboardFunc(keyboard);
initialise();
glutMainLoop(); // run glut main loop
ShutDown();
return EXIT_SUCCESS;
}

How is Texture Splatting in OpenGL implemented?

I have been reading for a while the different techniques used to texture terrains and came across texture splatting. I have found a lot of articles that discuss how to do this in OpenGL, but most only discuss it theoretically and provide little to no code that I can study. Does anyone know/have some code that illustrates this in OpenGL?
Just to clarify, I want to be able to load four different textures, and based on the height of the quad/vertices, change the texture from one gradually to the next.
Edit: Below is a quick bit of code to help show what I want to know
#include <windows.h>
#include <SFML/Graphics.hpp>
#include <gl/gl.h>
#include <gl/glu.h>
#define GL_CLAMP_TO_EDGE 0x812F
class Scene {
public:
void resize( int w, int h ) {
// OpenGL Reshape
glViewport( 0, 0, w, h );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 120.0, (GLdouble)w/(GLdouble)h, 0.5, 500.0 );
glMatrixMode( GL_MODELVIEW );
}
};
int main() {
sf::RenderWindow window(sf::VideoMode(800, 600, 32), "Test");
///Setup the scene, materials, lighting
Scene scene;
scene.resize(800,600);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
glEnable(GL_COLOR_MATERIAL);
glShadeModel(GL_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LIGHT0);
float XL = .5, YL = .1, ZL = 1;
GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat diffuseLight[] = { 0.8f, 0.8f, 0.8, 1.0f };
GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat lightpos[] = {XL, YL, ZL, 0.};
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
///Test terrain texture splatting
///Load the textures
sf::Image tex1;
tex1.loadFromFile("texture1.png");
sf::Image tex2;
tex2.loadFromFile("texture2.png");
///Set the first texture
GLuint grass;
glGenTextures(1, &grass);
glBindTexture(GL_TEXTURE_2D, grass);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, tex1.getSize().x, tex1.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLvoid*)tex1.getPixelsPtr() );
///Set the second texture
GLuint dirt;
glGenTextures(1, &dirt);
glBindTexture(GL_TEXTURE_2D, dirt);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, tex2.getSize().x, tex2.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLvoid*)tex2.getPixelsPtr() );
///Start loop
while( window.isOpen() ) {
sf::Event event;
while( window.pollEvent( event ) ) {
if( event.type == sf::Event::Closed )
window.close();
}
///Clear buffer and set camera
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(50.0, 1.0, 1.0, 50);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1, 0, 1, 0, 0, 0, 0, 1, 0);
///Begin rendering quad
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, grass);
///I know that around here I should enable blending in order to get my two textures to mix, but I am not certain
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(-0.5, -0.5, 0.0);
glTexCoord2f(1, 0);
glVertex3f(-0.5, 0.5, 0.0);
glTexCoord2f(1, 1);
glVertex3f(0.5, 0.5, 0.0);
glTexCoord2f(0, 1);
glVertex3f(0.5, -0.5, 0.0);
glEnd();
///Reset env settings for SFML
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
window.display();
}
return 1;
}
As people mentioned above, use programmable pipeline, use shaders. In the fragment shader you can pass all the textures and interpolate between them based on vertex data you receive from the vertex shader.
Quick search gave me this result. I am sure that is what you need. Also take a look at this post. And this paper explains the technique very well.