I'm writing a 2d game engine using libgdx where multiple layers of sprites have to be rendered using SpriteBatch with an OrthgraphicCamera. My layers are sorted with a z component : higher z layers should be rendered on top of layers with a lower z.
Currently, I have to render layers sorted by their z component to achieve that. Is there a way, using opengl Z-buffer, to have them rendered out of order, and still show up correctly ?
Fixed by switching to DecalBatch instead of SpriteBatch. Here are the GL commands I use before drawing with the DecalBatch to enable depth-testing :
Gdx.gl.apply {
glClearColor(0f, 0f, 0f, 0f);
glEnable(GL20.GL_DEPTH_TEST)
glClear(GL20.GL_COLOR_BUFFER_BIT or GL20.GL_DEPTH_BUFFER_BIT)
glClearDepthf(1f)
glDepthFunc(GL20.GL_LESS)
}
Related
It's my first time attempting to create a basic light system that uses a black texture with a white circle on top. I read various threads about the issue but I just don't know what I am doing wrong.
What I want is the ambient to be dark and the light to be well white but changing the spritebatch color to something darker will cause the light to be darker to EVEN if I reset the color when drawing the light texture
So this is what I want (did this by forcing the light texture draw 5 times but that isn't a solution, it's an hack):
This is what I get (only 1 light texture is drawn but isn't very visible):
This is what I get without darkening the spritebatch:
Main code:
Game.sb.begin();
//Make stuff darker
Game.sb.setColor(0.1f, 0.1f, 0.1f,1f);
sb.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
lvl.render();
//Reset color
Game.sb.setColor(1f, 1f, 1f,1f);
sb.setBlendFunction(GL20.GL_DST_COLOR, GL20.GL_SRC_ALPHA);
//This draws all lights by drawing a texture with the above blending function
lightM.render();
Game.sb.end();
Light object draw method:
Game.sb.setColor(c.r,c.b,c.g, 1f);
Utils.drawTexture(Assets.get("sprites/lightcircle2.png", Texture.class), pos, size, true);
Game.sb.setColor(1,1,1,1);
Am I making some kind of error with the setcolor? I been considering using a FrameBuffer but I am not sure if it will give me the light effect I want
By the way this is my light texture (it's CC0):
You can achieve your requirement by these ways :
By using Shaders. Here is a small video and article on that video.
By use FBO and Blending, Here is one of my answer on this topic.
You can use box2dlight, even without using box2dbody(if you don't want any shadows)
World world = new World(new Vector2(0,0),false);
RayHandler rayHandler = new RayHandler(world);
rayHandler.setCombinedMatrix(stage.getCamera().combined); //<-- pass your camera combined matrix
new PointLight(rayHandler,1000, Color.WHITE,radius,x_position,y_position);
And at last call rayHandler.updateAndRender(); after all your rendering in your render() method.
Recently I switched from using an array of integers as my screen in Java to using a library. The library I'm using is LibGDX, and the conversion for me is quite different. Most things I have already started to get the hang of, and I'm still writing a bit of the code myself.
At this point, I'm curious if I can limit the rendering range of Sprites and any other factor of drawing, such as if a sprite stuck half-way out of a box, it wouldn't render the part that was sticking out (as so:)
Is there a way to render in a specific range, and if it is partially out of the range, it doesn't render what is out of the range, or will I have to do that myself?
You can do simple "clipping" to a rectangle with the LibGDX ScissorStack.
Because OpenGL is stateful and many of the LibGDX drawing APIs cache, be sure to "flush" or "end" your batches within the range of the scissors. See libgdx ScissorStack not working as expected and libgdx Cutting an image
If i did not missunderstand you, you are looking for camera.
The camera lets you define a Viewport (size) and you only see things inside this Viewport.
You can also move it arroung to see other parts of the world.
For example:
OrthographicCamera cam = new OrthographicCamera(80, 45);
This defines a camera, which showes you 80 units in x and 45 units in y. It P(0/0) by default is in the middle of the screen, so this camera shows objects from -40 to +40 in x and -22.5 to + 22.5 in y.
You can move it, so that the P(0/0) is in the left lower corner:
camera.position.x = -40;
camera.position.y = -22.5;
camera.update();
This should move the camera to the left by 40 units and down by 22.5 units, so that the P(0/0) is the left lower corner. Don't forget to call update() as this recalculates the projection and view matrix.
Finally, to draw with this camera, you need to set the SptieBatchs projectionMatrix to the one of the camera:
spriteBatch.setProjectionMatrix(camera.combined);
Now you can use this SpriteBatch to draw.
You should also consider to se ViewFrustum-Culling, which means, that you don't draw things out of the camera, because they will never appear on screen, but the draw call costs some performance.
I have a 2D tile map in java (using libgdx no Tiled Map Editor) formed with squares and I want the tiles to gradually become darker until they won't be visible. So basically I don't want round light. The only option I know is to use alpha channel and make every tile from the source which is the player become less visible. I want to know how can I implement this using a shader. I want to render my map normally with a spritebacth and then apply the shader to my spritebacth, so I can render the light effect. Each tile should have it's own visibility. An example of a game which uses the kind of lightning I want is: http://www.desura.com/games/fragile-soul
Render each tile itself via SpriteBatch and use spriteBatch.setColor(r, g, b, a) with different "grey" values.
The tile where your player is standing on will start with white, so spriteBatch.setColor(1, 1, 1, 1) before rendering that one. And then linearly decrease the brightness for the other ones in a radius around.
For example all tiles one next to the player might get spriteBatch.setColor(0.8f, 0.8f, 0.8f, 1f) resulting in a slightly darker tile. You do this until you reach black via spriteBatch.setColor(0, 0, 0, 1). All those tiles will be completely black.
I want to render a particle effect in 3D using the Z coordinate. I've tried to implement a own ParticleEffect using Decals instead of Sprites without success.
Is there any other way to render a ParticleEffect using the Z coordinate? Maybe by manipulating the transformation Matrix of the SpriteBatch?
Update:
working code
// update projection each frame since my camera is moving
spriteBatch.setProjectionMatrix(camera3d.projection);
for (ParticleEffect effect : effects){
spriteBatch.setTransformMatrix(camera3d.view);
spriteBatch.getTransformMatrix().translate(x,y,z); // different for each effect
spriteBatch.getTransformMatrix().scale(0.1f,0.1f,0.1f); //optional
spriteBatch.begin();
effect.draw(spriteBatch, delta);
spriteBatch.end();
spriteBatch.getTransformMatrix().idt();
}
If your 3D effect is a parallax effect, meaning your particles face the camera perpendicularily, you can indeed set the transformation matrix of the SpriteBatch
batch.getTransformMatrix().idt().translate(0, 0, z);
batch.begin();
... do your rendering here
batch.end();
// reset the matrix, so you can use the batch for other stuff
batch.idt();
For a perspective effect you'll also have to use perspective projection. The easiest way to cope with this requirement is to use a PerspectiveCamera instead of an OrthographicCamera.
I'm trying to render a colored cube after rendering other cubes that have textures. I have multiple "Drawer" objects that conform to the Drawer interface, and I pass each a reference to the GL object to the draw( final GL gl ) method of each individual implementing class. However, no matter what I do, I seem unable to render a colored cube.
Code sample:
gl.glDisable(GL.GL_TEXTURE_2D);
gl.glColor3f( 1f, 0f, 0f );
gl.glBegin(GL.GL_QUADS);
// Front Face
Point3f point = player.getPosition();
gl.glNormal3f(0.0f, 0.0f, 1.0f);
//gl.glTexCoord2f(0.0f, 0.0f);
gl.glVertex3f(-point.x - 1.0f, -1.0f, -point.z + 1.0f);
//gl.glTexCoord2f(1.0f, 0.0f);
gl.glVertex3f(-point.x + 1.0f, -1.0f, -point.z + 1.0f);
//continue rendering rest of cube. ...
gl.glEnd();
gl.glEnable(GL.GL_TEXTURE_2D);
I've also tried throwing the glColor3f calls before each vertex call, but that still gives me a white cube. What's up?
There are a few things you need to make sure you do.
First off:
gl.glEnable(gl.GL_COLOR_MATERIAL);
This will let you apply colors to your vertices. (Do this before your calls to glColor3f.)
If this still does not resolve the problem, ensure that you are using blending properly (if you're using blending at all.)
For most applications, you'll probably want to use
gl.glEnable(gl.GL_BLEND);
gl.glBlendFunc(gl.GL_SRC_ALPHA,gl.GL_ONE_MINUS_SRC_ALPHA);
If neither of these things solve your problem, you might have to give us some more information about what you're doing/setting up prior to this section of your code.
If lighting is enabled, color comes from the material, not the glColor vertex colors. If your draw function that you mentioned is setting a material for the textured objects (and a white material under the texture would be common) then the rest of the cubes would be white. Using GL_COLOR_MATERIAL sets up OpenGL to take the glColor commands and update the material instead of just the vertex color, so that should work.
So, simply put, if you have lighting enabled, try GL_COLOR_MATERIAL.
One thing you might want to try is: glBindTexture(GL_TEXTURE_2D, 0); to bind the texture to nil.
Some things to check:
Is there a shader active?
Any gl-errors?
What other states did you change? For example GL_COLOR_MATERIAL, blending or lighting will change the appearance of your geometry.
Does it work if you draw the non-textured cube first? And if it does try to figure out at which point it turns white. It's also possible that the cube will only show up in the correct color in the first frame, then there's definitely a GL state involved.
Placing glPushAttrib/glPopAttrib at the beginning/end of your drawing methods might help, but it's better to figure out what caused the problem in the first place.