Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package atmos;
- import com.badlogic.gdx.ApplicationListener;
- import com.badlogic.gdx.Gdx;
- import com.badlogic.gdx.Input.Keys;
- import com.badlogic.gdx.InputAdapter;
- 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.g2d.TextureRegion;
- import com.badlogic.gdx.graphics.glutils.ShaderProgram;
- import com.badlogic.gdx.math.Matrix4;
- import com.badlogic.gdx.math.Vector2;
- import com.badlogic.gdx.math.Vector3;
- /**
- * Simple illumination model with shaders in LibGDX.
- * @author davedes / mattdesl
- */
- public class Illumination2D implements ApplicationListener {
- Texture texture, texture_n;
- OrthographicCamera cam;
- SpriteBatch fxBatch, batch;
- TextureRegion sprite, spriteNormals;
- Matrix4 transform = new Matrix4();
- // the color of our light
- Vector3 lightColor = new Vector3(1f, 1f, 1f);
- // the position of our light in 3D space
- Vector3 lightPos = new Vector3(0f, 0f, 2f);
- // the ambient color (color to use when unlit)
- Vector3 ambientColor = new Vector3(1f, 1f, 1f);
- // the resolution of our game/graphics
- Vector2 resolution = new Vector2();
- // the attenuation factor: x=constant, y=linear, z=quadratic
- Vector3 attenuation = new Vector3(0.75f, 0.0f, 0.00001f);
- // the ambient intensity (brightness to use when unlit)
- float ambientIntensity = 0.1f;
- // whether to use attenuation/shadows
- boolean useShadow = true;
- // whether to use lambert shading (with our normal map)
- boolean useNormals = true;
- ShaderProgram program;
- public void create() {
- // load our textures
- texture = new Texture(Gdx.files.internal("data/rock.png"));
- texture_n = new Texture(Gdx.files.internal("data/rock_n.png"));
- // we'll use texture regions instead of Stage2D/Actors for simplicity's sake
- sprite = new TextureRegion(texture);
- sprite.flip(false, true);
- spriteNormals = new TextureRegion(texture_n);
- spriteNormals.flip(false, true);
- // a simple 2D orthographic camera
- cam = new OrthographicCamera(Gdx.graphics.getWidth(),
- Gdx.graphics.getHeight());
- cam.setToOrtho(true);
- // create our shader program...
- program = createShader();
- // now we create our sprite batch for our shader
- fxBatch = new SpriteBatch(100, program);
- // setShader is needed; perhaps this is a LibGDX bug?
- fxBatch.setShader(program);
- fxBatch.setProjectionMatrix(cam.combined);
- fxBatch.setTransformMatrix(transform);
- // usually we would just use a single batch for our application,
- // but for demonstration let's also show the un-affected image
- batch = new SpriteBatch(100);
- batch.setProjectionMatrix(cam.combined);
- batch.setTransformMatrix(transform);
- // quick little input for debugging -- press S to toggle shadows, N to
- // toggle normals
- Gdx.input.setInputProcessor(new InputAdapter() {
- public boolean keyDown(int key) {
- if (key == Keys.S) {
- useShadow = !useShadow;
- return true;
- } else if (key == Keys.N) {
- useNormals = !useNormals;
- return true;
- }
- return false;
- }
- });
- }
- private ShaderProgram createShader() {
- // see the code here: http://pastebin.com/7fkh1ax8
- // simple illumination model using ambient, diffuse (lambert) and attenuation
- // see here: http://nccastaff.bournemouth.ac.uk/jmacey/CGF/slides/IlluminationModels4up.pdf
- String vert = "attribute vec4 " + ShaderProgram.POSITION_ATTRIBUTE + ";\n" //
- + "attribute vec4 " + ShaderProgram.COLOR_ATTRIBUTE + ";\n" //
- + "attribute vec2 " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n" //
- + "uniform mat4 u_proj;\n" //
- + "uniform mat4 u_trans;\n" //
- + "uniform mat4 u_projTrans;\n" //
- + "varying vec4 v_color;\n" //
- + "varying vec2 v_texCoords;\n" //
- + "\n" //
- + "void main()\n" //
- + "{\n" //
- + " v_color = " + ShaderProgram.COLOR_ATTRIBUTE + ";\n" //
- + " v_texCoords = " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n" //
- + " gl_Position = u_projTrans * " + ShaderProgram.POSITION_ATTRIBUTE + ";\n" //
- + "}\n";
- String frag = "#ifdef GL_ES\n" +
- "precision mediump float;\n" +
- "#endif\n" +
- "varying vec4 v_color;\n" +
- "varying vec2 v_texCoords;\n" +
- "uniform sampler2D u_texture;\n" +
- "uniform sampler2D u_normals;\n" +
- "uniform vec3 light;\n" +
- "uniform vec3 ambientColor;\n" +
- "uniform float ambientIntensity; \n" +
- "uniform vec2 resolution;\n" +
- "uniform vec3 lightColor;\n" +
- "uniform bool useNormals;\n" +
- "uniform bool useShadow;\n" +
- "uniform vec3 attenuation;\n" +
- "\n" +
- "void main() {\n" +
- " vec4 color = texture2D(u_texture, v_texCoords.st);\n" +
- " vec3 normal = normalize(texture2D(u_normals, v_texCoords.st).rgb * 2.0 - 1.0);\n" +
- " vec3 light_pos = normalize(light);\n" +
- " float lambert = useNormals ? max(dot(normal, light_pos), 0.0) : 1.0;\n" +
- " \n" +
- " //now let's get a nice little falloff\n" +
- " float d = distance(gl_FragCoord.xy, light.xy * resolution);\n" +
- " d *= light.z;\n" +
- " \n" +
- " float att = useShadow ? 1.0 / ( attenuation.x + (attenuation.y*d) + (attenuation.z*d*d) ) : 1.0;\n" +
- " \n" +
- " vec3 result = (ambientColor * ambientIntensity) + (lightColor.rgb * lambert) * att;\n" +
- " result *= color.rgb;\n" +
- " \n" +
- " gl_FragColor = v_color * vec4(result, color.a);\n" +
- "}";
- ShaderProgram program = new ShaderProgram(vert, frag);
- // u_proj and u_trans will not be active but SpriteBatch will still try to set them...
- program.pedantic = false;
- if (program.isCompiled() == false)
- throw new IllegalArgumentException("couldn't compile shader: "
- + program.getLog());
- // set resolution vector
- resolution.set(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
- // we are only using this many uniforms for testing purposes...!!
- program.begin();
- program.setUniformi("u_texture", 0);
- program.setUniformi("u_normals", 1);
- program.setUniformf("light", lightPos);
- program.setUniformf("ambientIntensity", ambientIntensity);
- program.setUniformf("ambientColor", ambientColor);
- program.setUniformf("resolution", resolution);
- program.setUniformf("lightColor", lightColor);
- program.setUniformf("attenuation", attenuation);
- program.setUniformi("useShadow", useShadow ? 1 : 0);
- program.setUniformi("useNormals", useNormals ? 1 : 0);
- program.end();
- return program;
- }
- public void dispose() {
- fxBatch.dispose();
- batch.dispose();
- texture.dispose();
- texture_n.dispose();
- }
- public void render() {
- Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
- cam.update();
- // draw our sprites without any effects
- batch.begin();
- batch.draw(sprite, 0, 0);
- batch.draw(spriteNormals, sprite.getRegionWidth() + 10, 0);
- batch.end();
- // start our FX batch, which will bind our shader program
- fxBatch.begin();
- // get y-down light position based on mouse/touch
- lightPos.x = Gdx.input.getX() / (float) Gdx.graphics.getWidth();
- lightPos.y = (resolution.y - Gdx.input.getY() - 1)
- / (float) Gdx.graphics.getHeight();
- // update our uniforms
- program.setUniformf("light", lightPos);
- program.setUniformi("useNormals", useNormals ? 1 : 0);
- program.setUniformi("useShadow", useShadow ? 1 : 0);
- // bind the normal first at texture1
- texture_n.bind(1);
- // bind the actual texture at texture0
- texture.bind(0);
- // we bind texture0 second since draw(sprite) will end up binding it at
- // texture0...
- fxBatch.draw(sprite, 0, sprite.getRegionHeight() + 10);
- fxBatch.end();
- }
- public void resize(int width, int height) {
- cam.setToOrtho(true, width, height);
- resolution.set(width, height);
- program.setUniformf("resolution", resolution);
- }
- public void pause() {
- }
- public void resume() {
- }
- public static void main(String[] args) {
- LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
- cfg.title = "lighting";
- cfg.useGL20 = true;
- cfg.width = 1024;
- cfg.height = 768;
- new LwjglApplication(new Illumination2D(), cfg);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement