how can i create the full-screen effect with a texture image ?
till now i do this :
static void Draw(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-5.0f);
texture[0] = SOIL_load_OGL_texture // load an image file directly as a new OpenGL texture
(
"my_img.jpg",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_POLYGON);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
glutSwapBuffers();
}
this code places my image in the top-left position of the screen, but i would like the full-screen texture effect.
So, How can i accomplish that ?
As #BrettHale already suggested in the comment, just set all the matrices to the identity transformation:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Then get rid of any other transformations you have in place, like the glTranslatef() call you currently have in the code. Use 0.0f instead of 1.0f for the last coordinate of your vertices, and you should be good to go.
ok , I did it , and now it works. for a full-screen image i added this function
void resize(int height, int width) {
const float ar = (float) widthX / (float) heightY;
glViewport(0, 20, widthX, heightY);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar+1, ar-1, -1.0, 1.0, 2.0, 90.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity() ;
}
make sure to add this :
glutReshapeFunc(resize); // calling the "resize function"
I'm currently porting a game of which the code is very obfuscated due to porting from C to Java.
My problem is that some users report a black screen and no other problems (sound is working fine e.g.), with no errors showing a problem. On my pc it runs fine, and it makes for a hell of debugging.
I was wondering if anyone can post a (list of) reason(s) this might be occurring. I've read somewhere one of the issues could be using a 32 bits Java on a 64 bits system.
My code below, also opensourced at: https://code.google.com/p/jake2t/
private void renderSideBySide() {
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sbsFboId);
// Render side by side
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, width, 0, height);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glViewport(0,0,width,height);
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
glDisable(GL_CULL_FACE);
int shaderId = sbsShader.getId();
glDisable(GL_TEXTURE_2D);
ARBShaderObjects.glUseProgramObjectARB(shaderId);
if (postFboTextureLocation[0] < 0) {
postFboTextureLocation[0] = ARBShaderObjects.glGetUniformLocationARB(shaderId, "leftTexture");
}
if (postFboTextureLocation[1] < 0) {
postFboTextureLocation[1] = ARBShaderObjects.glGetUniformLocationARB(shaderId, "rightTexture");
}
if (postFboDepthTextureLocation[0] < 0) {
postFboDepthTextureLocation[0] = ARBShaderObjects.glGetUniformLocationARB(shaderId, "leftDepthTexture");
}
if (postFboDepthTextureLocation[1] < 0) {
postFboDepthTextureLocation[1] = ARBShaderObjects.glGetUniformLocationARB(shaderId, "rightDepthTexture");
}
// Load the images with the colors and the depth values
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, postFboTextureId[0]);
ARBShaderObjects.glUniform1iARB(postFboTextureLocation[0], 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, postFboTextureId[1]);
ARBShaderObjects.glUniform1iARB(postFboTextureLocation[1], 1);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, postFboDepthTexture[0]);
ARBShaderObjects.glUniform1iARB(postFboDepthTextureLocation[0], 2);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, postFboDepthTexture[1]);
ARBShaderObjects.glUniform1iARB(postFboDepthTextureLocation[1], 3);
glBegin (GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex2i (0, 0);
glTexCoord2f(1.0f, 0.0f);
glVertex2i (width, 0);
glTexCoord2f(1.0f, 1.0f);
glVertex2i (width, height);
glTexCoord2f(0.0f, 1.0f);
glVertex2i (0, height);
glEnd();
ARBShaderObjects.glUseProgramObjectARB(0);
// Rendering with warping
glPopMatrix();
glPopAttrib();
unbindFBO();
}
public void drawPostFBOs() {
renderSideBySide();
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, width, 0, height);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glViewport(0,0,width,height);
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
glClear (GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_TEXTURE_2D);
int shaderId = riftShader.getId();
ARBShaderObjects.glUseProgramObjectARB(shaderId);
if (sbsFboTextureLocation < 0) {
sbsFboTextureLocation = ARBShaderObjects.glGetUniformLocationARB(shaderId, "tex");
}
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, sbsFboTextureId);
ARBShaderObjects.glUniform1iARB(sbsFboTextureLocation, 0);
glBegin (GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex2i (0, 0);
glTexCoord2f(1.0f, 0.0f);
glVertex2i (width, 0);
glTexCoord2f(1.0f, 1.0f);
glVertex2i (width, height);
glTexCoord2f(0.0f, 1.0f);
glVertex2i (0, height);
glEnd();
ARBShaderObjects.glUseProgramObjectARB(0);
glPopMatrix();
glPopAttrib();
}
The common problems that OpenGL 3+ programmer doesn't consider when coding are:
OpenGL Extensions
use of ARB and EXT extension.
use of correct OGL extension.
use multiple implementation of different OGL extensions. Here is an example using C++:
#ifndef _MESA_INVERT_
/*** ... some codes here ... ***/
#else
/*** ... alt some codes here ... ***/
#endif
Check if the video card support the following extension using:
glxinfo - Linux and MacOS X based system.
glview - Windows based system.
I am working on a n-body code with "glut functions" display. I would like to display each body with a 2D texture from a bmp image. Currently, I can draw a single textured element with the following code :
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Clear The Screen And The Depth Buffer
glBindTexture(GL_TEXTURE_2D, texture[0]); // pick the texture.
glBegin(GL_QUADS); // begin drawing the textured quad.
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd(); // done drawing the textured quad.
In the first version of my code, I draw the positions of each body with the following display function :
void drawPoints()
{
GLuint vbo;
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexPointer(4, GL_DOUBLE, 4*sizeof(double), pos);
glEnableClientState(GL_VERTEX_ARRAY);
if (colorVBO) {
glBindBuffer(GL_ARRAY_BUFFER, id_colorVBO);
glColorPointer(4, GL_DOUBLE, 4*sizeof(double), pos);
glEnableClientState(GL_COLOR_ARRAY);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
glColor3f(1, 1, 0);
glDrawArrays(GL_POINTS, 0, numBodies);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
where pos array contains the coordinates x, y, z of each body. I am using glDrawArrays function to draw all the points at the same time.
Could you tell me how to plot all the textured elements and not only one, i.e a way to use the coordinates pos array for indicate the positions of all the textured bodies and draw them.
Updated :
ok, I try to use glTexCoordPointer with the following display function :
void drawPoints()
{
glPushMatrix();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Clear The Screen And The Depth Buffer
glBindTexture(GL_TEXTURE_2D, texture[0]); // pick the texture.
glLoadIdentity(); // reset the view before we draw each star.
glTranslatef(0.0f, 0.0f, zoom); // zoom into the screen.
glEnableClientState(GL_VERTEX_ARRAY);
lEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(4, GL_DOUBLE, 4*sizeof(double), pos);
glTexCoordPointer(4, GL_DOUBLE, 4*sizeof(double), pos);
// Assign A Color Using Bytes
glColor4ub(30, 100, 120, 255);
glBegin(GL_QUADS); // Begin Drawing The Textured Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd(); // Done Drawing The Textured Quad
glDrawArrays(GL_QUADS, 0, numBodies);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
}
but only one textured element is displayed.
Anyone sees what's wrong ?
In addition to glVertexPointer, you should use glTexCoordPointer. Do not forget to enable the corresponding client state, GL_TEXTURE_COORD_ARRAY. There is also a complete example on the official wiki, with interleaved attributes.
Note that the new (3.0+) way is to use glVertexAttribPointer along with shaders. There's a very descriptive page on the wiki on that, as well.
Recently I have been looking into OpenGL, and I've got up to the stage were I want to texture things. I thought I would start with texturing a simple cube.
I currently have this code, and understand fully how it works:
#include <glut.h>
#define WINDOW_WIDTH 400
#define WINDOW_HEIGHT 400
float angle = 30.0f;
void Draw() {
glLoadIdentity(); //Reset the drawing perspective
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Clears the buffers
//Add positioned light
GLfloat lightColor0[] = {0.5f, 0.5f, 0.5f, 1.0f}; //Color intensity
GLfloat lightPos0[] = {0.0f, 0.0f, 0.0f, 1.0f}; //Positioned at..
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0); //Set our light colour
glLightfv(GL_LIGHT0, GL_POSITION, lightPos0); //Set our light position
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 200);
glRotatef(angle,1.0f,1.0f,1.0f); //Rotate around the origin
glScalef(0.4f, 0.4f, 0.4f); //Scale the shape down
glBegin(GL_QUADS); //Start drawing a Quad
glColor3f(1.0f,0.0f,0.0f); //Set the colour to Red
glVertex3f( 1.0f, 1.0f,-1.0f); //Top right of the quad (Top Face)
glVertex3f(-1.0f, 1.0f,-1.0f); //Top left of the quad (Top Face)
glVertex3f(-1.0f, 1.0f, 1.0f); //Bottom left of the quad (Top Face)
glVertex3f( 1.0f, 1.0f, 1.0f); //Bottom right of the quad (Top Face)
glVertex3f( 1.0f,-1.0f, 1.0f); //Top right of the quad (Bottom Face)
glVertex3f(-1.0f,-1.0f, 1.0f); //Top left of the quad (Bottom Face)
glVertex3f(-1.0f,-1.0f,-1.0f); //Bottom left of the quad (Bottom Face)
glVertex3f( 1.0f,-1.0f,-1.0f); //Bottom right of the quad (Bottom Face)
glVertex3f( 1.0f, 1.0f, 1.0f); //Top right of the quad (Front Face)
glVertex3f(-1.0f, 1.0f, 1.0f); //Top left of the quad (Front Face)
glVertex3f(-1.0f,-1.0f, 1.0f); //Bottom left of the quad (Front Face)
glVertex3f( 1.0f,-1.0f, 1.0f); //Bottom right of the quad (Front Face)
glVertex3f( 1.0f,-1.0f,-1.0f); //Top right of the quad (Back Face)
glVertex3f(-1.0f,-1.0f,-1.0f); //Top left of the quad (Back Face)
glVertex3f(-1.0f, 1.0f,-1.0f); //Bottom left of the quad (Back Face)
glVertex3f( 1.0f, 1.0f,-1.0f); //Bottom right of the quad (Back Face)
glVertex3f(-1.0f, 1.0f, 1.0f); //Top right of the quad (Left Face)
glVertex3f(-1.0f, 1.0f,-1.0f); //Top left of the quad (Left Face)
glVertex3f(-1.0f,-1.0f,-1.0f); //Bottom left of the quad (Left Face)
glVertex3f(-1.0f,-1.0f, 1.0f); //Bottom right of the quad (Left Face)
glVertex3f( 1.0f, 1.0f,-1.0f); //Top right of the quad (Right Face)
glVertex3f( 1.0f, 1.0f, 1.0f); //Top left of the quad (Right Face)
glVertex3f( 1.0f,-1.0f, 1.0f); //Bottom left of the quad (Right Face)
glVertex3f( 1.0f,-1.0f,-1.0f); //Bottom right of the quad (Right Face)
glEnd(); //Finished Drawing The Quad
glutSwapBuffers(); //Send the 3D scene to the screen
}
void Update(int value){ //Our update function
angle+=0.5f; //Increase the angle by 5
if(angle>360){ //If the angle is greater than 360
angle=0; //Set the angle to 0
}
glutPostRedisplay(); //Tell it that the scene has changed
glutTimerFunc(25,Update,0); //Call "Update" again in another 25ms
}
void Initialize() {
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING); //Enable lighting
glEnable(GL_LIGHT0); //Enable light No. 0
glEnable(GL_NORMALIZE); //Automatically "normalize" normals
glShadeModel(GL_SMOOTH); //Enable smooth shading (nice effect)
glClearColor(0.0, 0.0, 0.0, 0.0); //Background RGBA
glMatrixMode(GL_MODELVIEW); //MODELVIEW view
glLoadIdentity(); //Start at origin
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); //Set the scale
//X axis = 0 to 1. Y = 0 to 1. Z = -1 to 1.
}
int main() {
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); //The display mode
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); //Window Size
glutInitWindowPosition(200, 200); //Window Position
glutCreateWindow("Lighting!"); //Creates a window with the name "Lighting!"
Initialize(); //Call our initialize function.
glutDisplayFunc(Draw); //"Draw" then refresh the window
glutTimerFunc(25,Update,0); //Call "Update" 25ms after program starts
glutMainLoop(); //Process events etc. Also keeps the window open.
return 0; //End the program
}
However after reading many, MANY texturing tutorials (I mean literally all of the ones I could find on the web); I'm still confused about how I would add it to this program.
I know that I have to load the texture (somehow) and then bind it using the glBindTexture function before I draw the cube, but I think there is something else I need to do in-between (and I don't know how to load the image properly either).
For loading texture files (png, jpg...) use this:
(don't forget to install SDL and SDL_image libraries)
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
GLuint texture_alloc(const char *tex_name, int alpha)
{
GLuint tex_num;
SDL_Surface *tex_img;
glGenTextures(1, &tex_num);
if(tex_img = (SDL_Surface *) IMG_Load(tex_name)) {
glBindTexture(GL_TEXTURE_2D, tex_num);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
if (alpha==1)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_img->w, tex_img->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_img->pixels);
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_img->w, tex_img->h, 0, GL_RGB, GL_UNSIGNED_BYTE, tex_img->pixels);
SDL_FreeSurface (tex_img);
}
return tex_num;
}
For setting texture coordinates use glTexCoord function:
glTexCoord2f(0.0f, 0.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
.
.
.
I recommend looking at SOIL, an OpenGL image loading library - its what I use.
As far as getting a texture working, its pretty much:
Unsigned int texture = SOIL_load_OGL_texture(imagePath.c_str(), SOIL_CREATE_NEW_ID, SOIL_LOAD_AUTO, SOIL_FLAG_MIPMAPS);
glBindTexture(texture);
You do however have to use texture co-ordinates so that opengl knows how to wrap your texture. Heres some sample calls that render cube.
int size = 1;
// Begin Rending
glBegin(GL_QUADS);
{
// Face 1
glNormal3f( 0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f( m_size, m_size,-m_size);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-m_size, m_size,-m_size);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-m_size, m_size, m_size);
glTexCoord2f(0.0f, 1.0f);
glVertex3f( m_size, m_size, m_size);
// Face 2
glNormal3f( 0.0f, 0.0f,-1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f( m_size,-m_size, m_size);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-m_size,-m_size, m_size);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-m_size,-m_size,-m_size);
glTexCoord2f(0.0f, 1.0f);
glVertex3f( m_size,-m_size,-m_size);
// Face 3
glTexCoord2f(0.0f, 0.0f);
glVertex3f( m_size, m_size, m_size);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-m_size, m_size, m_size);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-m_size,-m_size, m_size);
glTexCoord2f(0.0f, 1.0f);
glVertex3f( m_size,-m_size, m_size);
// Face 4
glNormal3f( 0.0f,-1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f( m_size,-m_size,-m_size);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-m_size,-m_size,-m_size);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-m_size, m_size,-m_size);
glTexCoord2f(0.0f, 1.0f);
glVertex3f( m_size, m_size,-m_size);
// Face 5
glNormal3f( 1.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-m_size, m_size, m_size);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-m_size, m_size,-m_size);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-m_size,-m_size,-m_size);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-m_size,-m_size, m_size);
// Face 6
glNormal3f( 1.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f( m_size, m_size,-m_size);
glTexCoord2f(1.0f, 0.0f);
glVertex3f( m_size, m_size, m_size);
glTexCoord2f(1.0f, 1.0f);
glVertex3f( m_size,-m_size, m_size);
glTexCoord2f(0.0f, 1.0f);
glVertex3f( m_size,-m_size,-m_size);
}
glEnd();
I think the part your missing is the concept of texture coordinates.
Textures are 2d right? So, when you're pushing the 3d points of your object to the graphics card, if you want it textured you also need to associate that 3d point with a position in a texture image which you do with a pair of texture coordinates (pair because textures are 2d)... Take a look at glTexCoord2f()... If you make a call to that right before a call to glVertex3f() you'll associate that 3d point with a point in the image... If you do that for all the points that make up a primitive opengl can interpolate for all the points in between...
For image loading you can also use the SDL-image Library:
http://www.libsdl.org/projects/SDL_image/
It is very handy.
You can use the glaux code from the http://nehe.gamedeve.net/ this also is pretty simple.
AUX_RGBImageRec* LoadBMP(char* Filename)
{
FILE *File = NULL;
if ( !Filename )
return NULL;
File = fopen(Filename,"r");
if ( !Filename )
return NULL;
fclose(File);
return auxDIBImageLoad(Filename);
}
int LoadTextures()
{
int Status = FALSE;
AUX_RGBImageRec *TextureImage[1];
memset(TextureImage,0,sizeof(void*)*1);
if ( TextureImage[0] = LoadBMP("GoneFishing.bmp") )
{
Status = true;
if(texture[0] == -1)
glGenTextures(1,&texture[0]);
glBindTexture(GL_TEXTURE_2D,texture[0]);
// Generate The Texture
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering
}
if (TextureImage[0]) // If Texture Exists
{
if (TextureImage[0]->data) // If Texture Image Exists
{
free(TextureImage[0]->data); // Free The Texture Image Memory
}
free(TextureImage[0]); // Free The Image Structure
}
return Status;
}
A have a question, maybe someone can help me.
I am trying to make a mirror effect using OpenGL. I draw a transparent plane, a "reflected" scene cut by stencil, and an original one.
But I have a completely non-transparent "wall" instead of the mirror. I know it happens because of the first mirror plane rendering (to get a stencil buffer). But I don't know what to do with this:(
Here is the code:
void CMirror::draw(CSceneObject * curscene)
{
glPushMatrix();
glClearStencil(0.0f);
glClear(GL_STENCIL_BUFFER_BIT);
//Draw into the stencil buffer
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glStencilFunc(GL_ALWAYS, 1, 0);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glEnable(GL_STENCIL_TEST);
glPushMatrix();
glTranslatef(this->coords[0], this->coords[1], this->coords[2]);
glScalef(this->size, this->size, this->size);
glColor4f(1, 0, 1, 0);
glBegin(GL_QUADS);
glVertex3f(0.0f, this->height / 2.0f, this->width / 2.0f);
glVertex3f(0.0f, this->height / -2.0f, this->width / 2.0f);
glVertex3f(0.0f, this->height / -2.0f, this->width / -2.0f);
glVertex3f(0.0f, this->height / 2.0f, this->width / -2.0f);
glEnd();
glPopMatrix();
glDisable(GL_STENCIL_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
//glClear(GL_COLOR_BUFFER_BIT);
//Draw the scene
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_EQUAL, 1, 255);
glPushMatrix();
glTranslatef( 2*this->coords[0], 2*this->coords[1], 2*this->coords[2]);
glScalef(-1.0f, 1.0f, 1.0f);
((CScene*)curscene)->draw();
glColor4f(0.0f, 0.30f, 0, 0.9);
((CScene*)curscene)->spline->draw();
((CScene*)curscene)->morph->draw();
glPopMatrix();
glDisable(GL_STENCIL_TEST);
//the mirror itself:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glPushMatrix();
glTranslatef(this->coords[0], this->coords[1], this->coords[2]);
glScalef(this->size, this->size, this->size);
glColor4f(0, 0, 0, 0.9);
glBegin(GL_QUADS);
glVertex3f(0.0f, this->height / 2.0f, this->width / 2.0f);
glVertex3f(0.0f, this->height / -2.0f, this->width / 2.0f);
glVertex3f(0.0f, this->height / -2.0f, this->width / -2.0f);
glVertex3f(0.0f, this->height / 2.0f, this->width / -2.0f);
glEnd();
glPopMatrix();
glDisable(GL_BLEND);
glPopMatrix();
}
What happens if you don't do that last draw (i.e. if the problem is still there, remove it as it complicates the example)?
One thing that's clear is that you don't seem to handle anything Z-buffer related.
When you draw your first quad to set the stencil, assuming Z-write is on, you end up setting the Z-values to your mirror Z. Drawing the scene that is supposed to be reflected in the mirror will be Z-rejected.
You need to clear the Z buffer for that region of the screen somehow. Obviously, a full Clear(DEPTH_BIT) can work but it depends on what you've already drawn on your screen.
Likewise, not updating the Z-buffer when updating the stencil can work depending on whether anything has been drawn there before.