I have to put illumination in a OpenGL picture but i don't know how to put a correct point light illumination like in the following picture:
For now i had tried different mode of illumination, but the result is the following :(
I attach you the code that I used for my result. What is wrong?
float specref[] = { 1.0f, 1.0f, 1.0f, 1.0f };
// Light values and coordinates
float ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f };
float diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f };
float specular[] = { 1.0f, 1.0f, 1.0f, 1.0f};
float lightPos[] = { 0.0f, -150.0f, -150.0f, 1.0f };
glEnable ( GL_LIGHTING ) ;
glLightfv(GL_LIGHT0,GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glEnable(GL_LIGHT0);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,specref);
glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,128);
glEnable ( GL_COLOR_MATERIAL ) ;
glClearColor (1.0, 1.0, 1.0, 1.0);
glColor3f(0.0,0.0,0.0);
Edit 04/11/2011 0.39 CET
I attach also my display() function called by glutDisplayFunc(display);
void display(void)
{
[...]
//Draw polygons in 3d
glColor3f(0.0,1.0,1.0);
glBegin(GL_QUADS);
for(i=0;i<NVERT-1;i++) {
for (j=0;j<NVERT-1;j++) {
glVertex3f( (GLfloat)((sb[i*NVERT+j]).x()),
(GLfloat)((sb[i*NVERT+j]).y()),
(GLfloat)((sb[i*NVERT+j]).z()));
glVertex3f( (GLfloat)((sb[i*NVERT+j+1]).x()),
(GLfloat)((sb[i*NVERT+j+1]).y()),
(GLfloat)((sb[i*NVERT+j+1]).z()));
glVertex3f( (GLfloat)((sb[(i+1)*NVERT+j+1]).x()),
(GLfloat)((sb[(i+1)*NVERT+j+1]).y()),
(GLfloat)((sb[(i+1)*NVERT+j+1]).z()));
glVertex3f( (GLfloat)((sb[(i+1)*NVERT+j]).x()),
(GLfloat)((sb[(i+1)*NVERT+j]).y()),
(GLfloat)((sb[(i+1)*NVERT+j]).z()));
}
}
glEnd();
glFlush();
}
In practice with display I write the small areas that compose the 2° figure that i represented (I omitted the algorithm for the calculation of the points of each area because is it working).
My goal is to have a result similar to figure 1 for the lightning and rendering of the figure but I only obtained the result in figure 2.
I don't know how to put correctly the light and how to setup my figure in order to have this render (like mirror).
You're missing normals. You either need to provide one normal per vertex (glNormal) or you could enable GL_AUTO_NORMALS if you use glMap2 (which you are not). There's an article on how to compute normals for a triangle or polygons on opengl.org that you probably will find useful.
Begin Function CalculateSurfaceNormal (Input Polygon) Returns Vector
Set Vertex Normal to (0, 0, 0)
Begin Cycle for Index in [0, Polygon.vertexNumber)
Set Vertex Current to Polygon.verts[Index]
Set Vertex Next to Polygon.verts[(Index plus 1) mod Polygon.vertexNumber]
Set Normal.x to Sum of Normal.x and (multiply (Current.y minus Next.y) by (Current.z plus Next.z))
Set Normal.y to Sum of Normal.y and (multiply (Current.z minus Next.z) by (Current.x plus Next.x))
Set Normal.z to Sum of Normal.z and (multiply (Current.x minus Next.x) by (Current.y plus Next.y))
End Cycle
Returning Normalize(Normal)
End Function
From the image you posted of the results it seems you are calculating and drawing the normals (red arrows), just not applying them.
Can't really figure out what's happening with your code. I hope your cordinates are between -1 to +1. I'd suggest you to work with lighting with simple primitives. the work on with your surface generation. The lighting source's position and calculating normals are the most important points.
http://www.falloutsoftware.com/tutorials/gl/gl8.htm
http://glprogramming.com/red/chapter05.html
Related
I followed a guide to draw a Lorenz system in 2D.
I want now to extend my project and switch from 2D to 3D. As far as I know I have to substitute the gluOrtho2D call with either gluPerspective or glFrustum. Unfortunately whatever I try is useless.
This is my initialization code:
// set the background color
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
/// set the foreground (pen) color
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);*/
// set the foreground (pen) color
glColor4f(1.0f, 1.0f, 1.0f, 0.02f);
// enable blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// enable point smoothing
glEnable(GL_POINT_SMOOTH);
glPointSize(1.0f);
// set up the viewport
glViewport(0, 0, 400, 400);
// set up the projection matrix (the camera)
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//gluOrtho2D(-2.0f, 2.0f, -2.0f, 2.0f);
gluPerspective(45.0f, 1.0f, 0.1f, 100.0f); //Sets the frustum to perspective mode
// set up the modelview matrix (the objects)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
while to draw I do this:
glClear(GL_COLOR_BUFFER_BIT);
// draw some points
glBegin(GL_POINTS);
// go through the equations many times, drawing a point for each iteration
for (int i = 0; i < iterations; i++) {
// compute a new point using the strange attractor equations
float xnew=z*sin(a*x)+cos(b*y);
float ynew=x*sin(c*y)+cos(d*z);
float znew=y*sin(e*z)+cos(f*x);
// save the new point
x = xnew;
y = ynew;
z = znew;
// draw the new point
glVertex3f(x, y, z);
}
glEnd();
// swap the buffers
glutSwapBuffers();
the problem is that I don't visualize anything in my window. It's all black. What am I doing wrong?
The name "gluOrtho2D" is a bit misleading. In fact gluOrtho2D is probably the most useless function ever. The definition of gluOrtho2D is
void gluOrtho2D(
GLdouble left,
GLdouble right,
GLdouble bottom,
GLdouble top )
{
glOrtho(left, right, bottom, top, -1, 1);
}
i.e. the only thing it does it calling glOrtho with default values for near and far. Wow, how complicated and ingenious </sarcasm>.
Anyway, even if it's called ...2D, there's nothing 2-dimensional about it. The projection volume still has a depth range of [-1 ; 1] which is perfectly 3-dimensional.
Most likely the points generated lie outside the projection volume, which has a Z value range of [0.1 ; 100] in your case, but your points are confined to the range [-1 ; 1] in either axis (and IIRC the Z range of the strange attractor is entirely positive). So you have to apply some translation to see something. I suggest you choose
near = 1
far = 10
and apply a translation of Z: -5.5 to move things into the center of the viewing volume.
i want to draw a rotating cube in the middle of the screen, and i want it to be lit by a light above it (i want it to look as if the cube was being lit from a fixed screen position). my problem is that i don't know how to prevent the light from rotating with the cube.
here's the code:
(SUMMARY: initGL, paintGL, and resizeGl are the functions that you always have to implement. in paintGL i use makeCube(). in makeCube() i use glBegin(GL_QUADS) to make a cube,and i use calcNormals() to calculate the normals of the cube )
-------------initGL--------------------------
angle=0.0;
glEnable (GL_DEPTH_TEST);
glEnable (GL_LIGHTING);
GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightPosition[]= { 0.0f, 1.5f,1.5f, 1.0f };
glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);
glLightfv(GL_LIGHT0, GL_POSITION,LightPosition);
glEnable (GL_LIGHT0);
--------------paintGL------------------
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -13.0);
glRotatef(angle,0.0f,1.0f,0.0f);
makeCube();
angle+=0.3;
--------------void makeCube()-------------------
float P[8][3]={ {-1,-1, 1},{1,-1, 1},{1,1, 1},{-1,1, 1},
{-1,-1,-1},{1,-1,-1},{1,1,-1},{-1,1,-1}};
float * planes[6][4] ={ {P[0],P[1],P[2],P[3]},
{P[1],P[5],P[6],P[2]},
{P[4],P[7],P[6],P[5]},
{P[0],P[3],P[7],P[4]},
{P[3],P[2],P[6],P[7]},
{P[0],P[4],P[5],P[1]}};
int i;
for(i=0;i<6;i++){
float *normal;
normal = calcNormal(planes[i][0],planes[i][1],planes[i][2]);
glBegin(GL_QUADS);
glNormal3f(normal[0], normal[1], normal[2]);
glVertex3f(planes[i][0][0],planes[i][0][1],planes[i][0][2]);
glVertex3f(planes[i][1][0],planes[i][1][1],planes[i][1][2]);
glVertex3f(planes[i][2][0],planes[i][2][1],planes[i][2][2]);
glVertex3f(planes[i][3][0],planes[i][3][1],planes[i][3][2]);
glEnd();
}
----------------float* calcNormal()----------------------
float vec1[3] = {P2[0]-P1[0],P2[1]-P1[1],P2[2]-P1[2]};
float vec2[3] = {P3[0]-P2[0],P3[1]-P2[1],P3[2]-P2[2]};
float cross[3] = {vec1[1]*vec2[2]-vec2[1]*vec1[2],
vec1[2]*vec2[0]-vec2[2]*vec1[0],
vec1[0]*vec2[1]-vec2[0]*vec1[1]};
float modCross = sqrt(cross[0]*cross[0]+cross[1]*cross[1]+cross[2]*cross[2]);
cross[0]/=modCross;
cross[1]/=modCross;
cross[2]/=modCross;
return cross;
-------------resizeGL--------------------------
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLfloat x = GLfloat(width) / height;
glFrustum(-x, +x, -1.0, +1.0, 4.0, 15.0);
glMatrixMode(GL_MODELVIEW);
It seems that you're transforming the position of the light in your paintGL section.
Looking over old code, I found an app in my code directory that loads and rotates .OBJ meshes, while allowing the light to be moved.
I think that the solution is to set the position of the light each frame. (Can't remember it's been over 18 months since I touched the project)
void idleFunc()
{
light(); /// *** I think you need to replicate this functionality ****
glPushMatrix();
myGluLookAt(0.0, -.50, -6.0, /* eye is at (0,0,5) */
0.0, 0.0, 0.0, /* center is at (0,0,0) */
0.0, 1.0, 0.); /* up is in positive Y direction */
transformFunc();
displayFunc();
glPopMatrix();
}
void displayFunc()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (useDrawList)
glCallList(DLid);
else
drawObj(loadedObj);
drawLight0(); // *** just displays an unlit sphere at the position of the light **
glutSwapBuffers();
frameCount++;
}
/* set the poition of each of the lights */
void light()
{
glLightfv(GL_LIGHT0, GL_POSITION, lightPos1);
glLightfv(GL_LIGHT1, GL_POSITION, lightPos2);
}
i solved this problem drawing the cube with VERTEX ARRAYS rather than DIRECT MODE, it seems that rotations or lights affect the object in a different way with each method, which is quite weird
For the lighting portion of an OpenGL project I'm doing this part for my team at the moment:
Define material properties for the models in Part 1. Make your material definitions easily
replaceable. Specifically, robot components and the remote control unit should be "shiny";
rubble piles should be defuse if various color shades; main platform tiles should be diffuse
gray. Select your own material properties and properly document them for the blocks, bases, factories, etc.
I've only been trying to apply the "shiny" effect on the control unit and it hasn't worked well. I tried putting in some sample lighting since we haven't put in any yet (or at least it's not in the repository) to test it out. The result is that the cube portions of the controller reflected (though way too white, no matter what I tried, the color of the cubes is grey) but not the cylinder antenna. (None of those tests are in the repository since I couldn't commit something that won't work.)
Basically I need help with material properties and setting up some basic lighting to test them (the test lighting is temporary since one of my teammates is working on lighting).
I would really appreciate if someone could help me out with doing this part.
Project info:
Repository for our project (a Visual Studio 2010 Project)
The map/grid lies along the xz plane with y being the height
Everything is done using either glCubes or glut shapes so no normals need to be defined for those, only some of the tiles and the numbers 4 everywhere are done using gl_quads
If I missed anything or if you need more info please ask!
I'll help you with the basics on lightning in OpenGL... first you need to enable and set your lights, so, here is some example:
void setlight(){
//here you set the lights and parameters, example with one light
float LightAmbient[] = { 0.1f, 0.1f, 0.05f, 1.0f };
float LightEmission[] = { 1.0f, 1.0f, 0.8f, 1.0f };
float LightDiffuse[] = { 1.0f, 1.0f, 0.8f, 1.0f };
float LightSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
float LightDirection[]={-0.5f, -0.5f, -0.5f};
glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, LightSpecular);
glLightfv(GL_LIGHT0, GL_POSITION, LightDirection);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
void setmaterial(){
//here you set materials, you must declare each one of the colors global or locally like this:
float MatAmbient[] = { 0.1f, 0.1f, 0.1f, 1.0f };
float MatDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
float MatSpecular[] = { 0.1f, 0.1f, 0.0f, 0.1f };
float MatShininess = 60;
float black[] = {0.0f,0.0f,0.0f,1.0f};
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, MatAmbient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MatDiffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, MatSpecular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, MatShininess);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
}
void render(){
//your render function
//clean buffers, set viewport, projection, lookat, etc...
. . .
//set light and materials
setlight();
setmaterial();
//draw your stuff
. . .
glutSwapBuffers();
}
Now, if you need to set different materials for differents object to draw you must set the materials for each object before you draw them... example:
for(int i=0; i<num_objetcs; i++){
setmaterial(i);
drawobject(i);
}
Of course, you have to modify what I wrote before... You just have to set the light and then for each object you set their material and then draw, one by one. You must modify the "setmaterial" function to take the material parameter and I suppose you know what to do for the rest... good luck!
So I have begun learning OpenGL, reading from the book "OpenGL Super Bible 5 ed.". It's explains things really well, and I have been able to create my first gl program myself! Just something simple, a rotating 3d pyramid.
Now for some reason one of the faces are not rendering. I checked the vertecies (plotted it on paper first) and it seemed to be right. Found out if I changed the shader to draw a line loop, it would render. However it would not render a triangle. Can anyone explain why?
void setupRC()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
shaderManager.InitializeStockShaders();
M3DVector3f vVerts1[] = {-0.5f,0.0f,-0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,-0.5f};
M3DVector3f vVerts2[] = {-0.5f,0.0f,-0.5f,0.0f,0.5f,0.0f,-0.5f,0.0f,0.5f};
M3DVector3f vVerts3[] = {-0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,0.5f};
M3DVector3f vVerts4[] = {0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,-0.5f};
triangleBatch1.Begin(GL_LINE_LOOP, 3);
triangleBatch1.CopyVertexData3f(vVerts1);
triangleBatch1.End();
triangleBatch2.Begin(GL_TRIANGLES, 3);
triangleBatch2.CopyVertexData3f(vVerts2);
triangleBatch2.End();
triangleBatch3.Begin(GL_TRIANGLES, 3);
triangleBatch3.CopyVertexData3f(vVerts3);
triangleBatch3.End();
triangleBatch4.Begin(GL_TRIANGLES, 3);
triangleBatch4.CopyVertexData3f(vVerts4);
triangleBatch4.End();
glEnable(GL_CULL_FACE);
}
float rot = 1;
void renderScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
GLfloat vRed[] = {1.0f, 0.0f, 0.0f, 0.5f};
GLfloat vBlue[] = {0.0f, 1.0f, 0.0f, 0.5f};
GLfloat vGreen[] = {0.0f, 0.0f, 1.0f, 0.5f};
GLfloat vWhite[] = {1.0f, 1.0f, 1.0f, 0.5f};
M3DMatrix44f transformMatrix;
if (rot >= 360)
rot = 0;
else
rot = rot + 1;
m3dRotationMatrix44(transformMatrix,m3dDegToRad(rot),0.0f,1.0f,0.0f);
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vRed);
triangleBatch1.Draw();
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vBlue);
triangleBatch2.Draw();
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vGreen);
triangleBatch3.Draw();
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vWhite);
triangleBatch4.Draw();
glutSwapBuffers();
glutPostRedisplay();
Sleep(10);
}
You've most likely defined the vertices in clockwise order for the triangle that isn't showing, and in counterclockwise order (normally the default) for those that are. Clockwise winding essentially creates an inward facing normal and thus OpenGL won't bother to render it when culling is enabled.
The easiest way to check this is to set glCullFace(GL_FRONT)--that should toggle it so you see the missing triangle and no longer see the other three.
The only thing I see that affects polygons here is glEnable(GL_CULL_FACE);.
You shouldn't have that, because if you plot your vertices backwards, the polygon won't render.
Remove it or actually call glDisable(GL_CULL_FACE); to be sure.
In your case, it's not likely that you want to draw a polygon that you can see from one side only.
This is a simple issue that I'm somewhat ashamed to ask for help on.
I'm making a simple call to gluSphere to render a sphere, however, it does not light properly even though I'm pretty sure I added the normals and lighting correctly. If, however, I add a texture, the model lights normally, except it seems to be always SMOOTH, and I cannot change it to flat.
This is the lighting code in my init() function:
gl.glLightfv( GL.GL_LIGHT0, GL.GL_AMBIENT , AMBIENT_LIGHT, 0 );
gl.glLightfv( GL.GL_LIGHT0, GL.GL_DIFFUSE , DIFFUSE_LIGHT, 0 );
gl.glLightfv( GL.GL_LIGHT0, GL.GL_POSITION, light_pos , 0 );
gl.glEnable ( GL.GL_LIGHT0 );
gl.glEnable ( GL.GL_LIGHTING );
this is my sphere code in my display() function:
gl.glColor3d(1.0, 1.0, 1.0);
glu.gluQuadricDrawStyle (quad, GLU.GLU_FILL);
glu.gluQuadricNormals (quad, GLU.GLU_FLAT);
glu.gluQuadricOrientation(quad, GLU.GLU_OUTSIDE);
glu.gluSphere(quad, 1.0, lat, lon);
Please advise.
EDIT:
light values:
public final static float[] DIFFUSE_LIGHT = { 1.0f, 1.0f, 1.0f, 1.0f };
public final static float[] AMBIENT_LIGHT = { 0.3f, 0.3f, 0.3f, 1.0f };
public float[] light_pos = { -2.0f, 2.0f, 10.0f, 0.0f };
added materials, no change:
gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT , new float[]{0.5f, 0.5f, 0.5f, 1.0f}, 0);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE , new float[]{1.0f, 1.0f, 1.0f, 1.0f}, 0);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, new float[]{0.7f, 0.7f, 0.7f, 1.0f}, 0);
gl.glMaterialf (GL.GL_FRONT, GL.GL_SHININESS, 0.5f);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_EMISSION, new float[]{0.3f, 0.3f, 0.3f, 0.0f}, 0);
EDIT2:
Blah, I figured i had a:
gl.glEnable(GL.GL_TEXTURE_2D);
active somewhere and it was causing my model not to have shading if there was no texture associated with it. -_- carry on good people, carry on.
I encountered lighting problem too and figured out that i need to add glEnable(GL_NORMALIZE).
What kind of lighting are you expecting? The third parameter to glLightfv is supposed to be the values of the light you are setting.
Are there any translations/rotations you do that may affect the position of the light?
Is GL_COLOR_MATERIAL enabled or disabled? It may overwrite your material settings if it is.
Even if your code is not enabling GL_TEXTURE_2D, you should try disabling it manually right before the line is reached, just in case.
If you wish to ignore gluSphere completely, there's some code in this thread that you can use.