Related
I'm trying to write something in OpenGL, and I'm a beginner so sorry for any mistakes I make.
in general I just wanted to draw two triangles with different colours and I did using the following code:
float vertices[] = {
-0.5f, -0.6f, 0.0f,
0.5f, -0.6f, 0.0f,
0.4f, 0.5f, 0.0f,
0.5f, 0.6f, 0.0f,
-0.5f, 0.6f, 0.0f,
-0.4f, -0.5f, 0.0f
};
void display() {
std::cout << "frame";
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer
// activate and specify pointer to vertex array
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
// draw a cube
glColor3f(1.0f, 0.0f, 0.0f); // Red
glDrawArrays(GL_TRIANGLES, 0, 3);
//glColor3f(0.0f, 1.0f, 0.0f); // Green
glDrawArrays(GL_TRIANGLES, 3, 3);
glDisableClientState(GL_VERTEX_ARRAY);
glFlush(); // Render now
}
int main(int argc, char** argv) {
glutInit(&argc, argv); // Initialize GLUT
glutCreateWindow("OpenGL Setup Test"); // Create a window with the given title
glutInitWindowSize(320, 320); // Set the window's initial width & height
glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
glutDisplayFunc(display); // Register display callback handler for window re-paint
glutMainLoop(); // Enter the infinitely event-processing loop
return 0;
}
now.. if I . want to draw both triangles in the same command I can do
glDrawArrays(GL_TRIANGLES, 0, 6);
but then it draws the two triangles in the same colour.
is there a way to draw each triangle in a different colour by still using only one glDrawArrays() command?
if not.. is there some other command I should go for ?
thank you
In the description of glDrawArrays it is written :
Instead of calling a GL procedure to pass each individual vertex attribute, you can use glVertexAttribPointer to prespecify separate arrays of vertices, normals, and colors and use them to construct a sequence of primitives with a single call to glDrawArrays.
Is that your solution ?
"if not.. is there some other command I should go for ?" Fixed function attributes and client-side capability is deprecated since decades.See Fixed Function Pipeline and Legacy OpenGL.
Read about Vertex Specification and Shader for a state of the art way of rendering.
Anyway you can define an array of color attributes by glColorPointer, so each vertex coordinate is associated to an individual color attribute:
float colors[] = {
1.0f, 0.0f, 0.0f, // red
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, // green
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_FLOAT, 0, colors);
glDrawArrays(GL_TRIANGLES, 0, 6);
I am Trying to Render 3 textures,
-Background
-Black/White Foreground Mask
-Foreground
I have used this OpenGL - mask with multiple textures
because it acurately descirbes my problem. But i can not get it to work. I only get the Last rendererd Texture, in this case the Foreground. I have called glutInitDisplayMode(GLUT_ALPHA); to get Alpha rendering as sugested in the Answer.
Can anyone spot errors from my side?
My code is as follows:
double stretch = ((double)m_videoResY * (double)m_depthResX) / ((double)m_videoResX * (double)m_depthResY);
glEnable(GL_BLEND);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(+0.5, -0.5, +0.5, -0.5, 0.001f, 1.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -0.5f);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glDisable(GL_DEPTH_TEST);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBlendFunc(GL_ONE, GL_ZERO);
glBindTexture(GL_TEXTURE_2D, m_backgroundTexture);//Draw BGTexture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-0.5f, -0.5f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-0.5f, 0.5f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(0.5f, 0.5f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(0.5f, -0.5f, 0.0f);
glEnd();
glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ZERO);
//mask with userID
glBindTexture(GL_TEXTURE_2D, m_userIDTexture);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-0.5f, -0.5f, 0.0f);
glTexCoord2f(1.0f, 1.0f * stretch);
glVertex3f(-0.5f, 0.5f, 0.0f);
glTexCoord2f(0.0f, 1.0f * stretch);
glVertex3f(0.5f, 0.5f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(0.5f, -0.5f, 0.0f);
glEnd();
//blend with Video of User
glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
glBindTexture(GL_TEXTURE_2D, m_videoTexture);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-0.5f, -0.5f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-0.5f, 0.5f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(0.5f, 0.5f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(0.5f, -0.5f, 0.0f);
glEnd();
I suppose your mistakes are:
When you drawing your background with glBlendFunc(GL_ONE, GL_ZERO);
As result you normaly draw it in framebuffer, but providing no needed blending operation, more effective on this pass is don't use blending at all. So, more effective is glDisable(GL_BLEND), but your pass work here like you expect.
At second pass you drawing with glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ZERO); I don't know why you using so sofisticated function here and separatively blend colors and alpha values.
So, looking on third pass, I suppose you want to modify your background alpha value by your foreground black/white color mask. If It's true, you must use glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_ZERO, GL_SRC_COLOR); - Yep, little mistake.
And at third pass when you drawing foreground you have glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA), what means you wanna draw those regions, where your black/white mask was white and blending with attenuation for more darker mask regions.
If you have any questions about glBlendFunc, I can help you.
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.
I want to be able to render something into a texture, on OpenGL, so I can further use it whenever I want, without rendering everything over again. This website here gave me the guidelines to do it, without using the FrameBuffer. I don't want to do it with the FrameBuffer Object due to compatibility issues, since this old machine is not supporting it. I have done some code, which creates my texture, renders my scene, and I then create a Quad to render the texture on it. The only problem is that the texture is being rendered like an "Alpha Mask", it means, looks like it's only taking into account the Alpha Value, maintaining my rectangle always with the same color, but just changing the transparency on pixels. Here is some code I've done so far:
void CreateTexture ()
{
xSize = 512;
ySize = 512; //size of texture
//new array
char* colorBits = new char[ xSize * ySize * 3 ];
//texture creation..
glGenTextures(1,&texture);
glBindTexture(GL_TEXTURE_2D,texture);
glTexImage2D(GL_TEXTURE_2D,0 ,3 , xSize,
ySize, 0 , GL_RGB,
GL_UNSIGNED_BYTE, colorBits);
//you can set other texture parameters if you want
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//clean up
delete[] colorBits;
}
Then:
int viewport[4];
glGetIntegerv(GL_VIEWPORT,(int*)viewport);
glViewport(0,0,xSize,ySize);
DrawScene(hDC);
//save data to texture using glCopyTexImage2D
glBindTexture(GL_TEXTURE_2D,texture);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
0,0, xSize, ySize, 0);
glClearColor(.0f, 0.5f, 0.5f, 1.0f); // Set The Clear Color To Medium Blue
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(viewport[0],viewport[1],viewport[2],viewport[3]);
// glBindTexture(GL_TEXTURE_2D,texture);
And Finally:
glEnable(GL_TEXTURE_2D); // Enable 2D Texture Mapping
glBlendFunc(GL_DST_COLOR,GL_ONE); // Set Blending Mode
glEnable(GL_BLEND);
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D,texture);
glRotatef(theta, 0.0f, 0.0f, 0.01f);
glBegin(GL_QUADS);
//Front Face
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-0.5, -0.5f, 0.5f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 0.5f, -0.5f, 0.5f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f( 0.5f, 0.5f, 0.5f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glEnd();
SwapBuffers(hDC);
The DrawScene() function simply renders a rectangle with a triangle on top of it, with each vertice having different colors.. nothing special.
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT );//| GL_DEPTH_BUFFER_BIT);
glPushMatrix();
// glRotatef(theta, 0.0f, 0.0f, 1.0f);
glBegin(GL_QUADS);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex2f(0.0f, 1.0f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex2f(0.87f, -0.5f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2f(-0.87f, -0.5f);
glEnd();
glPopMatrix();
I've found something on nVidia website which looks useful, for someone who cannot also do offscreen rendering with FBO:
http://developer.download.nvidia.com/SDK/9.5/Samples/samples.html
This website contains one project called "Simple P-Buffer", which basically contains an implementation of a P-buffer. The idea of the sample is that you make context switching to the pBuffer, while you want to draw pixels on offscreen mode, let's say. After drawing your scene with the normal rendering functions, we use glReadPixels to read the data from the pBuffer into an array of unsigned bytes (GLubyte). After that, we do context-switching once again, setting it back to the screen context, so that you can use glReadPixels to read the content from our array.
The method before FBOs were available was to use an alternate render buffer (see glDrawBuffer(GL_AUX0), then copy pixels from that buffer (see glReadBuffer) to the texture (see glCopyTexImage2D. Rendering directly into a texture requires FBOs.
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;
}