Thursday, August 10, 2017

libgdx - GLSL 2D Silhouette



I'm trying to render a silhouette of any entity behind foreground objects to indicate their position to the player. Here's an example of what I want to achieve, from Hyper Light Drifter:


Hyper Light Drifter Silhouette


From what I've read online about GLSL and the ways I might be able to achieve this, the closest thing I can think of to achieve this would be to use the stencil buffer, which was also indicated in this question:


2D Hidden Object Silhouette Shader


I don't quite understand how I can achieve this within LibGDX. Should I be using a vertex / fragment shader, or the native Gdx methods? This is my current rendering workflow:


Render Lower Tiled Map Layers
Render Entities
Render Upper Tiled Map Layers

From what I understand, I would have to:




  1. Write the top layer to the stencil buffer

  2. Render the entities (silhouettes) within the stencil


Is this right? If anyone can enlighten me, it would be greatly appreciated!



Answer



I solved it! Here is the process I followed:



  1. Render Lower Tiled Map Layers

  2. Render Entities


  3. Render Upper Tiled Map Layers

  4. Render Upper Tiled Map Layers to stencil buffer

  5. Render Entities using the stencil buffer with a simple color fragment shader


The code.


Rendering the upper map layer:


// Render the top map layer normally
renderer.render(layerIndeces);

// Clear the stencil buffer

Gdx.gl20.glClear(GL20.GL_STENCIL_BUFFER_BIT);

// Enable Stencil Test
Gdx.gl20.glEnable(GL20.GL_STENCIL_TEST);
Gdx.gl20.glStencilFunc(GL20.GL_ALWAYS, 0x1, 0xFF);
Gdx.gl20.glStencilOp(GL20.GL_REPLACE, GL20.GL_REPLACE, GL20.GL_REPLACE);

// Simple "if (gl_FragColor.a == 0.0) discard;" fragment shader
renderer.getBatch().setShader(shader);
renderer.render(layerIndeces);

renderer.getBatch().setShader(null);

Rendering the silhouettes:


Gdx.gl20.glStencilFunc(GL20.GL_LEQUAL, 0x1, 0xFF);
Gdx.gl20.glStencilOp(GL20.GL_KEEP, GL20.GL_KEEP, GL20.GL_KEEP);

// "gl_FragColor = vec4(0.0, 1.0, 1.0, 0.2) * texture2D(u_texture, v_texCoord0).a;"
batch.setShader(shader);

// Render Entities


batch.setShader(null);

Gdx.gl20.glDisable(GL20.GL_STENCIL_TEST);

No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...