Skip to content

Instantly share code, notes, and snippets.

@mattdesl
Created December 20, 2012 03:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattdesl/4342861 to your computer and use it in GitHub Desktop.
Save mattdesl/4342861 to your computer and use it in GitHub Desktop.
package atmos.tool2d;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
/**
* A port of ShaderLesson4 from lwjgl-basics to LibGDX:
* https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson4
*
* @author davedes
*/
public class ShaderLesson4 implements ApplicationListener {
//Minor differences:
//LibGDX Position attribute is a vec4
//u_projView is called u_projTrans
//we need to set ShaderProgram.pedantic to false
//TexCoord attribute requires "0" appended at end to denote GL_TEXTURE0
//ShaderProgram.TEXCOORD_ATTRIBUTE+"0"
//It's wise to use LOWP when possible in GL ES
//In LibGDX ShaderProgram uses begin() and end()
//we can use Texture.bind(int) to bind a texture unit
//note that it will leave that unit active -- so we need to reset to zero after!
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.title = "Shader Lesson - LibGDX";
cfg.useGL20 = true;
cfg.width = 320;
cfg.height = 240;
cfg.resizable = false;
new LwjglApplication(new ShaderLesson4(), cfg);
}
final String VERT =
"attribute vec4 "+ShaderProgram.POSITION_ATTRIBUTE+";\n" +
"attribute vec4 "+ShaderProgram.COLOR_ATTRIBUTE+";\n" +
"attribute vec2 "+ShaderProgram.TEXCOORD_ATTRIBUTE+"0;\n" +
"uniform mat4 u_projTrans;\n" +
" \n" +
"varying vec4 vColor;\n" +
"varying vec2 vTexCoord;\n" +
"void main() {\n" +
" vColor = "+ShaderProgram.COLOR_ATTRIBUTE+";\n" +
" vTexCoord = "+ShaderProgram.TEXCOORD_ATTRIBUTE+"0;\n" +
" gl_Position = u_projTrans * " + ShaderProgram.POSITION_ATTRIBUTE + ";\n" +
"}";
final String FRAG =
//GL ES specific stuff
"#ifdef GL_ES\n" //
+ "#define LOWP lowp\n" //
+ "precision mediump float;\n" //
+ "#else\n" //
+ "#define LOWP \n" //
+ "#endif\n" + //
"varying LOWP vec4 vColor;\n" +
"varying vec2 vTexCoord;\n" +
"uniform sampler2D u_texture;\n" +
"uniform sampler2D u_texture1;\n" +
"uniform sampler2D u_mask;\n" +
"void main(void) {\n" +
" //sample the colour from the first texture\n" +
" vec4 texColor0 = texture2D(u_texture, vTexCoord);\n" +
"\n" +
" //sample the colour from the second texture\n" +
" vec4 texColor1 = texture2D(u_texture1, vTexCoord);\n" +
"\n" +
" //get the mask; we will only use the alpha channel\n" +
" float mask = texture2D(u_mask, vTexCoord).a;\n" +
"\n" +
" //interpolate the colours based on the mask\n" +
" gl_FragColor = vColor * mix(texColor0, texColor1, mask);\n" +
"}";
Texture tex0, tex1, mask;
SpriteBatch batch;
OrthographicCamera cam;
ShaderProgram shader;
@Override
public void create() {
tex0 = new Texture(Gdx.files.internal("data/grass.png"));
tex1 = new Texture(Gdx.files.internal("data/dirt.png"));
mask = new Texture(Gdx.files.internal("data/mask.png"));
//important since we aren't using some uniforms and attributes that SpriteBatch expects
ShaderProgram.pedantic = false;
//print it out for clarity
System.out.println("Vertex Shader:\n-------------\n\n"+VERT);
System.out.println("\n");
System.out.println("Fragment Shader:\n-------------\n\n"+FRAG);
shader = new ShaderProgram(VERT, FRAG);
if (!shader.isCompiled()) {
System.err.println(shader.getLog());
System.exit(0);
}
if (shader.getLog().length()!=0)
System.out.println(shader.getLog());
shader.begin();
shader.setUniformi("u_texture1", 1);
shader.setUniformi("u_mask", 2);
shader.end();
//bind mask to glActiveTexture(GL_TEXTURE2)
mask.bind(2);
//bind dirt to glActiveTexture(GL_TEXTURE1)
tex1.bind(1);
//now we need to reset glActiveTexture to zero!!!! since sprite batch does not do this for us
Gdx.gl.glActiveTexture(GL10.GL_TEXTURE0);
//tex0 will be bound when we call SpriteBatch.draw
batch = new SpriteBatch(1000, shader);
batch.setShader(shader);
cam = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
cam.setToOrtho(false);
}
@Override
public void resize(int width, int height) {
cam.setToOrtho(false, width, height);
batch.setProjectionMatrix(cam.combined);
}
@Override
public void render() {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(tex0, 0, 0);
batch.end();
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void dispose() {
batch.dispose();
shader.dispose();
tex0.dispose();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment