I am building a simple Wavefront Obj file loader and renderer in Java, using JOGL. However, whenever I am loading a simple bunny test mesh, it's rendering in a glitchy fashion, and I have no idea what could be causing it. I am just using geometry vertices and normals, no textures or materials.
The following is the GL initialization code from the init() method:
gl.setSwapInterval(1);
gl.glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
gl.glEnable(GL2.GL_DEPTH_TEST);
gl.glDepthFunc(GL2.GL_LESS);
gl.glEnable(GL2.GL_CULL_FACE);
gl.glCullFace(GL2.GL_BACK);
gl.glShadeModel(GL2.GL_SMOOTH);
gl.glClearDepth(1.0d);
And this is the method that I'm using to render the model (fixed pipeline, for now):
gl.glBegin(GL2.GL_TRIANGLES);
for(Face face : master.faces) {
for(int i = 0; i < face.points.length; i++) {
gl.glNormal3f(face.normals[i].x, face.normals[i].y, face.normals[i].z);
gl.glVertex3f(face.points[i].x, face.points[i].y, face.points[i].z);
}
}
gl.glEnd();
Where master is the main "group" that contains all the faces and vertices. I've checked - everything goes into the master group, and glNormal3f and glVertex3f get called for every needed vertex in every triangle.
Can anyone tell what could be causing those glitches?
Edit 1:
Here is the code I'm using to set the projection and modelview matrices up:
float aspect = (float) width / (float) height;
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(60.0f, aspect, 0.01f, 100.0f);
glu.gluLookAt(2.0f, 1.0f, 1.5f,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f);
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
try removing
gl.glDepthFunc(GL2.GL_LESS);
gl.glClearDepth(1.0d);
Well, it seemed like this was being caused by a silly little bug in my object loader.
When parsing my input vertices, it would chomp the first character of all the x coordinates of the geometry vertices. This didn't affect the positive values, since they were all normalized and 0.43 = .43, but it messed up all negative values causing them to be interpreted as positive.
It took me a while to figure that out, but I eventually found it and it just goes to show that the tiniest errors can be incredibly tricky to track down.
Related
just doing some tinkering with lwjgl and making some 2d shapes. Not sure what I'm doing wrong but I'm not able to show more than the first green square on screen. Here is the code for my window loop function:
private void loop() {
// This line is critical for LWJGL's interoperation with GLFW's
// OpenGL context, or any context that is managed externally.
// LWJGL detects the context that is current in the current thread,
// creates the GLCapabilities instance and makes the OpenGL
// bindings available for use.
GL.createCapabilities();
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glOrtho(0, vidmode.width(),0, vidmode.height(),-1,1);
// Set the clear color
glClearColor(.0f, 0.6f, 0.6f, 0.0f);
// Run the rendering loop until the user has attempted to close
// the window or has pressed the ESCAPE key.
while (!glfwWindowShouldClose(window) && !dataH.isGameOver()) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer
glBegin(GL_QUADS);
{
glColor3f(0.1f, 1.0f, 0.1f); // Green
glVertex2d(xMapCentre - 100,yMapCentre - 100);
glVertex2d(xMapCentre - 100,yMapCentre + 100);
glVertex2d(xMapCentre + 100,yMapCentre + 100);
glVertex2d(xMapCentre + 100,yMapCentre - 100);
glColor3f(0.2f, 0.2f, 0.2f); // Dark Gray
glVertex2f(-0.9f, -0.7f);
glColor3f(1.0f, 1.0f, 1.0f); // White
glVertex2f(-0.5f, -0.7f);
glColor3f(0.2f, 0.2f, 0.2f); // Dark Gray
glVertex2f(-0.5f, -0.3f);
glColor3f(1.0f, 1.0f, 1.0f); // White
glVertex2f(-0.9f, -0.3f);
}
glEnd();
glBegin(GL_TRIANGLES); // Each set of 3 vertices form a triangle
{
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex2f(0.1f, -0.6f);
glVertex2f(0.7f, -0.6f);
glVertex2f(0.4f, -0.1f);
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex2f(0.3f, -0.4f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex2f(0.9f, -0.4f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex2f(0.6f, -0.9f);
}
glEnd();
glfwSwapBuffers(window); // swap the color buffers
// Poll for window events. The key callback above will only be
// invoked during this call.
glfwPollEvents();
}
}
Any help would be appreciated, and let me know if I'm being too vague. Thanks.
Generally, when rendering 2D structures in 3D space, you should disable the back-face culling glDisable(GL_CULL_FACE). Otherwise you can only see them from one side. In your shaders you have to be aware of the normal direction.
In the 2D only case, check for your winding order of the triangles if you want to have back or front face culling, set glFontFace(GL_CCW) or glFrontFace(GL_CW) for counter-clockwise and clockwise winding order respectively. (I cant confirm if the winding order makes a difference in 2D when using glVertex2f)
Also try to diable the depth test and depth write glDisable(GL_DEPTH_TEST) and glDepthMask(GL_FALSE).
I have been learning how to use shaders in lwjgl. Now i have ran into an issue, where i need to rotate my mask for shading to get different results. How can i modify the mask transformation/rotation after it is bind, or do i need to modify it before. I tried almost anything but couldn't find an existing question / instructions. Any help will be greatly appreciated! This is my code for drawing a textured rectangle using my custom shader program.
private static void drawTexture(int shaderProgram, int texID1, int texID2) {
glUseProgram(shaderProgram);
setTextureUnits(shaderProgram);
bindTextures(texture1.getTextureID(), texture2.getTextureID(), mask.getTextureID());
glBegin(GL11.GL_QUADS);
glColor3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(0,0);
glVertex2f(-0.5f,-0.5f);
glColor3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(1,0);
glVertex2f(+0.5f,-0.5f);
glColor3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(1,1);
glVertex2f(+0.5f,+0.5f);
glColor3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(0,1);
glVertex2f(-0.5f,+0.5f);
glEnd();
glUseProgram(0);
}
Here is the answer to my own question:
create a matrix2 variable, and rotate the textCoords of your mask. the -+0.5's are for rotate around center. To fix any issues like exposed corners, clamp your textures on to the edge.
shader:
mat2 textureMatrix = mat2(cos(angle), sin(angle), -sin(angle), cos(angle));
float mask = texture2D(mask, textureMatrix*(gl_TexCoord[0].xy-0.5)+0.5).a;
I'm trying to get the lights and reflection correct in my program. I have a big sphere, which I can move the the mouse, that should be a light source (LIGHT0), and smaller spheres bouncing around that should reflect the light. I also need a directional light that I can change the direction using the keyboard
first some colors I defined:
float whitish[] = {0.8f, 0.8f, 0.8f, 1};
float white[] = {1, 1, 1, 1};
float blackish[] = {0.2f, 0.2f, 0.2f, 1};
float black[] = {0, 0, 0, 1}
I create the directional light with
gl.glLightfv(GL.GL_LIGHT1, GL.GL_AMBIENT, blackish,0);
gl.glLightfv(GL.GL_LIGHT1, GL.GL_SPECULAR, white,0);
gl.glLightfv(GL.GL_LIGHT1, GL.GL_DIFFUSE, white,0);
gl.glLightfv(GL.GL_LIGHT1, GL.GL_POSITION, spot_position,0);
spot_position is initially [ 0, 0, 1, 0] but it can change by pressing the keyboard keys. a key press adds 0.05 to a specific component of the position vector, until it reaches 1, then it resets back to -1 (nothing fancy).
The light of the center sphere is:
gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, position,0);
gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, blackish,0);
gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, white,0);
gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, white,0);
This light's position is always centered inside my big transparent sphere. w component of the position vector is 1.
I have this code to draw the picture in the back
gl.glBegin(GL_QUADS);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, white,0);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, white,0);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_SHININESS, white,0);
// Back Face
gl.glNormal3f(0, 0, 1);
gl.glTexCoord2f(texRight, texBottom);
gl.glVertex3f(rx2, ry1, rz1);
gl.glTexCoord2f(texRight, texTop);
gl.glVertex3f(rx2, ry2, rz1);
gl.glTexCoord2f(texLeft, texTop);
gl.glVertex3f(rx1, ry2, rz1);
gl.glTexCoord2f(texLeft, texBottom);
gl.glVertex3f(rx1, ry1, rz1);
To draw the spheres, I use the following functions:
public void drawtriangle(float[] v1, float[] v2, float[] v3) {
gl.glBegin(GL.GL_TRIANGLES);
gl.glNormal3fv(v1, 0);
gl.glVertex3fv(v1, 0);
gl.glNormal3fv(v2, 0);
gl.glVertex3fv(v2, 0);
gl.glNormal3fv(v3, 0);
gl.glVertex3fv(v3, 0);
gl.glEnd();
}
private void subdivideSphere2(float v1[], float v2[], float v3[], long depth) {
float v12[] = new float[3];
float v23[] = new float[3];
float v31[] = new float[3];
int i;
if (depth==0) {
float[] color= {v1[0]*v1[0], v2[1]*v2[1], v3[2]*v3[2], alpha};
gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT, blackish,0);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, color,0);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, color,0);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_SHININESS, color,0);
drawtriangle(v1, v2, v3);
return;
}
for (i = 0; i<3; i++) {
v12[i] = v1[i]+v2[i];
v23[i] = v2[i]+v3[i];
v31[i] = v3[i]+v1[i];
}
normalize(v12);
normalize(v23);
normalize(v31);
subdivideSphere2(v1, v12, v31, depth-1);
subdivideSphere2(v2, v23, v12, depth-1);
subdivideSphere2(v3, v31, v23, depth-1);
subdivideSphere2(v12, v23, v31, depth-1);
}
public void drawSphere() {
subdivideSphere2(sVdata[0], sVdata[1], sVdata[2], depth);
subdivideSphere2(sVdata[0], sVdata[2], sVdata[4], depth);
subdivideSphere2(sVdata[0], sVdata[4], sVdata[5], depth);
subdivideSphere2(sVdata[0], sVdata[5], sVdata[1], depth);
subdivideSphere2(sVdata[3], sVdata[1], sVdata[5], depth);
subdivideSphere2(sVdata[3], sVdata[5], sVdata[4], depth);
subdivideSphere2(sVdata[3], sVdata[4], sVdata[2], depth);
subdivideSphere2(sVdata[3], sVdata[2], sVdata[1], depth);
}
My problem is, the small spheres aren't reflecting light at all. They are very bright all the time. I can see a little bit of the light being reflected in the green lines of the cube when I move the big sphere closer to them, but no effect at all to the spheres. Also, I can't see any difference when I move the directional light (LIGHT1). I don't see any reflection on the lines of the cube, the big sphere, small spheres or the picture in the back. Below is screenshot of my program. How can I make my spheres not shine, and reflect both the directional light and the light from the big sphere? Any help would be greatly appreciated. Thank you.
It looks like the lightning is disabled when tracing your small spheres. I don't see the code where you call the drawSphere but it really looks like you are tracing the Big sphere with GL_LIGHTING enabled and the small spheres with GL_LIGHTING disabled.
By reflect the light do you mean that it is illuminated? Reflection involves ray tracing and is a much bigger subject.
I don't have direct experience with JOGL but I've used jME3 a fair amount and this sort of problem there is usually caused either by using an unlit material (which doesn't seem to be the case here as you say it is being lit a bit), by bad normals on the object, or by simply having the ambient light and/or the ambient color of the material turned up too high.
As far as I can tell you are not setting the normals correctly. A normal should basically point into the direction you want to reflect the light to, which is usually "90° away" from the triangle (use the cross product). OpenGL will then use that normal to calculate the actual lighting reflected by the surface. See this tutorial for further explanation.
The other problem is that you use the outdated OpenGL 2.0 functionality, which does vertex-based lighting, so effectively each triangle in your sphere is lightened to the same value. If you are looking for per-pixel lighting, which is close to impossible using the outdated functionality unless the sphere has as many vertices as it has pixels on the screen, you need to update your code and use Shaders.
This tutorial isn't Java, but it explains the basics of modern OpenGL very well, and should be easily translatable to JOGL.
I have some cube models and a lantern model in the "world" (with normals) and a light source which is placed in specific coordinates. The problem comes when I try move around the models, position of lightsource changes every frame to viewport position. Here is my initialization part of code, which contain lighting init:
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glShadeModel(GL11.GL_SMOOTH);
GL11.glClearDepth(1.0f);
GL11.glClearColor(0.0f, 0.75f, 1.0f, 1);
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glEnable(GL11.GL_BLEND);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glDepthFunc(GL11.GL_LESS);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
ByteBuffer temp = ByteBuffer.allocateDirect(16);
temp.order(ByteOrder.nativeOrder());
byf = temp;
GL11.glLight(GL11.GL_LIGHT1, GL11.GL_AMBIENT, (FloatBuffer)temp.asFloatBuffer().put(lightAmbient).flip()); // Setup The Ambient Light
GL11.glLight(GL11.GL_LIGHT1, GL11.GL_DIFFUSE, (FloatBuffer)temp.asFloatBuffer().put(lightDiffuse).flip()); // Setup The Diffuse Light
GL11.glLight(GL11.GL_LIGHT1, GL11.GL_POSITION,(FloatBuffer)temp.asFloatBuffer().put(lightPosition).flip()); // Position The Light
GL11.glEnable(GL11.GL_LIGHT1);
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
GL11.glFogi(GL11.GL_FOG_MODE, fogMode[fogfilter]);
temp.asFloatBuffer().put(fogColor).flip();
GL11.glFog(GL11.GL_FOG_COLOR, temp.asFloatBuffer());
GL11.glFogf(GL11.GL_FOG_DENSITY, 0.35f);
GL11.glHint(GL11.GL_FOG_HINT, GL11.GL_DONT_CARE);
GL11.glFogf(GL11.GL_FOG_START, 1.0f);
GL11.glFogf(GL11.GL_FOG_END, 5.0f);
GL11.glEnable(GL11.GL_FOG);
I have seen some similar problems but their solutions didn't help me at all. I know that the problem is with irregular order of setting Matrixes, but I have no idea which one (Matrix) and where I should change.
I tried to place setting Modelview matrix before the init of lighting but it didn't work for me.
By the way, I don't want to set the correct light position every frame, it works for me but it can slow the render.
Your'e probably using a code similar to this or glulookat().
GL11.glTranslatef(Camera.x, Camera.y, Camera.z);
GL11.glRotatef(Camera.roatationz, 0.0f, 0.0f, 1.0f);
GL11.glRotatef(Camera.roatationx, 1.0f, 0.0f, 0.0f);
GL11.glRotatef(Camera.roatationy, 0.0f, 1.0f, 0.0f);
//Render stuff here
Your light has to move as well. :)
The following code produces the image that follows. The image I am using for the background is 640 x 480, as is the displayMode. The texture background is a .bmp and is loaded with the Slick texture loader. I am confuse to why it is not filling the Quad and why it is reflected.
EDIT: The background of my OpenGL scene is pink, the black you see is from the Quad created. The background image is the green block with a 2px light blue border with "test" plastered on it.
private void renderBackground(){
float w = displayMode.getHeight()/2;
float h = displayMode.getWidth()/2;
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glPushMatrix();
GL11.glLoadIdentity();
GLU.gluOrtho2D(-w, w, -h, h);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glPushMatrix();
GL11.glLoadIdentity();
GL11.glDisable(GL11.GL_DEPTH_TEST);
if(useTextures)background.bind();
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex2f(-w,-h);
GL11.glTexCoord2f(1.0f, 0.0f);
GL11.glVertex2f(w,-h);
GL11.glTexCoord2f(1.0f, 1.0f);
GL11.glVertex2f(w, h);
GL11.glTexCoord2f(0.0f, 1.0f);
GL11.glVertex2f(-w, h);
GL11.glEnd();
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glPopMatrix();
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glPopMatrix();
}
Now when I add GL11.glTranslatef(20.0f, 20.0f, 0.0f); you will notice that the pink appears, which is the colour created int my "initGL" method:
GL11.glClearColor(1.0f, 0.75f, 0.796f, 0.0f);
My GL_PROJECTION contains the following before pushing it, my GL_MODELVIEW is unmodified when renderBackground() is called.
GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
GL11.glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
GLU.gluPerspective(45.0f, (float) displayMode.getWidth() / (float) displayMode.getHeight(), 0.1f, 25.0f);
//position camera
GLU.gluLookAt(5.0f, 3.0f, -5.0f, 0.0f, 0.0f, -10.0f, 0.0f, 1.0f, 0.0f);
GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix
I need more information to determine the problem, but here is a list with some possibilities.
1) You are using an older video card, which does not support texture non-power of 2, since you are using a library to load the texture, maybe it is detecting it, creating a power of two image, and filling it with black.
2) You (or some library you are using) changed the matrix of the texture matrix stack, and it is changing the texture coordinates.
3) You are doing something wrong when you load the texture (or call the library to do so).
The first thing I would check is if your video card supports texture non-power of 2 extension. You can check it at runtime, see how to detect if openGL/card supports non power of 2?
What I see first, is that you compute
float w = displayMode.getHeight()/2;
float h = displayMode.getWidth()/2;
switched?
Second, the texture could be flipped because the loader flipped it (when I remember right this happened to me, too especially with BMPs).