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).
Related
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 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. :)
I am making a voxel-based game, and for needs of it, i am creating a block rendering engine.
Point is, that i need to generate lots of cubes. Every time i render more than 16x16x16 chunk of theese blocks, my FPS is dropped down hardly, because it renders all 6 faces of all of theese cubes. That's 24 576 quads, and i dont want that.
So, my question is, How to stop rendering vertices(or quads) that are not visible, and therefore increase performance of my game?
Here is class for rendering of a block:
public void renderBlock(int posx, int posy, int posz) {
try{
//t.bind();
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);// or even GL_FRONT_AND_BACK */);
glPushMatrix();
GL11.glTranslatef((2*posx+0.5f),(2*posy+0.5f),(2*posz+0.5f)); // Move Right 1.5 Units And Into The Screen 6.0
GL11.glRotatef(rquad,1.0f,1.0f,1.0f);
glBegin(GL_QUADS); // Draw A Quad
GL11.glColor3f(0.5f, 0.4f, 0.4f); // Set The Color To Green
GL11.glTexCoord2f(0,0);
GL11.glVertex3f( 1f, 1f,-1f); // Top Right Of The Quad (Top)
GL11.glTexCoord2f(1,0);
GL11.glVertex3f(-1f, 1f,-1f); // Top Left Of The Quad (Top)
GL11.glTexCoord2f(1,1);
GL11.glVertex3f(-1f, 1f, 1f); // Bottom Left Of The Quad (Top)
GL11.glTexCoord2f(0,1);
GL11.glVertex3f( 1f, 1f, 1f); // Bottom Right Of The Quad (Top)
//GL11.glColor3f(1.2f,0.5f,0.9f); // Set The Color To Orange
GL11.glTexCoord2f(0,0);
GL11.glVertex3f( 1f,-1f, 1f); // Top Right Of The Quad (Bottom)
GL11.glTexCoord2f(0,1);
GL11.glVertex3f(-1f,-1f, 1f); // Top Left Of The Quad (Bottom)
GL11.glTexCoord2f(1,1);
GL11.glVertex3f(-1f,-1f,-1f); // Bottom Left Of The Quad (Bottom)
GL11.glTexCoord2f(1,0);
GL11.glVertex3f( 1f,-1f,-1f); // Bottom Right Of The Quad (Bottom)
//GL11.glColor3f(1.0f,0.0f,0.0f); // Set The Color To Red
GL11.glTexCoord2f(0,0);
GL11.glVertex3f( 1f, 1f, 1f); // Top Right Of The Quad (Front)
GL11.glTexCoord2f(1,0);
GL11.glVertex3f(-1f, 1f, 1f); // Top Left Of The Quad (Front)
GL11.glTexCoord2f(1,1);
GL11.glVertex3f(-1f,-1f, 1f); // Bottom Left Of The Quad (Front)
GL11.glTexCoord2f(0,1);
GL11.glVertex3f( 1f,-1f, 1f); // Bottom Right Of The Quad (Front)
//GL11.glColor3f(1f,0.5f,0.0f); // Set The Color To Yellow
GL11.glTexCoord2f(0,0);
GL11.glVertex3f( 1f,-1f,-1f); // Bottom Left Of The Quad (Back)
GL11.glTexCoord2f(1,0);
GL11.glVertex3f(-1f,-1f,-1f); // Bottom Right Of The Quad (Back)
GL11.glTexCoord2f(1,1);
GL11.glVertex3f(-1f, 1f,-1f); // Top Right Of The Quad (Back)
GL11.glTexCoord2f(0,1);
GL11.glVertex3f( 1f, 1f,-1f); // Top Left Of The Quad (Back)
//GL11.glColor3f(0.0f,0.0f,0.3f); // Set The Color To Blue
GL11.glTexCoord2f(0,1);
GL11.glVertex3f(-1f, 1f, 1f); // Top Right Of The Quad (Left)
GL11.glTexCoord2f(1,1);
GL11.glVertex3f(-1f, 1f,-1f); // Top Left Of The Quad (Left)
GL11.glTexCoord2f(1,0);
GL11.glVertex3f(-1f,-1f,-1f); // Bottom Left Of The Quad (Left)
GL11.glTexCoord2f(0,0);
GL11.glVertex3f(-1f,-1f, 1f); // Bottom Right Of The Quad (Left)
//GL11.glColor3f(0.5f,0.0f,0.5f); // Set The Color To Violet
GL11.glTexCoord2f(0,0);
GL11.glVertex3f( 1f, 1f,-1f); // Top Right Of The Quad (Right)
GL11.glTexCoord2f(1,0);
GL11.glVertex3f( 1f, 1f, 1f); // Top Left Of The Quad (Right)
GL11.glTexCoord2f(1,1);
GL11.glVertex3f( 1f,-1f, 1f); // Bottom Left Of The Quad (Right)
GL11.glTexCoord2f(0,1);
GL11.glVertex3f( 1f,-1f,-1f); // Bottom Right Of The Quad (Right)
//rquad+=0.0001f;
glEnd();
glPopMatrix();
}catch(NullPointerException t){t.printStackTrace(); System.out.println("rendering block failed");}
}
Here is code that renders them:
private void render() {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT|GL11.GL_DEPTH_BUFFER_BIT);
for(int y=0; y<32; y++){
for(int x=0; x<16; x++){
for(int z=0; z<16; z++) {
b.renderBlock(x, y, z);
}
}
}
}
Your code has a larger performance problem. You shouldn't be using immediate mode OpenGL rendering (glVertexXXX() calls) to draw such a large number of vertices.
When you perform your rendering this way, your code has to make a call to the graphics driver for every vertex, which is slow.
Instead, you should use Vertex Buffer Objects. This will allow you up upload all your geometry directly onto the graphics card, then draw all your cubes in a single Java method call (probably glDrawArrays).
I recommend, like ulmangt said, that you use VBO but before that, you need to calculate only the visible faces.
This can be easily done by (just once at the beginning) checking if a face is neighbor to a empty voxel ("air"). If it is, add that quad (face) to the rendering.
Afterwards you just do this check only on the neighbors of changed voxels. Example: When the user removes a cube, check the 6 neighbors of that voxel and add those quads to the rendering. Do the reverse when voxels are added, remove neighbor quads.
So with a 5x5x5 cube made of voxels, instead of 750 quads, you end up with 150.
Other gains can be had by just rendering chunks (a group of voxels) in the view (ignoring the ones to the back of the player) and using a distance limit.
You can go even more crazy by using octrees to only render chunks that you know that could possibly be visible.
A good idea is to NOT use immediate mode to render your blocks, I use display lists because they are the easiest to set up and are VERY fast. Second of all, Even if you still only use immediate mode then use only one glBegin/glEnd call when you're drawing, Use a texture atlas for textures in the future and to your main question which is how to stop rendering invisible faces, It is pretty simple, The way I do it is basically make six methods for each face which returns a boolean. You would simple return if the block type in the direction of that face is an air block, If it is. Then that means it will return true, Therefor render it. And in your draw method add the parameters "boolean backface, boolean topface... etc" and an if statement checking which side to draw.
hope I helped, Good luck!
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).
I was learning about how to use textures with GLSL (in LWJGL) to create a simple fragment shader that blurs a texture. The first attempt (for testing purposes) was a very simple shader which just takes the original color values:
uniform sampler2D rectTexture;
void main(){
vec4 color = texture2D(rectTexture, gl_FragCoord.st);
gl_FragColor = color;
}
The shader compiles fine. After compilation I link and start to use it, up to this everything's working and no errors are reported. Then I try to set the uniform variable for the texture:
uniformTextureAddr = ARBShaderObjects.glGetUniformLocationARB(programObject, "rectTexture");
ARBMultitexture.glActiveTextureARB(ARBMultitexture.GL_TEXTURE0_ARB);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
ARBShaderObjects.glUniform1iARB(uniformTextureAddr, 0);
Then I just draw a quad with normal texcoords (0.0f-1.0f on both dimensions) but the texture doesn't show up. The texture itself is not the problem; I draw a second quad next to the first one without my fragment shader an it shows up as you would expect. The basic approach is taken from NeHe: GLSL - An Introduction. uniformTextureAddr is not -1 and if I use an even simpler shader, which just turns every pixel red, I get a red quad. As expected. So the bug has to be in the whole sampler2D business. Trivial mistakes, such as the quad simply being out of frame, are also ruled out by this.
And yes, after drawing without the shader I call glUseProgramObject(programObj) with my shader again.
By the way, this is running on Windows XP SP3 with a ATI Radeon Catalyst 10.6 driver and LWJGL version 2.4.2.
UPDATE: I think something might be wrong with the program itself. When I add another variable to the shader:
uniform sampler2D secondTexture;
uniform sampler2D rectTexture;
void main(){
vec4 color = texture2D(rectTexture, gl_FragCoord.st);
gl_FragColor = color;
}
and call glGetUniformLocationARB(programObject, "secondTexture"); it just returns -1, even though it should be there. Log info still only says:
Info log:
Fragment shader was successfully compiled to run on hardware.
UPDATE 2:
The actual texture is copied from the backbuffer. A simple white line is drawn in a smaller viewport and then copied to a texture:
GL11.glViewport(0, 0, 256, 256);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glColor3f(1.0f, 1.0f, 1.0f);
GL11.glBegin(GL11.GL_LINES);
GL11.glVertex3f(0.0f, 0.0f, 0.0f);
GL11.glVertex3f(256.0f, 256.0f, 0.0f);
GL11.glEnd();
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_LUMINANCE, 0, 0, 256, 256, 0);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
But like I said, I don't think the texture is the actual problem, since it shows up fine on the second quad without my custom shader. Also, don't worry about binding; this is the only texture in the program and is only bound once at the very beginning.
Here is my drawing code:
ARBShaderObjects.glUseProgramObjectARB(programObject);
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0.0f, 1.0f);
GL11.glVertex3f(0.0f, 0.0f, 0.0f);
GL11.glTexCoord2f(1.0f, 1.0f);
GL11.glVertex3f(256.0f, 0.0f, 0.0f);
GL11.glTexCoord2f(1.0f, 0.0f);
GL11.glVertex3f(256.0f, 256.0f, 0.0f);
GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex3f(0.0f, 256.0f, 0.0f);
GL11.glEnd();
ARBShaderObjects.glUseProgramObjectARB(0);
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0.0f, 1.0f);
GL11.glVertex3f(256.0f, 0.0f, 0.0f);
GL11.glTexCoord2f(1.0f, 1.0f);
GL11.glVertex3f(512.0f, 0.0f, 0.0f);
GL11.glTexCoord2f(1.0f, 0.0f);
GL11.glVertex3f(512.0f, 256.0f, 0.0f);
GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex3f(256.0f, 256.0f, 0.0f);
GL11.glEnd();
You are providing texture coordinates but not using them in shader. Instead, you are using gl_FragCoord, which gives you window coordinates:
texture2D(rectTexture, gl_FragCoord.st)
You should use gl_MultiTexCoord0.xy instead.
Since you are using GL_TEXTURE_2D to store the rectTexture, the sampler will expect normalized texture coordinates (i.e. [0.0, 1.0]).
So your shader should be modified to:
uniform vec2 invTextureSize; // contains [1.0 / w, 1.0 / h];
uniform sampler2D rectTexture;
void main() {
vec4 color = texture2D( rectTexture, gl_FragCoord.st * invTextureSize.xy );
gl_FragColor = color;
}
In addition, you will need to setup the GL_TEXTURE_MIN_FILTER, GL_TEXTURE_MAG_FILTER, GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T properly for that texture object.
If not, most opengl driver will provide a rgba = [0, 0, 0, 0] color to the shader.
Please see the reference of glTexParameter
The following configuration works for most GL_TEXTURE_2D objects
glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
Hope this helps.
Are you using a vertex shader also? Some cards require that you provide both a vertex and a fragment shader.