If you look at this picture:
You can see that the left and right walls are brighter than the others, along with the faces of the chair.
I was wondering, is this an issue with the normals? Or would it potentially be just the position of the light illuminating these surfaces?
In my main method I just do this:
//enable lighting
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
//setup lighting
float lightColor [] = {1.0f, 0.8f, 0.8f,1.0f};
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, lightColor);
GLfloat lightpos[] = {2,2,4,4};
glLightfv(GL_LIGHT0,GL_POSITION, lightpos);
If you need to see the normals I can upload it but I'm not sure if it is a problem with them or not.
It seems your normals are not computed as they should. Notice how same direction sides of different objects are lit differently.
I would guess that:
you are not transforming the normals right when transforming your objects;
your normals are not normalized to unit length (do you have glEnable(GL_NORMALIZE) in your code?)
normals computation is wrong in some other way (e.g. you round the values before sending them to render).
It is hard to suggest more possible causes without seeing your actual code.
Related
I'm currently experimenting with opengl and glut.
As i have like no idea what i'm doing i totally mess up with the lighting.
The complete compilable file can be found here: main.c
I have a display loop which currently operates like following:
glutDisplayFunc(also idle func):
glClear GL_COLOR_BUFFER_BIT and GL_DEPTH_BUFFER_BIT
switch to modelview matrix
load identity
first Rotate and then Translate according to my keyboard and mouse inputs for the camera
draw a ground with glNormal 0,1,0 and glMaterial on front and back,
which is encapsulated by push/popmatrix
pushmatrix
translate
glutSolidTeapod
popmatrix
do lighting related things, glEnable GL_LIGHTING and LIGHT0 and passing
float pos[] = {0.1,0.1,-0.1,0.1};
glLightfv( GL_LIGHT0, GL_POSITION, pos );
swap the buffers
the function associated with
glutReshapeFunc operates(this is from the lighthouse3d.com glut tutorial):
calculate the ratio of the screen
switch to projection matrix
loadidentity
set the viewport
set the perspective
switch to modelview matrix
However this all seems to work somehow,
but as i enable lighting, the normals seem to totally mess up.
My GL_LIGHT0 seems to stay as it should, as i can see the lightspot on the ground
not moving, as i move around
And the Teapods texture seem to move if i move my camera,
the teapod itself stands still.
Here is some visual material to explain it,
i apologize for my bad english : /
Link to YouTube video describing visually
You have a series of mistakes in your code:
You don't properly set the properties of your OpenGL window:
glutCreateWindow (WINTITLE);
glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
The glutInitDisplayMode will only affect any windows you create after that. You should swap those two lines.
You never enable the depth test. You should add glEnable(GL_DEPTH_TEST) after you created the windows. Not using the depth test expalins the weird "see-through" effect you get with the teapot.
You have the following code
glEnable (GL_CULL_FACE | GL_CULL_FACE_MODE);
This is wrong in two ways: the GLenums are not single bits, but just values. You cannot OR them together and expect anything useful to happen. I don't know if this particular call will enable something you don't expect or just generate an error.
The second issue here is that GL_CULL_FACE_MODE isn't even a valid enum to enable.
In your case, you either skip the CULL_FACE completely, or you should write
glEnable (GL_CULL_FACE);
glFrontFace(GL_CW);
The latter call changes the face orientation from OpenGL's default counterclokcwise rule to the clockwise one, as the GLUT teapot is defined that way. Interestingly, your floor is also drawn following that rule, so it will fit for your whole scene. At least for now.
You have not fully understood how GL's state machine works. You draw the scene and then set the lighting. But this will not have an effect on the already drawn objects. It just affects the next time you draw something, which will be in the next frame here. Now, the lighting of the fixed function pipeline works in eye space. That means that if you want a light source which is located at a fixed position in the world, and not in a fixed position relativ to the camera, you have to re-specify the light position, with the updated modelview matrix, everytime the camera moves. In your case, the light source will lag behind one frame when the camera moves. This is probably not noticeable, but still wrong in principle. You should reorder your display() function to
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
control (WALKSPEED, MOUSESPEED, mousein);
lightHandler();
drawhelpgrid(1, 20);
drawTeapod();
glutSwapBuffers();
With those changes, I can actually get the expected result of a lighted teapot on my system. But as I side note I feel obligded to warn you that almost all of your code relies on deprecated features of OpenGL. This stuff has been removed from modern versions of OpenGL. If you start learning OpenGL now, you should consider learning the modern programmable pipeline, and not some decades old obsolete stuff.
I have a program that renders a 3D wire mesh model using this code fragment in a loop.
glBegin(GL_LINES);
glColor3f(.0f, 0.0f, 0.0f);
glVertex3d(xs,ys,zs);
glVertex3d(xe,ye,ze);
glEnd();
I need to add functionality so that the vertices where the line starts and ends can be rendered if the user desires, probably using a small shaded circle. The circle should be of a constant screen size, probably 4-6 pixels across and rendered at a size that is independent of where the camera is, or how close it is.
Can anyone suggest how to render such a vertex?
You can use GL_POINTS in your glBegin together with glPointSize function.
I have installed GLUT and Visual Studio 2010 and found some tutorials on OpenGL basics (www.opengl-tutorial.org) and 2D graphics programming. I have advanced knowledge in C but no expirience with graphics programming...
For project (astronomy - time scales) , i must create one object in center of window and make other 5 objects (circles,dots...) to rotate around centered object with respect to some equations (i can implement them and solve). Equations is for calculating coordinates of that 5 objects and all of equations have parameter t (as time). For creating animation i will vary parameter t from 0 to 2pi with some step and get coordinates in different moments. If task was to print new coordinates of objects it would be easy to me but problem is how to make animation of graphics. Can i use some functions of OpenGL for rotation/translation ? How to make an object to move to desired location with coordinates determined by equation? Or i can redraw object in new coordinates every millisecond? First thing i thought was to draw all objects, calculate new coordinates, clear screen and draw all objects in new coordinates and repeat that infinitely..(it would be primitive but will work?)
Here is screen shot of that objects - http://i.snag.gy/ht7tG.jpg . My question is how to make animation by calculating new coordinates of objects each step and moving them to new location. Can i do that with basics in OpenGL and good knowledge of C and geometry? Any ideas from what to start? Thanks
Or i can redraw object in new coordinates every millisecond? First
thing i thought was to draw all objects, calculate new coordinates,
clear screen and draw all objects in new coordinates and repeat that
infinitely..
This is indeed the way to go. I would further suggest that you don't bother with shaders and vertex buffers as is the OpenGL 3/4 way. What would be easiest is called "immediate mode", deprecated by OpenGL 3/4 but available in 1/2/3. It's easy:
glPushMatrix(); //save modelview matrix
glTranslatef(obj->x, obj->y, obj->z); //move origin to object center
glBegin(GL_TRIANGLES); //start drawing triangles
glColor3f(1.0f, 0.0f, 0.0f); //a nice red one
glVertex3f(0.0, +0.6f, 0.0f);
glVertex3f(-0.4f, 0.0f, 0.0f);
glVertex3f(+0.4f, 0.0f, 0.0f); //almost equilateral
glEnd();
glPopMatrix(); //restore modelview matrix/origin
Do look into helper libraries glu (useful for setting up the camera / the projection matrix) and glut (should make it very easy to set up a window and basic controls and drawing).
It would probably take you longer to set it up (display a rotating triangle) than to figure out how to use it. In fact, here's some code to help you get started. Your first challenge could be to set up a 2D orthogonal projection matrix that projects along the Z-axis, so you can use the 2D functions (glVertex2).
First thing i thought was to draw all objects, calculate new coordinates, clear screen and draw all objects in new coordinates and repeat that infinitely..(it would be primitive but will work?)
That's exactly how it works. With GLUT, you set a display function that gets called when GLUT thinks it's time to draw a new frame. In this function, clear the screen, draw the objects and flush it to the screen. Then just instruct GLUT to draw another frame, and you're animating!
Might want to keep track of the time inbetween frames so you can animate things smoothly, but I'm sure you can figure that part out.
OpenGL is really just a drawing library. It doesn't do animation, that's up to you to implement. Clear/draw/flush is the commonly used approach for it though.
Note: with 'flush' I mean glFlush(), although GLUT in multi-buffer mode requires glutSwapBuffers()
The red book explains the proper way to draw models that can first be translated, rotated, scaled and so on: http://www.glprogramming.com/red/chapter03.html
Basically, you load the identity, perform transforms/rotations/scales (which one you want first matters - again the book explains it), draw the model as though it was at the origin at normal scale and it'll be placed in its new position. Then you can load identity and proceed with the next one. Every frame of an animation, you glClear() and recalculate/redraw everything. (It sounds expensive, but there's usually not much you can cache between draws).
By (5, 5) I mean exactly the fifth row and fifth column.
I found it very hard to draw things using screen coordinates, all the coordinates in OpenGL is relative, and usually ranging from -1.0 to 1.0. Why it is so serious to prevent programmers from using screen coordinates / window coordinates?
The simplest way is probably to set the projection to match the pixel dimensions of the rendering space via glOrtho. Then vertices can be in pixel coordinates. The downside is that resizing the window could cause problems and you're mostly wasting the accelerated transforms.
Assuming a window that is 640x480:
// You can reverse the 0,480 arguments depending on you Y-axis
// direction preference
glOrtho(0, 640, 0, 480, -1, 1);
Frame buffer objects and textures are another avenue but you'll have to create your own rasterization routines (draw line, circle, bitmap, etc). There are problaby libs for this.
#dandan78 OpenGL is not a Vector Graphics renderer. Is a Rasterizer. And in a more precise way is a Standard described by means of a C language interface. A rasterizer, maps objects represented in 3D coordinated spaces (a car, a tree, a sphere, a dragon) into 2D coordinated spaces (say a plane, your app window or your display), these 2d coordinates belong to a discrete coordinated plane. The counter rendering method of rasterization is Ray Tracing.
Vector graphics is a way to represent by means of mathematical functions a set of curves, lines or similar geometrical primitives, in a nondiscrete way. So Vector graphics is in the "model representation" field rather than "rendering" field.
You can just change the "camera" to make 3D coordinates match screen coordinates by setting the modelview matrix to identity and the projection to an orthographic projection (see my answer on this question). Then you can just draw a single point primitive at the required screen coordinates.
You can also set the raster position with glWindowPos (which works in screen coordinates, unlike glRasterPos) and then just use glDrawPixels to draw a 1x1 pixel image.
glEnable( GL_SCISSOR_TEST );
glScissor( 5, 5, 1, 1 ); /// position of pixel
glClearColor( 1.0f, 1.0f, 1.0f, 0.0f ); /// color of pixel
glClear( GL_COLOR_BUFFER_BIT );
glDisable( GL_SCISSOR_TEST );
By changing last 2 arguments of glScissor you can also draw pixel perfect rectangle.
I did a bit of 3D programming several years back and, while I'm far from an expert, I think you are overlooking a very important difference between classical bitmapped DrawPixel(x, y) graphics and the type of graphics done with Direct3D and OpenGL.
Back in the days before 3D, computer graphics was mostly about bitmaps, which is to say collections of colored dots. These dots had a 1:1 relationship with the pixels on your monitor.
However, that had numerous drawbacks, including making 3D very difficult and requiring bitmaps of different sizes for different display resolutions.
In OpenGL/D3D, you are dealing with vector graphics. Lines are defined by points in a 3-dimensional coordinate space, shapes are defined by lines and so on. Surfaces can have textures, lights can be added, as can various types of lighting effects etc. This entire scene, or a part of it, can then be viewed through a virtual camera.
What you 'see' though this virtual camera is a projection of the scene onto a 2D surface. We're still dealing with vector graphics at this point. However, since computer displays consist of discrete pixels, this vector image has to be rasterized, which transforms the vector into a bitmap with actual pixels.
To summarize, you can't use screen/window coordinates because OpenGL is based on vector graphics.
I know I'm very late to the party, but just in case someone has this question in the future. I converted screen coordinates to OpenGL matrix coordinates using these:
double converterX (double x, int window_width) {
return 2 * (x / window_width) - 1;
}
double converterY (double y, int window_height) {
return -2 * (y / window_height) + 1;
}
Which are basically re-scaling methods.
I'm writing a 2D game using OpenGL. When I want to blit part of a texture as a sprite I use glTexCoord2f(u, v) to specify the UV co-ordinates, with u and v calculated like this:
GLfloat u = (GLfloat)xpos_in_texture/(GLfloat)width_of_texture;
GLfloat v = (GLfloat)ypos_in_texture/(GLfloat)height_of_texture;
This works perfectly most of the time, except when I use glScale to zoom the game in or out. Then floating point rounding errors cause some pixels to be drawn one to the right of or one below the intended rectangle within the texture.
What can be done about this? At the moment I'm subtracting an 'epsilon' value from the right and bottom edges of the rectangle, and it seems to work but this seems like a horrible kludge. Are there any better solutions?
Your issue is most likely not coming from rounding errors, but a misunderstanding on how OpenGL maps texels to pixels. If you notice off-by-one errors, it's probably because your UVs, your vertex positions or your projection matrix/viewport pair are not aligned to where they ought to be.
To simplify, I'll just talk about 1D, and be assuming you use a projection and a viewport that map X,Y coordinates to the equivalent pixel location (i.e. a glOrtho(0,width,0,height,zmin,zmax) and a glViewport(0,width,0,height).
Say you want to draw 5 texels (starting at 0 for simplicity) of your 64-wide texture showing on the 10 pixels (scale of 2) of your screen starting at pixel 20.
To get there, draw the triangle with X coordinates 20 and 30, and U (of the UV pair) of 10/64 and 15/64. The rasterization of OpenGL will generate 10 pixels to shade, with X coordinates 20.5, 21.5, ... 29.5. Note that the positions are not full integers. OpenGL rasterizes in the middle of the pixel.
Likewise, it will generate U coordinates of 10.25/64, 10.75/64, 11.25/64, 11.75/64 ... 14.25/64, 14.75/64. Note again that texel coordinates, brought back to texel positions in the texture space, are not full integers. OpenGL samples from the middle of texel locations, so this is fine.
How the samplers use these UVs to generate texel values depend on filtering modes, but be it nearest or linear, the pixels should be contained solely inside the texels of interest (0.25 with a size of 0.5 should only use color from 0 to 0.5, which is all inside the first texel).
In general, if you follow the general principles I laid out, you should never see artifacts.
Use Ortho and Viewport of exactly your frame buffer size
Use positions of X, X+width exactly
Use UVs that correspond to exactly the texels you want (if you want the 10 texels starting from the texel 0, use U=0 to U=10.
If you ever have a -1 somewhere in your math, it's likely not correct (for position or UVs).
To get back to your example, it's unclear how you link the uvs you compute to positions (since you don't show the position computation).
It's also unclear how you got xpos_in_texture (you should explain how you computed them for the corners of your sprite). My guess is that you computed that wrong.
A bit late, but for posterity I was having the same problem, with the pixels from adjacent regions of a texture atlas bleeding into sprites/tiles when scaling or zooming the view. I had my glOrtho, glViewport, etc dimensions all set correctly, then I realized the problem was I was scaling the view before translating the camera, which meant that even though I was snapping to integer pixels pre-zoom, after the zoom it would align to a fraction of a pixel and introduce the texel problem.
So if your code looks something like this, where camera.zoom is a non-integer (i.e. 0.75):
glScalef(camera.zoom, camera.zoom, 1.0f);
glTranslatef(camera.x, camera.y, 0.0f);
You'll want to make sure the result of the translation after scaling aligns to whole pixels on the screen, so you can do something like:
glScalef(camera.zoom, camera.zoom, 1.0f);
glTranslatef(
floor(camera.x * camera.zoom) / camera.zoom,
floor(camera.y * camera.zoom) / camera.zoom,
0.0f);
Do the division as a double, round the result down yourself to the desired level of precision, then cast it to GLFloat.
Your xpos/ypos must be based on 0 to (width or height) - 1 and then:
GLfloat u = (GLfloat)xpos_in_texture/(GLfloat)(width_of_texture - 1);
GLfloat v = (GLfloat)ypos_in_texture/(GLfloat)(height_of_texture - 1);