Box2dlights - Layering lights - java

How do you make the box2dlights ignore textures and sprites in ambient lighting? For example I have a stage that has the ambient lighting set to dark. I want my lights to brighten up a platform directly underneath the light, but the background image behind the light should remain dark and not lit up. Currently the lights are the top rendered layer and everything underneath the light is lit up.

The right way to achieve this is the following:
Update your physics and cameras.
Render the light map so you can later fetch the texture from the RayHandler's FrameBuffer.
Render your top layers to a transparent FrameBuffer object, in the desired order, but don't render the light map inside of it. Do not render here your HUD or whatever top-most layers you don't want to be affected by you lighting.
Finish rendering to your FBO and begin rendering to your screen.
Render the background which is not affected by lights.
Bind to Texture Units 0 and 1 the light map and your top layers' FBO Texture.
Begin a Shader you will use to blend your light map with your FBO Texture. The mixing is quite simple (occurs in the Fragment Shader): glFragColor = tex0.rgb * tex1.rgb, and keep tex1.a untouched (tex0 = light map texture, tex1 = fbo texture). The RayHandler's ambient light is lost with this rendering method, so you can pass the ambient light colour to the shader and add it to the light map channels.
Bind the texture units to the shader and perform the rendering. This rendering must be done with alpha blending enabled (SRC_ALPHA, ONE_MINUS_SRC_ALPHA).
Bind again the default Texture Unit so remaining rendering is properly done (TEXTURE_0): render any remaining top-most layers and the HUD, if any.
Some example code:
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
tweenManager.update(delta);
worldUpdate(delta);
/* We have three cameras (foreground + double parallax background) */
moveForegroundCamera(player.getPosition().x, player.getPosition().y);
moveBackground0Camera(player.getPosition().x, player.getPosition().y);
moveBackground1Camera(player.getPosition().x, player.getPosition().y);
cameraMatrixCopy.set(foregroundCamera.combined);
rayHandler.setCombinedMatrix(cameraMatrixCopy.scale(Globals.BOX_TO_WORLD, Globals.BOX_TO_WORLD, 1.0f), foregroundCamera.position.x,
foregroundCamera.position.y, foregroundCamera.viewportWidth * camera.zoom * Globals.BOX_TO_WORLD,
foregroundCamera.viewportHeight * foregroundCamera.zoom * Globals.BOX_TO_WORLD);
rayHandler.update();
rayHandler.render();
lightMap = rayHandler.getLightMapTexture();
fbo.begin();
{
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
/* Draw the second background (affected by lights), the player, the enemies and all the objects */
batch.enableBlending();
batch.setProjectionMatrix(background1Camera.combined);
batch.begin();
background1.draw(batch);
batch.end();
batch.setProjectionMatrix(foregroundCamera.combined);
batch.begin();
// Draw stuff...
batch.end();
}
fbo.end();
/* Now let's pile things up: draw the bottom-most layer */
batch.setProjectionMatrix(background0Camera.combined);
batch.disableBlending();
batch.begin();
background0.draw(batch);
batch.end();
/* Blend the frame buffer's texture with the light map in a fancy way */
Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE0);
fboRegion.getTexture().bind(); // fboRegion = new TextureRegion(fbo.getColorBufferTexture());
Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE1);
lightMap.bind();
Gdx.gl20.glEnable(Gdx.gl20.GL_BLEND);
Gdx.gl20.glBlendFunc(Gdx.gl20.GL_SRC_ALPHA, Gdx.gl20.GL_ONE_MINUS_SRC_ALPHA);
lightShader.begin();
lightShader.setUniformf("ambient_color", level.getAmbientLightColor());
lightShader.setUniformi("u_texture0", 0);
lightShader.setUniformi("u_texture1", 1);
fullScreenQuad.render(lightShader, GL20.GL_TRIANGLE_FAN, 0, 4);
lightShader.end();
Gdx.gl20.glDisable(Gdx.gl20.GL_BLEND);
Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE0); // Bind again the default texture unit
/* Draw any top-most layers you might have */
hud.draw();
}

Related

How do I make scaled images look better in Java/OpenGL?

Here are two pictures of the same image:
this is what it looks like when viewed in preview...
and this is how it looks in my game...
Obviously the character is scaled down in my game, however, when I scale down the sprite in preview or pixelmator, it is still smooth. Even when the image is at a 1:1 scale it still has the jagged edges.
This is my render method
public void render(Camera camera, List<Entity> entities) {
shader.loadViewMatrix(Main.createViewMatrix(camera));
//per textured model
GL30.glBindVertexArray(((RenderComponent) entities.get(0).getComponent(EntityComponentType.RENDER)).texturedModel.getRawModel().getVaoID());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
for(Entity e : entities) {
RenderComponent render = (RenderComponent) e.getComponent(EntityComponentType.RENDER);
//load transformation matrix per entity
shader.loadTransformationMatrix(Main.createTransformationMatrix(render.position, render.rx, render.ry, render.getScaleX(), render.getScaleY()));
shader.loadSprite((AnimationComponentContainer) e.getComponent(EntityComponentType.ANIMATION));
//activate texture for each entity
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, render.getTexturedModel().getTexture().getTextureID());
//render entity
GL11.glDrawElements(GL11.GL_TRIANGLES, render.getTexturedModel().getRawModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
}
//per textured model
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(1);
GL30.glBindVertexArray(0);
}
And in my fragment shader I sample the image
vec4 color = texture(sampler, pass_TextureCoords);
and remove transparency
if(color.a < 0.5) discard;
out_Color = vec4(totalDiffuse, 1) * color;
My question is, how do I prevent the jagged edges from occurring (they are most prominent around his pants)? Or how do I smooth them out? The image itself if 512x1024
Make sure the internal rendering resolution of the game is large enough for the full image, and be sure that the game isn't casting any light onto the sprite itself, because it looks like the character is interacting with that green light over there and it's causing some gradient issues on the pants.

positioning a sprite in libgdx

I've got a problem to draw a sprite to my project.
I have a map (960x900) divided into tiles (64x64).
As you can see in the picture, when i click on the bottom left corner of the purple square, the position is (0;0), and when I click on the top right corner of purple square, the position is (36;47)
The problem is that the picture of the purple square has a size of 32x32, and when I draw this picture with libgdx on the screen, the size doesn't match.
Another example: the square with black border has a size of 64x64. So if I draw the purple square in front of the black, the purple should be the half (in height and in width) of the black, no?
Does anyone know why libgdx resizes the purple square?
Sprite sprite = new Sprite(new Texture("assets/purpleSquare.png"));
i draw it in a method
public void render(SpriteBatch batch) {
batch.draw(sprite, 0, 0);
}
I don't know why the picture is resized by libgdx.. I have also tried to do
batch.draw(sprite, 0, 0, width, heigth);
To precise the sprite's size but it doesn't work too..
The size on screen bears no direct relation to the size of the original image. When you draw a sprite you provide the SpriteBatch with a position, width, and height in world coordinates. The sprite will be stretched to fit these world coordinates, regardless of the original image size.
When you click the screen, you are clicking in screen coordinates. The relation between screen and world coordinates is determined by the projection matrix that you use with the SpriteBatch. The projection matrix is typically controlled with a Camera or Viewport object, which you can use to convert between the two coordinate systems using the project and unproject methods.
I'm happy to see that after many hours i found a solution, even if i know which is not correct.
I would like some help to understand the problem's origin.
With this parts of code :
public void update(float delta) {
batch.begin();
drawBackground(); // Draw the background
drawButton(); // Draw the play/pause button
batch.end();
drawMap(); // draw a tmx map made with tiled
batch.begin();
if(!world.isInitial()) {
renderMonster(); // method which draw the monster
}
renderTower(); // method which draw the tower's level
batch.end();
}
I don't understand why i have to do "batch.begin()" and "batch.end()" twice.
I dont' understant why with this code, the purple square is resized.
With this code :
public void update(float delta) {
batch.begin();
drawBackground();
drawButton();
batch.end();
drawMap();
------->sb = new SpriteBatch();
sb.begin();
if(!world.isInitial()) {
renderMonster();
}
renderTower();
sb.end();
}
this line that i add fix the bug with the purple square. If i work with two SpriteBatch (because with one, if i reinitialize SpriteBatch in update method, my pause/play button diseapper) and i initialise the second (SpriteBatch sb) in the update method.
It is correct to initialise a SpriteBatch every time i'm passing on the update method ? There's no method with a SpriteBatch to avoid this problem ?

JOGL 2.0, render depth buffer to texture

I am trying to implement simple shadow mapping technique in JOGL 2.0 and I struggle with rendering depth values into texture. Maybe I am doing it completely wrong but it is weird that rendering scene in color works properly. I have also found a similar question here at stackoverflow, which is asked here: Render the depth buffer into a texture using a frame buffer
and problem is solved by calling
gl.glDrawBuffer(GL2.GL_NONE);
gl.glReadBuffer(GL2.GL_NONE);
However, this does not help in my case. When I render scene in texture in color as normally, function works properly. Here is the result:
However, after trying to render depth values, it just renders white color (and something which doesn't correspond with the scene at all)
---- UPDATED code, which is working properly now:
private void initializeFBO3(GL2 gl) {
//Create frame buffer
gl.glGenFramebuffers(1, frameBufferID, 0);
gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, frameBufferID[0]);
// ------------- Depth buffer texture --------------
gl.glGenTextures(1,depthBufferID,0);
gl.glBindTexture(GL2.GL_TEXTURE_2D, depthBufferID[0]);
gl.glTexImage2D(GL2.GL_TEXTURE_2D, // target texture type
0, // mipmap LOD level
GL2.GL_DEPTH_COMPONENT, // internal pixel format
//GL2.GL_DEPTH_COMPONENT
shadowMapWidth, // width of generated image
shadowMapHeight, // height of generated image
0, // border of image
GL2.GL_DEPTH_COMPONENT, // external pixel format
GL2.GL_UNSIGNED_INT, // datatype for each value
null); // buffer to store the texture in memory
//Some parameters
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST);
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_NEAREST);
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_EDGE);
//Attach 2D texture to this FBO
gl.glFramebufferTexture2D(GL2.GL_FRAMEBUFFER,
GL2.GL_DEPTH_ATTACHMENT,
GL2.GL_TEXTURE_2D,
depthBufferID[0],0);
gl.glBindTexture(GL2.GL_TEXTURE_2D, 0);
//Disable color buffer
//https://stackoverflow.com/questions/12546368/render-the-depth-buffer-into-a-texture-using-a-frame-buffer
gl.glDrawBuffer(GL2.GL_NONE);
gl.glReadBuffer(GL2.GL_NONE);
//Set pixels ((width*2)* (height*2))
//It has to have twice the size of shadowmap size
pixels = GLBuffers.newDirectByteBuffer(shadowMapWidth*shadowMapHeight*4);
//Set default frame buffer before doing the check
//http://www.opengl.org/wiki/FBO#Completeness_Rules
gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, 0);
int status = gl.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER);
// Always check that our framebuffer is ok
if(gl.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER) != GL2.GL_FRAMEBUFFER_COMPLETE)
{
System.err.println("Can not use FBO! Status error:" + status);
}
}
public void display(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2(); // get the OpenGL graphics context
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity(); // reset the model-view matrix
//Render scene into Frame buffer first
gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, frameBufferID[0]);
renderSmallScene(gl);
//Read pixels from buffer
gl.glBindFramebuffer(GL2.GL_READ_FRAMEBUFFER, frameBufferID[0]);
//Read pixels
gl.glReadPixels(0, 0, shadowMapWidth, shadowMapHeight, GL2.GL_DEPTH_COMPONENT , GL2.GL_UNSIGNED_BYTE, pixels);
//Switch back to default FBO
gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, 0);
drawSceneObjects(gl);
//Draw pixels, format has to have only one
gl.glDrawPixels(shadowMapWidth, shadowMapHeight, GL2.GL_LUMINANCE , GL2.GL_UNSIGNED_BYTE, pixels);
}
Working result:
You must read about using FBO and OpenGL in general.
In your code you create FBO and its attachments in each frame. That's wrong.It's huge overhead.Construct your FBOs on init only once.Second, you must bind FBO in order to draw into it (or read from it), otherwise OpenGL will draw into default FBO.Take a look here and here
So ,once your FBO is ready you render into it like this:
glBindFrameBuffer((GL_DRAW_FRAMEBUFFER, yourFbo);
drawSceneObjects(gl);
glBindFrameBuffer((GL_READ_FRAMEBUFFER, yourFbo);
readPixelsHere()
glBindFrameBuffer((GL_FRAMEBUFFER, 0);///switch to default FBO
In fact , in your case ,as you leave the FBO bound,just call
glBindFrameBuffer((GL_READ_FRAMEBUFFER, yourFbo);
after drawing your geometry.
Also , if you are not using shaders there is no reason to use textures as FBO attachments.Create render buffer instead.

Problems rendering to texture - scaling issues(?)

I'm trying to get my rendering-to-texture working. So far, it does all the necessary GL gubbins to draw on the texture and everything - the only problem is its getting the scaling all off.
I figured I'd want to set the viewport to the size of the texture, and the gluOrtho2d (the way I'm going to be drawing onto the texture) as -halfwidth, halfwidth, -halfheight, halfheight. This means when drawing position 0,0 should be in the center. A position of halfwdith, halfheight should be in the top right corner etc etc.
I'm getting really weird effects though, it seems that its not drawing on the texture in the right scale - so everything gets skewed, can anyone suggest what I might be doing wrong?
Thanks
public void renderToTexture(GLRenderer glRenderer, GL10 gl)
{
boolean checkIfContextSupportsExtension = checkIfContextSupportsExtension(gl, "GL_OES_framebuffer_object");
if(checkIfContextSupportsExtension)
{
GL11ExtensionPack gl11ep = (GL11ExtensionPack) gl;
int mFrameBuffer = createFrameBuffer(gl,texture.getWidth(), texture.getHeight(), texture.getGLID());
if (mFrameBuffer == -1)
{
return;
}
gl11ep.glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, mFrameBuffer);
int halfWidth = texture.getWidth()/2;//width/2;
int halfHeight = texture.getHeight()/2;//height/2;
gl.glViewport(0,0,texture.getWidth(), texture.getHeight());
gl.glLoadIdentity();
GLU.gluOrtho2D(gl, -halfWidth, halfWidth , -halfHeight, halfHeight);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glClearColor(0f, 1f, 0f, 1f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
//draw the old version of the texture to framebuffer:
Quad quad = new Quad(texture.getWidth(), texture.getHeight());
quad.setTexture(texture);
SpriteRenderable sr = new SpriteRenderable(quad);
sr.renderTo(glRenderer, gl, 1);
//draw the new gl objects etc to framebuffer
for (Renderable renderable : renderThese)
{
if (renderable.isVisible()) {
renderable.renderTo(glRenderer, gl, 1);
}
}
//default to the old framebuffer
gl11ep.glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, 0);
}
}
images:
This one is the game prior to any texture rendering.
image1
This is after the "blood splats" (currently pigs!) are rendered on the "arena" background texture shown in picture 1. Notice that the original texture has shrunk too small to see in the middle (its a few pixles) and the pig "blood splat" jumps in a zig-zag, flipping over the center of the texture and becoming smaller...
image2
(sorry, dont have enough rep to post images in the post!)
Just a speculative guess, but do you remember to set matrixMode to GL_PROJECTION prior to entering renderToTexture function? It's not set inside the function, where it seems like it should be. Also don't forget to restore projection matrix and viewport at the end of the function.

libgdx and android application. Image as background

I am new and I just start my journey with libgdx. I would like to know how I can do image.png in resolution 960x640 as background in my game? This is possible? Thx for advices and forbearance. Maybe you hava a simply tutorial?
This is my render class:
public void render() {
texture = new Texture(Gdx.files.internal("E:/background.png"));
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(texture, 0, 0);
batch.end();
}
Second question. I need to insert two active images, active means when I click on that image, the next image show me on the screen. I want to implement action when I click on that picture.
In your create() method, create a new Texture referencing your image.png, and then use your existing SpriteBatch to render it in the render() loop. Immediately after your GL.clear() call, go your batch.draw(backgroundTexture, 0. 0) and make sure you're in OrthographicProjection mode for your camera.
first you have to set the view port
do this in your create method
`float scrw = 960;
float scrh = 640;
camera = new OrthographicCamera();
camera.viewportHeight = scrh;
camera.viewportWidth = scrw;
camera.position.set(camera.viewportWidth * .5f,
camera.viewportHeight * .5f, 0f);
camera.update();`
create a texture
texture = new Texture("data/background.png");
put this texture in a sprite like this
sprite=new sprite(texture);
and then set the size like this
sprite.setsize(960,640);
and draw it in your render methods between batch.begin
and batch.end
sprite.draw(batch);

Categories