Split a Texture into puzzle pieces In libgdx - java

I am trying to convert android Canvas based game to Libgdx due to performance issues. Currently I am facing issues when I have to generate jigsaw puzzle piece sprites (dynamically).
What I did : I used android bitmap manipulation (Path and PorterDuff) and generated puzzle pieces and then fed that to Libgdx Game object in AndroidLauncher.
Question 1 : Is there a better way to convert a bitmap to puzzle pieces inside libgdx core project. (see below)
Question 2 : How can I create an area just to represent the puzzle piece.
(bounding box or width/height based solution is not suitable), so that user can drag the piece when he/she only touches on that texture area.
Question 3 : Best way to detect when adjacent puzzle pieces are moved closer to each other by the user.

Best Way to create a jigsaw puzzle game in LibGdx. There is an alternative to achieve pieces from an Image in LibGdx by using masking. Masking is achieved by creating a Shader Program i.e for this problem we have to write a
1.Vertex Shader
2.Fragment Shader
3.Create A Shader Program
4.create a custom sprite batch.
for more info on shaders: https://github.com/libgdx/libgdx/wiki/Shaders
Shader Program looks like this:
Below Vertex Shader For masking:-
Vertex Shader: Vertex shaders are responsible for performing operations on vertices.
`
uniform mat4 u_projTrans;
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord0;
varying vec4 v_color;
varying vec2 v_texCoord0;
void main()
{
v_color = a_color;
v_texCoord0 = a_texCoord0;
gl_Position = u_projTrans * a_position;
} `
2.Fragment Shader: A fragment shader functions in a very similar way to a vertex shader. But instead of processing it on a vertex it processes it once for each fragment.
`#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D u_texture;
uniform sampler2D u_mask;
varying vec4 v_color;
varying vec2 v_texCoord0;
void main()
{
vec4 texColor = texture2D(u_texture, v_texCoord0);
vec4 mask = texture2D(u_mask, v_texCoord0);
texColor.a *= mask.a;
gl_FragColor = v_color * texColor;
}`
create a Shader Program using Vertex and fragment Shader:
public class MyShader {
private FileHandle fragmentShader = Gdx.files.internal("fragment.glsl");
private FileHandle vertexShader = Gdx.files.internal("vertex.glsl");
public ShaderProgram myShader = new ShaderProgram(this.vertexShader,
this.fragmentShader);
public MyShader () {
this.myShader .begin();
this.myShader .setUniformi("u_texture", 0);
this.myShader .setUniformi("u_mask", 1);
this.myShader .end();
}
}
4.Custom Sprite Batch for Masking:
batch.setShader(MyShader.myShader);
this.alphaTexture.bind(1);
this.color.getTexture().bind(0);
batch.enableBlending();
Color c = getColor();
batch.draw(this.color, getX(), getY(), getOriginX(),
getOriginY(),
getWidth(), getHeight(), getScaleX(), getScaleY(), 0.0f);
batch.setShader(null);
ShaderLesson: https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson2

Related

libgdx - how to set sprite batch to blend/shade like this?

I currently have a default sprite batch:
batch = new SpriteBatch();
I have read about using shaders to modify how the batch draws each sprite. In my game, I am try to create a 'nighttime' effect - I want every pixel on screen to be black, except for pixels that are already white. For the white pixels, I want a shade of blue. Obviously I am new to libgdx and openGL - can anyone who is familiar with blending or shaders help me out with this? What should I do to my spritebatch to achieve the effect that I am describing?
Effect which you would like to achieve could be done with something like this.
Vertex Shader
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord;
attribute vec2 a_texCoord0;
uniform mat4 u_projTrans;
varying vec4 v_color;
varying vec2 v_texCoords;
void main()
{
v_color = a_color;
v_texCoords = a_texCoord0;
gl_Position = u_projTrans * a_position;
}
Fragment shader
precision mediump float;
varying vec4 v_color;
varying vec2 v_texCoords;
uniform sampler2D u_texture;
uniform mat4 u_projTrans;
bool equals(float a, float b) {
return abs(a-b) < 0.0001;
}
bool isWhiteShade(vec4 color) {
return equals(color.r, color.g) && equals(color.r, color.b);
}
void main() {
vec4 color = texture2D (u_texture, v_texCoords) * v_color;
if(isWhiteShade(color)) {
color *= vec4(0, 0, 1, 1);
}
else {
color *= vec4(0, 0, 0, 1);
}
gl_FragColor = color;
}
Add them to assets folder and then pass as arguments while creating instance of ShaderProgram and of course don't forget to apply this shader program to your SpriteBatch.
To be honest it has (almost) nothing common with SpriteBatch - all you have to do with it is just apply created shader
batch.setShader(ShaderProgram shader)
The shaders topic is very very wide (and to be honest independent of Libgdx) and there is no simple answer to your question without informations of what it should do. Also - to be honest - try at first to read something about shaders and come back on SO when you will have some troubles with this.
You can start right here:
https://github.com/libgdx/libgdx/wiki/Shaders

OpenGL ES 2.0 Android Clipping Color

i'm using my fragment shader to clip objects in OpenGL ES 2.0. Everything is working well, however the colour of the clipped surface is all black... I can not figure out how to change the colour (well ideally I'd want to make a similar texture to the rest of the object. I have included the code for my fragment shader below.
precision mediump float;
varying vec2 texCoord;
varying vec3 v_Normal;
varying vec3 v_Position;
varying vec4 originalPosition;
uniform sampler2D texSampler2D;
uniform vec3 lightPosition;
uniform vec4 lightColor;
void main()
{
vec3 L = normalize(lightPosition - v_Position);
vec3 N = normalize(v_Normal);
float NdotL = max(dot(N,L),0.0);
if(originalPosition.y >= 2.0){
discard;
}else{
gl_FragColor = NdotL * lightColor * texture2D(texSampler2D, texCoord);
}
}
Using discard in a fragment shader doesn't render anything to the pixel, it just leaves it exactly as it was before, so the black color is probably your clear color or whatever you had rendered previously. If you want to render a particular color to the pixels you are currently discarding, add another uniform to your shader for the clip color, like this:
uniform vec4 clipColor;
Set it in the same way you set the lightColor, then instead of discarding the pixel when clipping, you can set the pixel to the clip color:
if(originalPosition.y >= 2.0) {
gl_FragColor = clipColor;
} else {
gl_FragColor = NdotL * lightColor * texture2D(texSampler2D, texCoord);
}

2D glsl shader transformation

I would like to create a shader to simulate a pseudo 3D water surface on a 2D scene build with libgdx. The idea is to recreate the following effect:
http://forums.tigsource.com/index.php?topic=40539.msg1104986#msg1104986
But I am stuck at creating the trapezoid shape, I think I didn't understand how texture coordinate are calculated on opengl shaders. May I modify the vertex in the vertex shader or may I displace the texture on the fragment shader?
here is a test I have done but that don't work as expected.
vertex shader:
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord0;
uniform mat4 u_projTrans;
varying vec4 v_color;
varying vec2 v_texCoord0;
void main()
{
v_color = a_color;
float factor = (a_texCoord0.x - 0.5) * (a_texCoord0.y);
v_texCoord0 = a_texCoord0;
v_texCoord0.x += factor;
gl_Position = u_projTrans * a_position;
}
the fragment shader is just a passthrough
varying vec4 v_color;
varying vec2 v_texCoord0;
uniform sampler2D u_texture;
void main()
{
gl_FragColor = v_color * texture2D(u_texture, v_texCoord0);
}
and the result image
I am sure that my approach is too naive.
Finally, I decided to use only the fragment shader to achieve the effect.
Fake depth calculation is done by applying X displacement in regards of the Y axis.
Here is the snipet:
// simulate 3D surface
vec2 new_coord = v_texCoord0;
// calculate the stretching factor
float factor = ((0.5 - new_coord.x) * new_coord.y);
// apply the factor and stretch the image
new_coord.x += factor;
gl_FragColor = texture2D(u_texture, new_coord);

Using deferred rendering, getting blank output

So I'm working with Java/LibGDX and I'm trying to set up the very basics of deferred rendering, namely rendering the actual game art to one color buffer of an FBO and the corresponding normals to another color buffer of the FBO.
(So essentially, I'm wanting to create this and this by using multiple-render-targets.)
My problem is my end output is blank, as if nothing is being rendered or is being rendered incorrectly.
My shader (vertex and fragment)
I'm sort of sure this works, since if I just render some sprites completely normally with it enabled to the screen (not an FBO), they do render.
#version 150
in vec4 a_position;
in vec4 a_color;
in vec2 a_texCoord0;
uniform mat4 u_projTrans;
out vec4 v_color;
out vec2 v_texCoords;
void main()
{
v_color = a_color;
v_color.a = v_color.a * (255.0/254.0);
v_texCoords = a_texCoord0;
gl_Position = u_projTrans * a_position;
}
#version 150
#ifdef GL_ES
#define LOWP lowp
precision mediump float;
#else
#define LOWP
#endif
in LOWP vec4 v_color;
in vec2 v_texCoords;
uniform sampler2D u_texture;
uniform sampler2D u_normal;
out vec4 fragColor;
void main()
{
gl_FragData[0] = v_color * texture(u_texture, v_texCoords);
gl_FragData[1] = texture(u_normal, v_texCoords);
}
The following code is in the render loop.
The basic idea is I'm doing binding the two color buffers of the FBO with glDrawBuffers. I then bind two texture units, game art and normal'd game art. My shader above is supposed to take this and output game art to one color buffer and the corresponding normal art to the other.
// Position the camera.
_cameraRef.position.set(_stage.getWidth() * 0.5f, _stage.getHeight() * 0.5f, 0);
// Update the camera, SpriteBatch, and map renderer.
_cameraRef.update();
_spriteBatch.setProjectionMatrix(_cameraRef.combined);
_mapRenderer.setView(_cameraRef);
// Bind the color texture units of the FBO (multiple-render-targets).
Gdx.gl30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, _gBufferFBOHandle);
IntBuffer intBuffer = BufferUtils.newIntBuffer(2);
intBuffer.put(GL30.GL_COLOR_ATTACHMENT0);
intBuffer.put(GL30.GL_COLOR_ATTACHMENT1);
Gdx.gl30.glDrawBuffers(2, intBuffer);
// Draw!
Gdx.gl30.glClearColor(0, 0, 0, 1);
Gdx.gl30.glClear(GL30.GL_COLOR_BUFFER_BIT);
_spriteBatch.setShader(_shaderGBuffer);
_spriteBatch.begin();
_tilesAtlasNormal.bind(1); // Using multiple texture units to draw art and normals at same time to the two color buffers of the FBO.
_tilesAtlas.bind(0);
_mapRenderer.renderTileLayer(_mapLayerBackground);
_spriteBatch.end();
_spriteBatch.setShader(null);
// Bind the default FBO.
Gdx.gl30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
// Draw the contents of the FBO onto the screen to see what it looks like.
Gdx.gl30.glClearColor(0, 0, 0, 1);
Gdx.gl30.glClear(GL30.GL_COLOR_BUFFER_BIT);
_spriteBatch.begin();
_spriteBatch.draw(_gBufferTexture1, 0.0f, 0.0f); // <-- This texture is blank? It's the texture that was just rendered to above.
_spriteBatch.end();
So like I said, the end output is blank. I'm sure the FBO I create is valid since I check with glCheckFramebufferStatus.
It's just when I take the color texture(s) from that FBO and draw them to the screen, they're blank. I don't know where I'm going wrong.
Appreciate any input.
Last Ive checked the gl30 wasnt really ready for prime time in LibGDX.
That said, Ive achieved exactly what you want, but in gl20. Even if you have other reasons to use gl30, perhaps you will find my implementation useful source, video.
Don't forget to rewind your intbuffer:
IntBuffer intBuffer = BufferUtils.newIntBuffer(2);
intBuffer.put(GL30.GL_COLOR_ATTACHMENT0);
intBuffer.put(GL30.GL_COLOR_ATTACHMENT1);
intBuffer.rewind();

OpenGL Shader Compiles on Desktop, But Not Android

I recently started learning opengl and still don't know very much about it. I was following a tutorial and wrote these two shaders:
Vertex Shader:
#version 400
in vec4 s_vPosition;
in vec4 s_vColor;
out vec4 color;
void main() {
color = s_vColor;
gl_Position = s_vPosition;
}
Fragment Shader:
#version 400
in vec4 color;
out vec4 fColor;
void main() {
fColor = color;
}
They compile and work just fine on the desktop with OpenGL 3, but don't compile with OpenGL ES 2 on Android. I tried checking the shader output log, but it returned a blank string. Again, I am very new to this and my mistake is probably very simple, but any help would be highly appreciated.
In OpenGLES2 you don't use the in and out variable prefixes like in 3.0. Instead you use the following keywords:
attribute Values that are passed in to the vertex shader per vertex
varying Values that are passed from the vertex shader to the fragment shader
uniform Global variables that you can set on a shader for all vertices and fragments (includes things like textures, but can also be scalar or vector types).
An attribute corresponds to an in in a vertex shader.
A varying corresponds to an out in a vertex shader and an in in a fragment shader. So, change your vertex shader to this:
attribute vec4 s_vPosition;
attribute vec4 s_vColor;
varying vec4 color;
void main() {
color = s_vColor;
gl_Position = s_vPosition;
}
and your fragment shader to this:
varying vec4 color;
void main() {
gl_FragColor = color;
}
gl_FragColor is a specially defined variable like gl_Position used for outputting the color from a fragment shader.

Categories