I called this function once per frame and it took my FPS from >400 to 33. Why?
sw blt(const PtRect *dstRect, Texture *src, const PtRect *srcRect, RenderDevice::bltFlags flags=RenderDevice::bltDefault)
{
assert(src);
GL_Texture *glsrc = dynamic_cast<GL_Texture*>(src);
if (glsrc == 0)
return -1;
PtRect srcRect2(0, 0, src->width, src->height);
if (srcRect == 0)
srcRect = &srcRect2;
PtRect dstRect2(0, 0, srcRect->makeWidth(), srcRect->makeHeight());
if (dstRect == 0)
dstRect = &dstRect2;
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, *glsrc->getTex());
glBegin( GL_QUADS );
glNormal3f( 0.0f, 0.0f, 1.0f );
for (size_t i=0; i<350; i++)
{
glTexCoord2f( srcRect->left /src->width, srcRect->top/src->height); glVertex2f(dstRect->left, dstRect->top);
glTexCoord2f( srcRect->right/src->width, srcRect->top/src->height); glVertex2f(dstRect->right, dstRect->top);
glTexCoord2f( srcRect->right/src->width, srcRect->bottom/src->height); glVertex2f(dstRect->right, dstRect->bottom);
glTexCoord2f( srcRect->left /src->width, srcRect->bottom/src->height); glVertex2f(dstRect->left, dstRect->bottom);
}
glEnd();
return 0;
}
Hard to say without more details, potential problems could be using a too large texture, causing software fallbacks in your driver. Also you appear to loop 350 times for no obvious reason.
You may be able to improve performance by building an array of data and then calling glDrawArrays instead of issuing each glTexCoord/glVertex pair individually
For performance you should load your textures in an init function and use a list to display then later on the main render function, for example:
// Generate texture object ID
glGenTextures(1, img);
glBindTexture(GL_TEXTURE_2D, img);
// Set Texture mapping parameters
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
LoadBMP("texture.bmp");
Then on the main render function you have something like:
// Front face of Cube
glBindTexture(GL_TEXTURE_2D, img);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-fSize, fSize, fSize);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-fSize, -fSize, fSize);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(fSize,-fSize, fSize);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(fSize,fSize, fSize);
glEnd();
As you can see you can wrap the texture on the parameters instead of repeating it over and over in a loop.
Maybe you are not using Textures with of a power of 2 (e.g. 1024x768 instead of 1024x512)?
It looks like you draw the quad onto the screen 350 times for some reason. If this is full screen, then texturing every pixel on the screen 350 times a frame is bound to damage your performance.
Related
I am new to GLFW and made a simple texture mapping program. Problem is while running the program the memory resource increases non stop which I can see clearly in taskmanager.
After running the program for a few minutes, my computer's fan speeds up and a heating problem occurs. How can I fix this problem?
Here is code for texture loading function
GLuint LoadTexture(const char* TextureName)
{
GLuint Texture; //variable for texture
glGenTextures(1,&Texture); //allocate the memory for texture
glBindTexture(GL_TEXTURE_2D,Texture); //Binding the texture
if(glfwLoadTexture2D(TextureName, GLFW_BUILD_MIPMAPS_BIT)){
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
return Texture;
}else return -1;
}
Here is code for draw function
void display()
{
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); //clear background screen to black
//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.0f,0.0f,-35.0f); //Translate whole scene to -ve z-axis by -35 unit
GLuint text2D;
text2D = LoadTexture("cicb.tga"); //loading image for texture
glEnable(GL_TEXTURE_2D); //Enable texture
glBindTexture(GL_TEXTURE_2D,text2D);//Binding texture
glPushMatrix();
glBegin(GL_POLYGON); //Begin quadrilateral coordinates
glNormal3f(0.0f, 0.0f, 1.0f);//normal vector
glTexCoord2f(0.0f, 0.0f); //Texture co-ordinate origin or lower left corner
glVertex3f(-10.0f,-11.0f,5.0f);
glTexCoord2f(1.0f, 0.0f); //Texture co-ordinate lower right corner
glVertex3f(10.0f,-11.0f,5.0f);
glTexCoord2f(1.0f, 1.0f);//Texture co-ordinate top right corner
glVertex3f(10.0f,-1.0f,-15.0f);
glTexCoord2f(0.0f, 1.0f);//Texture co-ordinate top left corner
glVertex3f(-10.0f,-1.0f,-15.0f);
glEnd(); //End quadrilateral coordinates
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,text2D);
glPushMatrix();
glBegin(GL_POLYGON);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);//Texture co-ordinate origin or lower left corner
glVertex3f(-10.0f,-1.0f,-15.0f);
glTexCoord2f(10.0f, 0.0f); //Texture co-ordinate for repeating image ten times form
//origin to lower right corner
glVertex3f(10.0f,-1.0f,-15.0f);
glTexCoord2f(10.0f, 10.0f);//repeat texture ten times form lower to top right corner.
glVertex3f(10.0f,15.0f,-15.0f);
glTexCoord2f(0.0f, 10.0f);//repeat texture ten time form top right to top left corner.
glVertex3f(-10.0f,15.0f,-15.0f);
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D); //Disable the texture
glfwSwapBuffers();
}
If anyone want to see the problem by running exe then I can provide download link.
You seem to be loading your texture each time you call display(). (Once per frame in essence) I assume that is what is taking all your memory at some point. You just want to do this once outside of your display function.
I'm rendering textures on the two surfaces which actually have the same location and position.
In these kind of cases I want to display only one of the textures, while I get following
I.e. I want only the texture of first material to be displayed.
So I would like to know where I've to search for solution, should I play with the blending of the materials ?
This is a pretty old issue (z-fighting) as the card isn't sure which object to draw in front. The linked Wikipedia article has more examples of this.
To fix this, increase the depth buffer's accuracy (bit depth), reduce the depth of your view (distance far/near clip plane) or add a tiny offset so the coordinates are no longer exactly (or almost) the same. You could as well simply disable the depth buffer (or clear it) for rendering this (in which case whatever is rendered last will overlap everything else).
You mean you want to display few textures at one time? Use multi texturing then. Attach both textures to one Quad using:
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.0f, 0.0f);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.0f, 0.0f);
And play with glTexEnvi to combine them as you want. If you want to show only one of your textures then draw two quads with separate textures on each of them. And quad witch will be drawn later will be visible. Then if you want to turn from one to another, make separate -(void)'s for each of quad, with glClearColor before each quad drawing and then make button to call for example -(void)quad1 and button to call -(void)quad2.
Or just use depth buffer.
At your situation i would use multi texturing, because all buffers looked too hard for me all time.
I will show how would my code look like.
Code using multi texture:
glClear(GL_COLOR_BUFFER_BIT);
//Turn on blending and set glBlendFunc for your needs
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//Describing multitexturing
glClientActiveTexture(GL_TEXTURE0_ARB); //Activating texture on unit 0
glActiveTexture(GL_TEXTURE0_ARB); //Activating texture on unit 0
glBindTexture(GL_TEXTURE_2D, Texture1); //Bind texture on unit 0
glEnable(GL_TEXTURE_2D); //Enable GL_TEXTURE_2D to set it's glTexEnvi for your needs
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE ); //Edit glTexEnvi for your needs (link bellow code)
glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_INTERPOLATE );
glClientActiveTexture(GL_TEXTURE1_ARB); //Activating texture on unit 1
glActiveTexture(GL_TEXTURE1_ARB); //Activating texture on unit 1
glBindTexture(GL_TEXTURE_2D, Texture2); //Bind texture on unit 0
glEnable(GL_TEXTURE_2D); //Enable GL_TEXTURE_2D to set it's glTexEnvi for your needs
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE ); //Edit glTexEnvi for your needs (link bellow code)
glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE );
//Drawing quad with multi texture
glBegin(GL_QUADS);
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.0f, 0.0f); //Texture on unit 0 coords
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.0f, 0.0f); //Texture on unit 1 coords
glVertex2f(0.0, 500);
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.0f, 1.0f); //Texture on unit 0 coords
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.0f, 1.0f); //Texture on unit 1 coords
glVertex2f(0.0, 0.0);
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1.0f, 1.0f); //Texture on unit 0 coords
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1.0f, 1.0f); //Texture on unit 1 coords
glVertex2f(800, 0.0);
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1.0f, 0.0f); //Texture on unit 0 coords
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1.0f, 0.0f); //Texture on unit 1 coords
glVertex2f(800, 500);
glEnd();
//Disable GL_TEXTURE_2D. We don't need it anymore
glDisable(GL_TEXTURE_2D);
//Disable blending
glDisable(GL_BLEND);
//Flush everything
glFlush();
Code for using one quad for each texture
-(void) drawQuad1
{
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, Texture1);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0, 500);
glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0, 0.0);
glTexCoord2f(1.0f, 1.0f); glVertex2f(800, 0.0);
glTexCoord2f(1.0f, 0.0f); glVertex2f(800, 500);
glEnd();
glDisable(GL_TEXTURE_2D)
glFlush();
}
-(void) drawQuad2
{
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, Texture2);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0, 500);
glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0, 0.0);
glTexCoord2f(1.0f, 1.0f); glVertex2f(800, 0.0);
glTexCoord2f(1.0f, 0.0f); glVertex2f(800, 500);
glEnd();
glDisable(GL_TEXTURE_2D)
glFlush();
}
//and now when you want to draw `drawQuad1` you need to do `[self drawQuad1];`
//and where you want to draw `drawQuad2` you need to do `[self drawQuad2];`
Info about glTexEnvi here. Its just sample code. Fast written so could have mistakes. Sorry if i forgot something. Just i haven't been doing it for long time. Written it on Mac OS X, so if you are using other platform maby you will have to change few things (not opengl). And about depth buffer? I don't know how to use it. So I can't explain it for you. Sorry. Never used them.
How i can disable lighting for only one of the textures in this multitexturing scheme? I tried to use glDisable(GL_LIGHTING) and glEnable(GL_LIGHTING) but it doesnt remember the settings when i render the quad.
Here is the code snippet:
glDisable(GL_LIGHTING);
glEnable(GL_BLEND);
glDisable(GL_TEXTURE_RECTANGLE_ARB);
glDisable(GL_TEXTURE_2D);
//------------------------
glActiveTextureARB(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, LIGHT_MAP); // texture with black/white
//------------------------
glActiveTextureARB(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, MY_TEXTURE); // normal texture
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_ADD);
glColor4f(1, 1, 1, 1);
glBegin(GL_QUADS);
glNormal3f(0,0,1);
glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f, 0.0f);
glMultiTexCoord2fARB(GL_TEXTURE1, 0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f, 1.0f);
glMultiTexCoord2fARB(GL_TEXTURE1, 0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 0.0f);
glMultiTexCoord2fARB(GL_TEXTURE0, 1.0f, 1.0f);
glMultiTexCoord2fARB(GL_TEXTURE1, 1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glMultiTexCoord2fARB(GL_TEXTURE0, 1.0f, 0.0f);
glMultiTexCoord2fARB(GL_TEXTURE1, 1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f);
glEnd();
glActiveTextureARB(GL_TEXTURE0);
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE1);
glDisable(GL_TEXTURE_2D);
Edit: the texture loading:
glGenTextures(1, &LIGHT_MAP);
glBindTexture(GL_TEXTURE_2D, LIGHT_MAP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
Weird thing is that when i enable lighting at the first line of code, i cant see the light_map texture rendered at all in the multitexture quad. Also the lighting doesnt seem to affect that quad at all, it works on other quads (which arent multitextured) in my app.
Any help appreciated.
Your first sentence does not make sense. GL Lighting happens at the vertex level. texturing, be it single texture or multitexture. happens way after. In more details:
The lighting that got computed per vertex is interpolated to each fragment, and that value is input to the texturing pipeline stage 0.
So... The lit color L comes in and gets combined with the texture on the texture stage 0 (your light map here), according to the texture environment of stage 0. You don't show how you set up the Texture environment for texture stage 0, so I can't tell you how it will pass down.
Then your output from stage 0 (computed from lighting and texture 0) get sent to the texture stage 1 input (where your "normal" texture is bound. That's called a diffuse texture). You use an environment of COMBINE with ADD on both RGB and ALPHA here, which is not typical of lightmapping: You're adding your lighting+lightmap to the diffuse color. Usually you want to multiply them (GL_TEXTURE_ENV_MODE=GL_MODULATE rather than GL_COMBINE).
Also, you did not set the SOURCE0_ALPHA and SOURCE1_ALPHA, so I'm not sure what exactly you add to generate the stage 1 ALPHA output.
All in all, I'd advise to write down exactly what you want as a result first (as math), and try to map that to the GL multitexturing pipeline.
Edit: Following your comments, if you don't specify stage 0 TexEnv, then you get the default:
GL_TEXTURE_ENV_MODE defaults to GL_MODULATE and GL_TEXTURE_ENV_COLOR
defaults to (0, 0, 0, 0).
So your color coming from the lighting is modulated with your lightmap (which may make sense depending on what you're trying to achieve). That gets added to your diffuse (where, as I said, it should probably get modulated instead).
None of these change what I said earlier: write down exactly what math you would like for your result. From that we can help find which texture environment you may need. But you did not say what result you want to achieve.
Good day.
I draw a scene with shadows using shadow maps method (when we're rendering scene from light point of view to retrieve depth buffer, making shadow texture and projecting it on the scene, rendered from a camera point of view)
As I use shadowmap texture, all other textured objects, of course, lose their texturing.
But I really DO want textured scene with shadows:)
I read about multitexturing, I actually tried to apply it, but failed.
What exactly should I do?
(I took code from OpenGl superbible)
Here is the main setup procedure's code. I marked new strings (those for multitexturing) with //<====
void SetupRC()
{
ambientShadowAvailable = GL_TRUE;
npotTexturesAvailable = GL_TRUE;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
fprintf(stdout, "Controls:\n");
fprintf(stdout, "\tRight-click for menu\n\n");
fprintf(stdout, "\tx/X\t\tMove +/- in x direction\n");
fprintf(stdout, "\ty/Y\t\tMove +/- in y direction\n");
fprintf(stdout, "\tz/Z\t\tMove +/- in z direction\n\n");
fprintf(stdout, "\tf/F\t\tChange polygon offset factor +/-\n\n");
fprintf(stdout, "\tq\t\tExit demo\n\n");
// Black background
glClearColor(0.32f, 0.44f, 0.85f, 0.5f );
// Hidden surface removal
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glPolygonOffset(factor, 0.0f);
// Set up some lighting state that never changes
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_NORMALIZE);
glEnable(GL_LIGHT0);
// Set up some texture state that never changes
glActiveTexture(GL_TEXTURE1); //<=====
glGenTextures(1, &shadowTextureID);
glBindTexture(GL_TEXTURE_2D, shadowTextureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
// if (ambientShadowAvailable)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB,
0.5f);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
::scene->fog->init();
RegenerateShadowMap();
}
Here is shadowmap generation procedure:
void RegenerateShadowMap(void)
{
GLfloat lightToSceneDistance, nearPlane, fieldOfView;
GLfloat lightModelview[16], lightProjection[16];
GLfloat sceneBoundingRadius = 200.0f; // based on objects in scene
// Save the depth precision for where it's useful
lightToSceneDistance = sqrt(lightPos[0] * lightPos[0] +
lightPos[1] * lightPos[1] +
lightPos[2] * lightPos[2]);
nearPlane = lightToSceneDistance - sceneBoundingRadius;
// Keep the scene filling the depth texture
fieldOfView = (GLfloat)m3dRadToDeg(2.0f * atan(sceneBoundingRadius / lightToSceneDistance));
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fieldOfView, 1.0f, nearPlane, nearPlane + (2.0f * sceneBoundingRadius));
glGetFloatv(GL_PROJECTION_MATRIX, lightProjection);
// Switch to light's point of view
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(lightPos[0], lightPos[1], lightPos[2],
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glGetFloatv(GL_MODELVIEW_MATRIX, lightModelview);
glViewport(0, 0, shadowWidth, shadowHeight);
// Clear the depth buffer only
glClear(GL_DEPTH_BUFFER_BIT);
// All we care about here is resulting depth values
glShadeModel(GL_FLAT);
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_NORMALIZE);
glActiveTexture(GL_TEXTURE0); //<=====
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE1); //<=====
glColorMask(0, 0, 0, 0);
// Overcome imprecision
glEnable(GL_POLYGON_OFFSET_FILL);
// Draw objects in the scene except base plane
// which never shadows anything
DrawModels(GL_FALSE);
// Copy depth values into depth texture
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
0, 0, shadowWidth, shadowHeight, 0);
// Restore normal drawing state
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_NORMALIZE);
glActiveTexture(GL_TEXTURE0); //<=====
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glColorMask(1, 1, 1, 1);
glDisable(GL_POLYGON_OFFSET_FILL);
// Set up texture matrix for shadow map projection,
// which will be rolled into the eye linear
// texture coordinate generation plane equations
M3DMatrix44f tempMatrix;
m3dLoadIdentity44(tempMatrix);
m3dTranslateMatrix44(tempMatrix, 0.5f, 0.5f, 0.5f);
m3dScaleMatrix44(tempMatrix, 0.5f, 0.5f, 0.5f);
m3dMatrixMultiply44(textureMatrix, tempMatrix, lightProjection);
m3dMatrixMultiply44(tempMatrix, textureMatrix, lightModelview);
// transpose to get the s, t, r, and q rows for plane equations
m3dTransposeMatrix44(textureMatrix, tempMatrix);
}
Scene render proc:
void RenderScene(void)
{
// Track camera angle
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (windowWidth > windowHeight)
{
GLdouble ar = (GLdouble)windowWidth / (GLdouble)windowHeight;
glFrustum(-ar * cameraZoom, ar * cameraZoom, -cameraZoom, cameraZoom, 1.0, 1000.0);
}
else
{
GLdouble ar = (GLdouble)windowHeight / (GLdouble)windowWidth;
glFrustum(-cameraZoom, cameraZoom, -ar * cameraZoom, ar * cameraZoom, 1.0, 1000.0);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(cameraPos[0], cameraPos[1], cameraPos[2],
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glViewport(0, 0, windowWidth, windowHeight);
// Track light position
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (showShadowMap)
{
// Display shadow map for educational purposes
glActiveTexture(GL_TEXTURE1); //<=====
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
// Show the shadowMap at its actual size relative to window
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(-1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex2f(((GLfloat)shadowWidth/(GLfloat)windowWidth)*2.0f-1.0f,
-1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex2f(((GLfloat)shadowWidth/(GLfloat)windowWidth)*2.0f-1.0f,
((GLfloat)shadowHeight/(GLfloat)windowHeight)*2.0f-1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex2f(-1.0f,
((GLfloat)shadowHeight/(GLfloat)windowHeight)*2.0f-1.0f);
glEnd();
glDisable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
gluPerspective(45.0f, 1.0f, 1.0f, 1000.0f);
glMatrixMode(GL_MODELVIEW);
}
else if (noShadows)
{
// Set up some simple lighting
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
// Draw objects in the scene including base plane
DrawModels(GL_TRUE);
}
else
{
if (!ambientShadowAvailable)
{
GLfloat lowAmbient[4] = {0.1f, 0.1f, 0.1f, 1.0f};
GLfloat lowDiffuse[4] = {0.35f, 0.35f, 0.35f, 1.0f};
// Because there is no support for an "ambient"
// shadow compare fail value, we'll have to
// draw an ambient pass first...
glLightfv(GL_LIGHT0, GL_AMBIENT, lowAmbient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lowDiffuse);
// Draw objects in the scene, including base plane
DrawModels(GL_TRUE);
// Enable alpha test so that shadowed fragments are discarded
glAlphaFunc(GL_GREATER, 0.9f);
glEnable(GL_ALPHA_TEST);
}
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
// Set up shadow comparison
glActiveTexture(GL_TEXTURE1); //<=====
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
GL_COMPARE_R_TO_TEXTURE);
// Set up the eye plane for projecting the shadow map on the scene
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);
glTexGenfv(GL_S, GL_EYE_PLANE, &textureMatrix[0]);
glTexGenfv(GL_T, GL_EYE_PLANE, &textureMatrix[4]);
glTexGenfv(GL_R, GL_EYE_PLANE, &textureMatrix[8]);
glTexGenfv(GL_Q, GL_EYE_PLANE, &textureMatrix[12]);
// Draw objects in the scene, including base plane
DrawModels(GL_TRUE);
//glPushMatrix();
//glScalef(1, -1, 1);
//DrawModels(GL_TRUE);
//glPopMatrix();
glDisable(GL_ALPHA_TEST);
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
glDisable(GL_TEXTURE_GEN_Q);
}
if (glGetError() != GL_NO_ERROR)
fprintf(stderr, "GL Error!\n");
//glBindTexture
// Flush drawing commands
glutSwapBuffers();
//RegenerateShadowMap();
}
And an example of textured object draw:
CTeapot::CTeapot(std::string fn, float s, float iX, float iY, float iZ)
{
this->setCoords(iX, iY, iZ);
this->size = s;
glActiveTexture(GL_TEXTURE0); //<=====
try
{
this->texture = new C2DTexture(fn);
}
catch(ERR::CError err)
{
throw err;
}
glActiveTexture(GL_TEXTURE1); //<=====
}
void CTeapot::draw()
{
glPushMatrix();
glTranslatef(this->coords[0], this->coords[1], this->coords[2]);
if(this->angle[0] != 0.0f)
glRotatef(this->angle[0], 1.0f, 0.0f, 0.0f);
if(this->angle[1] != 0.0f)
glRotatef(this->angle[1], 0.0f, 1.0f, 0.0f);
if(this->angle[2] != 0.0f)
glRotatef(this->angle[2], 0.0f, 0.0f, 1.0f);
glScalef(this->size, this->size, this->size);
glActiveTexture(GL_TEXTURE0); //<=====
//glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, this->texture->getGLTexture());
glutSolidTeapot(this->size);
glPopMatrix();
glActiveTexture(GL_TEXTURE1); //<=====
//glEnable(GL_TEXTURE_2D);
}
C2DTexture texture generaton proc:
C2DTexture::C2DTexture(std::string fn)
{
this->filename = fn;
this->imgTexture = auxDIBImageLoad(this->filename.c_str());
if(this->imgTexture == NULL)
throw ERR::CError(ERR::ERR_NOSUCHFILE, ERR::ERR_NOSUCHFILETEXT + this->filename);
// Creating a texture
glGenTextures(1, &this->glTexture);
glBindTexture(GL_TEXTURE_2D, this->glTexture);
// Setting filters
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 3, this->imgTexture->sizeX, this->imgTexture->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, this->imgTexture->data);
}
You tried to apply multi-texturing ? It does not show in your code. You do need to use it. One texture unit for the shadow texture, one for your diffuse map. If you tried, you should show the code with multi-texturing.
Multi-texturing is handled through glActiveTexture (and for fixed function that you seem to be using, glClientActiveTexture to handle the texture coordinates specifications).
Some pieces of advice:
it's easier to understand exactly what you're doing if you use shaders.
you want to map the depth texture to the texture unit 1: the setup of the texture unit for shadow mapping needs to be preceded by a glActiveTexture(GL_TEXTURE1) -- the BindTexture, the TexGen, and the texturing related Enable/Disable. Of course, you need to switch back to the texture unit 0 for the rest.
you don't want any texturing when you draw to the depth map.
It is faster to draw directly to the texture with the framebuffer_object extension, than to copy to it
Hope this helps.
Edit: Since you've changed quite a bit your question, let me add some pieces of advice and answers to your comments:
A single texture unit will always fetch from a single texture object. You use glActiveTexture followed by glBindTexture to specify which texture will be fetched from on that texture unit. Note that to get any texturing on that unit, you still need to call glEnable(GL_TEXTURE_2D) for that unit.
What to apply first... Well, this is where using shaders simplifies quite a lot the discussion. In general, the order of application completely depends on what fragment math you want to end up with. Let's put the following nomenclature:
T_0 the result of the first texture fetch,
T_1 the result of the second texture fetch.
C_f The input color that OpenGL computed and rasterized for this fragment (You're using the fixed function lighting, that's what I'm talking about)
C_o The final color of the fragment
T_s the result of the shadow texture fetch,
T_d the result of the diffuse texture fetch.
The result you'll get, with 2 texture units enabled, is something like
C_o = TexEnv1(TexEnv0(C_f,T_0), T_1)
The result you want is likely
C_o = C_f * T_s * T_d
What does that tell us ?
to implement the multiplications, you want modulate as your TexEnv for both texture unit 0 and texture unit 1
the order does not matter in this case (this is because the multiplication -aka modulation- is commutative)
what I showed is pretty much shader code. A lot easier to read than TexEnv settings.
Now to get back to your problem... At this point, I hope you understand what OpenGL state you should have come draw time. However, trying to know exactly what state you actually have from reading your code is a perilous exercise at best. If you are serious about using OpenGL, I recommend either of the following:
use an OpenGL debugger. There are a number of tools out there that will show the exact state at a specific draw call.
build your own debugging state tracking
dump the OpenGL state of interest at the time of the draw. OpenGL provides getter methods for every bit of its state (or almost, I won't go into the dirtiest details here), You want to do that only for debugging purposes, Getters are not guaranteed to be efficient at all).
I'm learning to use OpenGL in my free time, and I'm working on deferred rendering right now. I've been stuck on this problem for a few weeks. When I bind my diffuse texture to GL_TEXTURE0, each pixel in the texture is (0.0f, 0.0f, 0.0f, 0.0f). When I switch it to GL_TEXTURE3 it works. Where should I be looking to debug this problem?
I will post the draw call for the rendering below.
The entire source code is in this repository:
https://github.com/DanielSmithMichigan/OpenGLExperimentation
The act of writing and reading from different textures happens in here:
https://github.com/DanielSmithMichigan/OpenGLExperimentation/blob/master/OpenGlTest6/Defer.h
The draw call:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// if I switch GL_TEXTURE0 to GL_TEXTURE3
// and diffuseUniform << 0 to diffuseUniform << 3
// then it will work
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, diffuseTexture);
*diffuseUniform << 0;
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, positionTexture);
*positionUniform << 1;
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, normalsTexture);
*normalsUniform << 2;
*ambientColorUniform << objects->ambientLight->color;
*lightColorUniform << objects->sun->color;
*lightDirectionUniform << objects->sun->direction;
*cameraPositionUniform << objects->camera->position;
*specularColorUniform << objects->sun->color;
*specularPowerUniform << 5.0f;
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(1, 0);
glVertex3f((float)width, 0.0f, 0.0f);
glTexCoord2f(1, 1);
glVertex3f((float)width, (float)height, 0.0f);
glTexCoord2f(0, 1);
glVertex3f(0.0f, (float)height, 0.0f);
glEnd();
I was trying to say GL_TEXTURE1 with uniform = 1
Because I doubted a texture you made before the diffuse texture using glGenTextures(1, &depthBuffer) but I don't know why you made its name depthBuffer depthbuffer must be one of RBOs not a texture.
Anyway,
the default value of glactivetexture() is GL_TEXTURE0
You didn't call glactivetexture(GL_TEXTURE0) before you called glbindtexture(depthBuffer) although because the default value is GL_TEXTURE0, you are using GL_TEXTURE0 already for the depthBuffer .
The issue was that in the files Mesh.h and Grid.h, I was binding a sampler to index 0 (GL_TEXTURE0). This sampler was still bound by the time I was trying to bind/read my diffuse texture on index 0.
The solution was to use glActiveTexture(GL_TEXTURE0) and glEnable(GL_TEXTURE_2D) before I started my geometry pass, and the opposite glActiveTexture(GL_TEXTURE0) and glDisable(GL_TEXTURE_2D) after it ended.
Then in the draw call for my deferred rendering object, I use glBindSampler(0, 0).
As far as I can tell, all 5 functions mentioned above were necessary.
The fix for this problem is in commit hash d60fec483e896971304f5f9f24c4bd0f10fe48fe for anyone who needs more information.