Repeating Textures in OpenGL - opengl

Hi i am quite new to OpenGL.
My task is to implement the GDI brushes in OpenGL for drawing on MAC OS X. Thus I turned to textures in OpenGL to first draw the pattern and then this needs to be mapped to drawing primitives such as a polygon (rectangle a case in point). I am creating a 8x8 texels texture and then mapping it on a polygon with co ordinates below on a 500x500 pixels window.
glVertex3f(0.35, 0.35, 0.0);
glVertex3f(0.35, 0.65, 0.0);
glVertex3f(0.65, 0.65, 0.0);
glVertex3f(0.65, 0.35, 0.0);
I since I need a brush effect the pattern must be repeated along the rectangle. The rectangle/square is 0.3 x 0.3 and the whole window is 500 x 500 then in terms of pixels the polygon is 150 x 150.
therefore repetitions required are 150/8
I therefore set the texture coordinates as follows:
glTexCoord2f(0.0, 0.0); glVertex3f(0.35, 0.35, 0.0);
glTexCoord2f(0.0, 150/8); glVertex3f(0.35, 0.65, 0.0);
glTexCoord2f(150/8, 150/8); glVertex3f(0.65, 0.65, 0.0);
glTexCoord2f(150/8, 0.0); glVertex3f(0.65, 0.35, 0.0);
I am having a problem that the vertical hatching (one texel transparent the other coloured) pattern I have created as a texture is not being appropriately mapped in the sense that some vertical lines are getting wider than others ( a sort of aliasing problem). Is it like this that I have to set the texture coordinates while mapping?
Thanks for any replies
al

If I'm understanding you correctly you're not treating the texture coordinates correctly. When using glTexCoord2f() the texture extends from 0.0, 0.0 to 1.0, 1.0. So if you want to have a texture that fills a quad you use the following:
glTexCoord2f(0.0f, 0.0f); glVertex3f(0.35f, 0.35f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0.35f, 0.65f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(0.65f, 0.65f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(0.65f, 0.35f, 0.0f);
And if you want to repeat the texture 8 times across the surface of the quad use 8.0f in place of the 1.0fs in the texCoords call. You'll also need to make sure that the texture is set to repeat when it is set once you've bound the texture.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
That's probably your problem, but if you're still having aliasing issues, try looking into glTexParameteri with GL_TEXTURE_MAG_FILTER and GL_TEXTURE_MAG_FILTER and mip-mapping.
It may be over a decade old, but this old Flipcode tutorial is still relevant and worth a look.
EDIT: Had vertex calls before texcoord calls

If the code you wrote is exactly what you have in your code, then 150/8 is your problem. This is an integer division, and will not return the floating point 18.75, but the integer 18.
Change your code to floating point values.
150.f/8.f

Related

Overlapping lines with OpenGl

I have two lines that cross each other and I have set the opacity for these lines to 0.7. Here's the code:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glLineWidth(7);
glBegin(GL_LINES);
glColor4f(0.9, 0.3, 0.4, 0.7);
glVertex2f(-1.0f, 0.8f);
glVertex2f(1.0f, 0.8f);
glEnd();
glLineWidth(10);
glBegin(GL_LINES);
glColor4f(0.9, 0.3, 0.4,0.7);
glVertex2f(-0.89f, -1.0f);
glVertex2f(-0.89f, 1.0f);
glEnd();
Here is the output of this:
Since the lines opacities are set to 0.7 the part where the lines intersect should have been a little darker than the rest of the line. How can I get that kind of effect?
So it was the depth test, makes sense. It just overwrote the same spot in the zbuffer. But the note about the premultiplied alpha still counts. Using the blender you specified originally you would have to multiply the rgb values by the alpha to get the color you wanted.

Why is my floor polygon not affected by specular and diffuse light?

I'm trying to light a scene with a few simple objects. I have two lights, one spot light and one point light and the lighting seems to work fine on the objects in the scene, but when it comes to the textured floor its only affected by ambient and I can't figure out why. I thought it had something to do with normals by I defined it as I think it should be, pointing up. if I remove the texture I get the same results.
what did I do wrong?
here is my code:
void drawFloor()
{
setMaterial(mat_specularFloor, mat_specularFloor, mat_specularFloor, mat_specularFloor);
//glColor3f(1.0, 1.0, 1.0);
glEnable(GL_TEXTURE_2D);
//glEnable(GL_NORMALIZE);
glBindTexture(GL_TEXTURE_2D, g_Texture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//glColor3f(.5, 0.5, 0.7);
glBegin(GL_TRIANGLE_FAN);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-50, 0, -50);
glTexCoord2f(10.0f, 0.0f);
glVertex3f( 50, 0, -50);
glTexCoord2f(10.0f, 10.0f);
glVertex3f( 50, 0, 50);
glTexCoord2f(0.0f, 10.0f);
glVertex3f(-50, 0, 50);
glEnd();
glDisable(GL_TEXTURE_2D);
}
I am not familiar with fixed function pipeline this can be fixed by using a newer version of opengl and using shaders for per pixel lighting.
One possible way to fix this is to subdivide the floor so it is made of many smaller sections.
Since opengl is running the calculation one for each vertex your light is being averaged out and if you were to subdivide it each section the light will have more impact on
ok so the main problem with my lighting was that it was just one giant polygon and because it was so big I didn't get any lighting at the vertices so there was nothing to interpolate.
Now I'm getting the diffuse lighting of the spotlight but I don't seem to get specular highlight.
Is it even possible to get a specular highlight on a plane?
If so, what else do I need to do to fix this? I need to make the floor look shiny.

fastest way to set every pixel

I have programmed a little raytracer in c++,
and want to show the raytraced image in a window.
I tried using a pixel buffer object in opengl,
then map the buffer into memory and manipulate the pixels one by one,
but at fullscreen resolution 1920x1080, I only get 4 fps
without raytracing and without changing the pixels colors
just the mapping and unmapping!
so i'm basically looking for the fastest way to display a raytraced image in a window.
i'm currently doing this way:
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, width * height * 4, 0, GL_STREAM_DRAW_ARB);
if (pixels = (uint*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB))
{
//modify pixels
glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB);
}
else
return;
//copy from pbo to texture
glBindTexture(GL_TEXTURE_2D, pbo_texture);
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, 0);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//draw image
glColor4f(1.0, 1.0, 1.0, 1.0);
glBindTexture(GL_TEXTURE_2D, pbo_texture);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, -1.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, -1.0, 0.0);
glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, 1.0, 0.0);
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, 1.0, 0.0);
glEnd();
glutSwapBuffers();
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
glBindTexture(GL_TEXTURE_2D, 0);
Check the memory traversal if you use loops. You should traverse your buffer in the right order, otherwise you may have cache miss at each iteration. If you use nested loops sometimes you only have to switch the x/y iteration order.
Also, don't read data from graphic memory. It tends to be slow. Only write to PBO.
It looks like a syncro issue. I'm not sure you need to map pbo at every frame. Check this link on OpenGL Pixel Buffer Object (PBO). There's also a workaround for stalls which could improve things

gl_lines and gl_clear in QGLWidget

I got a problem with drawing on a QGLWidget. I have several quads on the widget which I can move around when pressing some keys. As long as I just draw quads, everything works fine but now I want to add some lines using:
glBegin(GL_LINE);
glColor3f(c[0], c[1], c[2]);
glVertex3f(v1.x, v1.y, v1.z);
glVertex3f(v2.x, v2.y, v2.z);
glEnd;
The drawing also works fine, but the clearing of the glwidget doesn't work anymore. Means that I see everything I ever drawed on it. Just to mention.
I tried the same with GLUT using the same initializations and it worked, but since I have switched to Qt it doesn't work anymore.
paintGL(), resizeGL() and initializeGL() are below.
void GLWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0f, 0.0f, 0.0f, 0.0f, -10.0f, -20.0f, 0.0f, 20.0f, -10.0f);
glTranslatef(0.0f, -30.0f, -40.0f);
glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
glRotatef(s_deg, 0.0f, 0.0f, 1.0f);
glRotatef(s_deg2, cos(DEGRAD(s_deg)), sin(DEGRAD(s_deg)), 0.0f);
float colors[8][3] = {
0.5, 0.0, 0.0,
0.0, 0.5, 0.0,
0.0, 0.0, 0.5,
1.0, 0.5, 0.5,
0.5, 1.0, 0.5,
0.5, 0.5, 1.0,
0.9, 0.9, 0.9,
0.1, 0.1, 0.1,
}; //red, green, blue, red shiny, green shiny, blue shine, light grey, dark grey
for(int i=0;i<glBoxes.size();i++) {
glBoxes.at(i).setColor(colors[i]);
glBoxes.at(i).drawCuboid();
glBoxes.at(i).drawCuboidGrid();
}
}
void GLWidget::initializeGL() {
glDepthFunc(GL_LESS);
glClearColor(0.2, 0.2, 0.2, 0.2);
glClearDepth(1.0);
}
void GLWidget::resizeGL(int width, int height) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0.0f, 0.0f, (float)width, (float)height);
glLoadIdentity();
gluPerspective(45.0f, (float)width/(float)height, 0.5f, 100.0f);
glMatrixMode(GL_MODELVIEW);
}
any Ideas?
The tokens accepted by glBegin are
GL_POINTS
GL_LINES
GL_TRIANGLES
GL_TRIANGLE_FAN
GL_TRIANGLE_STRIP
GL_QUADS
GL_QUAD_STRIP
and
GL_POLYGON
The token used by you, GL_LINE (not the missing trailing S) is not valid for glBegin.
The statement glEnd; will evaluate the address of the function glEnd and silently discard the result. Could it be, that you have a Pascal or Delphi background? In C like languages you have to add a matched pair of parentheses to make it a function call. Functions that don't take a parameter are called with an empty pair of parentheses. E.g. in your case glEnd();.
Not related to your problem. All of the code in resizeGL should go to the head of paintGL (use the widget's width() and height() getters). Also what you have in initializeGL belongs to paintGL.
The proper use of initializeGL is to do one-time initialization, like loading textures, and shaders, preparing FBOs and such.
resizeGL is meant to re-/initialize stuff that depends on the window's size and which is quite time consuming to change, like renderbuffers and/or textures used as attachment in FBOs used for window sized post-processing or similar. Setting the projection matrix does not belong there, and neither does the viewport. Those go into paintGL.
glDepthFunc, glClearColor and glClearDepth directly influence the drawing process and as such belong with the drawing code.
Also you should not use the immediate mode (glBegin … glEnd) at all. It's been outdated ever since OpenGL-1.1 was released over 15 years ago. Use Vertex Arrays, with the possible addition of Buffer Objects.
glEnd; should be glEnd();. This may actually fix your problem.
GL_LINE isn't a valid token for glBegin. To draw lines, you need GL_LINES (that's subtle, and you're in good company - this is a common mistake).
GL_LINE is used to control how polygons are rendered, which is controlled by the glPolygonMode function.
It must be GL_LINES instead of GL_LINE. The symbols accepted by glBegin are plural (i.e. GL_QUADS, GL_LINE_STRIPS...).

glColor coloring all textures

I'm fairly new to OpenGL so maybe the answer will be obvious. I am currently trying to make a blue circle using GL_TRIANGLE_FAN in C++. My problem is that when I set the color using glColor4f, it sets all my other textures to have a blue color over them such as shown below (this is supposed to be silvery metal).
I draw the textures using the method shown below.
glLoadIdentity();
glTranslatef(x,y,0);
glBindTexture(GL_TEXTURE_2D, this->texture);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0,0,0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(width,0,0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(width,height,0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0,height,0);
glEnd();
I'm not sure whether I just have to clear a flag for it to work, but I've been stuck for a few days now.
After drawing your blue circle, you should set the color back to white (default value) using glColor4f(1.f, 1.f, 1.f, 1.f);. Please note that by default the texture gets modulated by the currently set color (blue in your case) and that's the reason why your silver material gets a bluish tone (final color = blue color * texture color).
Unbind the texture and set the color back to white after you're done drawing:
glLoadIdentity();
glTranslatef(x,y,0);
glEnable( GL_TEXTURE_2D );
glBindTexture(GL_TEXTURE_2D, this->texture);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0,0,0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(width,0,0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(width,height,0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0,height,0);
glEnd();
glColor4f(1, 1, 1, 1);
glBindTexture(GL_TEXTURE_2D, 0);
And if you aren't rendering textures on the next object, disable texturing:
glDisable( GL_TEXTURE_2D );
When You have enabled glEnable(GL_COLOR_MATERIAL) and changed a color by glColor, then all your textures will be affected by this color. This is because by default the texture is displayed in modulate mode (glColor multiplied by texture colors).
If you don't have lighting enabled, to restore the original texture color is simple - just set glColor to white: glColor4f(1.0, 1.0, 1.0, 1.0).
The problem comes, when you have lighting enabled on your texture. Then, setting the color to white or changing texture mode to REPLACE doesn't help at all - your lighting effects will be removed! (which nobody seems to be noticing!) The reason for this is because with enabling GL_COLOR_MATERIAL by default you're getting behaviour, where glColor commands changes both Ambient and Diffuse colours at the same time - thus your ambient and diffuse material properties will be affected (lost). So all you have to do, to restore the material state (and thus lighting effects), which you had before applying glEnable(GL_COLOR_MATERIAL), is the following:
glDisable(GL_COLOR_MATERIAL); //disable color influence
GLfloat ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f }; //default material has this ambient color!
GLfloat diffuse[] = { 0.8f ,0.8f ,0.8f, 1.0f }; //default material has this diffuse color!
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient); //restore default material ambient color
glMaterialfv(GL_FRONT, GL_AMBIENT, diffuse); //restore default material diffuse color
Please note, what are the default ambient and diffuse colors for default material! There is no pure white there!
This way, all the textures, that you use from this point will be drawn as intended (with the correct color and lighting effects).
Took me some time to find this stuff, so I suppose it's nice to mention it here.
Before binding a texture, you need to enable it. And normally, you should disabled it when you are done with it. Something like this :
glEnable( GL_TEXTURE_2D );
glBindTexture(GL_TEXTURE_2D, this->texture);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0,0,0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(width,0,0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(width,height,0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0,height,0);
glEnd();
glDisable( GL_TEXTURE_2D );