Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

Untitled

By: a guest on Oct 16th, 2012  |  syntax: Java  |  size: 14.39 KB  |  views: 955  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
This paste has a previous version, view the difference. Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. package atmos;
  2.  
  3. import java.text.DecimalFormat;
  4. import java.text.MessageFormat;
  5. import java.util.Random;
  6.  
  7. import com.badlogic.gdx.ApplicationListener;
  8. import com.badlogic.gdx.Gdx;
  9. import com.badlogic.gdx.Input.Keys;
  10. import com.badlogic.gdx.InputAdapter;
  11. import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
  12. import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
  13. import com.badlogic.gdx.graphics.Color;
  14. import com.badlogic.gdx.graphics.GL10;
  15. import com.badlogic.gdx.graphics.OrthographicCamera;
  16. import com.badlogic.gdx.graphics.Pixmap;
  17. import com.badlogic.gdx.graphics.Pixmap.Format;
  18. import com.badlogic.gdx.graphics.Texture;
  19. import com.badlogic.gdx.graphics.g2d.BitmapFont;
  20. import com.badlogic.gdx.graphics.g2d.SpriteBatch;
  21. import com.badlogic.gdx.graphics.glutils.ShaderProgram;
  22. import com.badlogic.gdx.math.Matrix4;
  23. import com.badlogic.gdx.math.Vector2;
  24. import com.badlogic.gdx.math.Vector3;
  25.  
  26. /**
  27.  * Simple illumination model with shaders in LibGDX.
  28.  * @author davedes
  29.  */
  30. public class Illumination2D implements ApplicationListener {   
  31.  
  32.         Texture texture, texture_n;
  33.        
  34.         boolean flipY;
  35.         Texture normalBase;
  36.         OrthographicCamera cam;
  37.         SpriteBatch fxBatch, batch;
  38.        
  39.         Matrix4 transform = new Matrix4();
  40.  
  41.         Random rnd = new Random();
  42.  
  43.         // position of our light
  44.         final Vector3 DEFAULT_LIGHT_POS = new Vector3(0f, 0f, 0.07f);
  45.         // the color of our light
  46.         final Vector3 DEFAULT_LIGHT_COLOR = new Vector3(1f, 0.7f, 0.6f);
  47.         // the ambient color (color to use when unlit)
  48.         final Vector3 DEFAULT_AMBIENT_COLOR = new Vector3(0.3f, 0.3f, 1f);
  49.         // the attenuation factor: x=constant, y=linear, z=quadratic
  50.         final Vector3 DEFAULT_ATTENUATION = new Vector3(0.4f, 3f, 20f);
  51.         // the ambient intensity (brightness to use when unlit)
  52.         final float DEFAULT_AMBIENT_INTENSITY = 0.2f;
  53.         final float DEFAULT_STRENGTH = 1f;
  54.        
  55.         final Color NORMAL_VCOLOR = new Color(1f,1f,1f,DEFAULT_STRENGTH);
  56.        
  57.         // the position of our light in 3D space
  58.         Vector3 lightPos = new Vector3(DEFAULT_LIGHT_POS);
  59.         // the resolution of our game/graphics
  60.         Vector2 resolution = new Vector2();
  61.         // the current attenuation
  62.         Vector3 attenuation = new Vector3(DEFAULT_ATTENUATION);
  63.         // the current ambient intensity
  64.         float ambientIntensity = DEFAULT_AMBIENT_INTENSITY;
  65.         float strength = DEFAULT_STRENGTH;
  66.        
  67.         // whether to use attenuation/shadows
  68.         boolean useShadow = true;
  69.  
  70.         // whether to use lambert shading (with our normal map)
  71.         boolean useNormals = true;
  72.        
  73.         DecimalFormat DEC_FMT = new DecimalFormat("0.00000");
  74.  
  75.         ShaderProgram program;
  76.  
  77.         BitmapFont font;
  78.        
  79.         private int texWidth, texHeight;
  80.        
  81.         final String TEXT = "Use number keys to adjust parameters:\n" +
  82.                         "1: Randomize Ambient Color\n" +
  83.                         "2: Randomize Ambient Intensity {0}\n" +
  84.                         "3: Randomize Light Color\n" +
  85.                         "4/5: Increase/decrease constant attenuation: {1}\n" +
  86.                         "6/7: Increase/decrease linear attenuation: {2}\n" +
  87.                         "8/9: Increase/decrease quadratic attenuation: {3}\n" +
  88.                         "0: Reset parameters\n" +
  89.                         "RIGHT/LEFT: Increase/decrease normal map intensity: {4}\n" +
  90.                         "UP/DOWN: Increase/decrease lightDir.z: {5}\n\n" +
  91.                         "S toggles attenuation, N toggles normal shading\n" +
  92.                         "T to toggle textures";
  93.        
  94.         private Texture rock, rock_n, teapot, teapot_n;
  95.        
  96.         public void create() {
  97.                 // load our textures
  98.                 rock = new Texture(Gdx.files.internal("data/teapot.png"));
  99.                 rock_n = new Texture(Gdx.files.internal("data/teapot_n.png"));
  100.                 teapot = new Texture(Gdx.files.internal("data/rock.png"));
  101.                 teapot_n = new Texture(Gdx.files.internal("data/rock_n.png"));
  102.                
  103.                 texture = teapot;
  104.                 texture_n = teapot_n;
  105.                 flipY = texture==rock;
  106.                
  107.                 //we only use this to show what the strength-adjusted normal map looks like on screen
  108.                 Pixmap pix = new Pixmap(1, 1, Format.RGB565);
  109.                 pix.setColor(0.5f, 0.5f, 1.0f, 1.0f);
  110.                 pix.fill();
  111.                 normalBase = new Texture(pix);
  112.                
  113.                 texWidth = texture.getWidth();
  114.                 texHeight = texture.getHeight();
  115.                
  116.                 // a simple 2D orthographic camera
  117.                 cam = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
  118.                 cam.setToOrtho(false);
  119.  
  120.                 // create our shader program...
  121.                 program = createShader();
  122.  
  123.                 // now we create our sprite batch for our shader
  124.                 fxBatch = new SpriteBatch(100, program);
  125.                 // setShader is needed; perhaps this is a LibGDX bug?
  126.                 fxBatch.setShader(program);
  127.                 fxBatch.setProjectionMatrix(cam.combined);
  128.                 fxBatch.setTransformMatrix(transform);
  129.  
  130.                 // usually we would just use a single batch for our application,
  131.                 // but for demonstration let's also show the un-affected image
  132.                 batch = new SpriteBatch(100);
  133.                 batch.setProjectionMatrix(cam.combined);
  134.                 batch.setTransformMatrix(transform);
  135.  
  136.                 // quick little input for debugging -- press S to toggle shadows, N to
  137.                 // toggle normals
  138.                 Gdx.input.setInputProcessor(new InputAdapter() {
  139.                         public boolean keyDown(int key) {
  140.                                 if (key == Keys.S) {
  141.                                         useShadow = !useShadow;
  142.                                         return true;
  143.                                 } else if (key == Keys.N) {
  144.                                         useNormals = !useNormals;
  145.                                         return true;
  146.                                 } else if (key == Keys.NUM_1) {
  147.                                         program.begin();
  148.                                         program.setUniformf("ambientColor", rndColor());
  149.                                         program.end();
  150.                                         return true;
  151.                                 } else if (key == Keys.NUM_2) {
  152.                                         ambientIntensity = rnd.nextFloat();
  153.                                         return true;
  154.                                 } else if (key == Keys.NUM_3) {
  155.                                         program.begin();
  156.                                         program.setUniformf("lightColor", rndColor());
  157.                                         program.end();
  158.                                         return true;
  159.                                 } else if (key == Keys.NUM_0) {
  160.                                         attenuation.set(DEFAULT_ATTENUATION);
  161.                                         ambientIntensity = DEFAULT_AMBIENT_INTENSITY;
  162.                                         lightPos.set(DEFAULT_LIGHT_POS);
  163.                                         strength = DEFAULT_STRENGTH;
  164.                                         program.begin();
  165.                                         program.setUniformf("lightColor", DEFAULT_LIGHT_COLOR);
  166.                                         program.setUniformf("ambientColor", DEFAULT_AMBIENT_COLOR);
  167.                                         program.setUniformf("ambientIntensity", ambientIntensity);
  168.                                         program.setUniformf("attenuation", attenuation);
  169.                                         program.setUniformf("lightPos", lightPos);
  170.                                         program.setUniformf("strength", strength);
  171.                                         program.end();
  172.                                 } else if (key == Keys.T) {
  173.                                         texture = texture==teapot ? rock : teapot;
  174.                                         texture_n = texture_n==teapot_n ? rock_n : teapot_n;
  175.                                         flipY = texture==rock;
  176.                                         texWidth = texture.getWidth();
  177.                                         texHeight = texture.getHeight();
  178.                                         program.begin();
  179.                                         program.setUniformi("yInvert", flipY ? 1 : 0);
  180.                                         program.end();
  181.                                 }
  182.                                 return false;
  183.                         }
  184.                 });
  185.                
  186.                 font = new BitmapFont();
  187.         }
  188.        
  189.         private Vector3 rndColor() {
  190.                 return new Vector3(rnd.nextFloat(), rnd.nextFloat(), rnd.nextFloat());
  191.         }
  192.  
  193.         private ShaderProgram createShader() {
  194.                 // see the code here: http://pastebin.com/7fkh1ax8
  195.                 // simple illumination model using ambient, diffuse (lambert) and attenuation
  196.                 // see here: http://nccastaff.bournemouth.ac.uk/jmacey/CGF/slides/IlluminationModels4up.pdf
  197.                 String vert = "attribute vec4 " + ShaderProgram.POSITION_ATTRIBUTE + ";\n" //
  198.                                 + "attribute vec4 " + ShaderProgram.COLOR_ATTRIBUTE + ";\n" //
  199.                                 + "attribute vec2 " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n" //
  200.                                 + "uniform mat4 u_proj;\n" //
  201.                                 + "uniform mat4 u_trans;\n" //
  202.                                 + "uniform mat4 u_projTrans;\n" //
  203.                                 + "varying vec4 v_color;\n" //
  204.                                 + "varying vec2 v_texCoords;\n" //
  205.                                 + "\n" //
  206.                                 + "void main()\n" //
  207.                                 + "{\n" //
  208.                                 + "   v_color = " + ShaderProgram.COLOR_ATTRIBUTE + ";\n" //
  209.                                 + "   v_texCoords = " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n" //
  210.                                 + "   gl_Position =  u_projTrans * " + ShaderProgram.POSITION_ATTRIBUTE + ";\n" //
  211.                                 + "}\n";
  212.                
  213.                 String frag = "#ifdef GL_ES\n" +
  214.                                 "precision mediump float;\n" +
  215.                                 "#endif\n" +
  216.                                 "varying vec4 v_color;\n" +
  217.                                 "varying vec2 v_texCoords;\n" +
  218.                                
  219.                                 "uniform sampler2D u_texture;\n" +
  220.                                 "uniform sampler2D u_normals;\n" +
  221.                                 "uniform vec3 light;\n" +
  222.                                 "uniform vec3 ambientColor;\n" +
  223.                                 "uniform float ambientIntensity; \n" +
  224.                                 "uniform vec2 resolution;\n" +
  225.                                 "uniform vec3 lightColor;\n" +
  226.                                 "uniform bool useNormals;\n" +
  227.                                 "uniform bool useShadow;\n" +
  228.                                 "uniform vec3 attenuation;\n" +
  229.                                 "uniform float strength;\n" +
  230.                                 "uniform bool yInvert;\n"+
  231.                                 "\n" +
  232.                                 "void main() {\n" +
  233.                                 "       //sample color & normals from our textures\n" +
  234.                                 "       vec4 color = texture2D(u_texture, v_texCoords.st);\n" +
  235.                                 "       vec3 nColor = texture2D(u_normals, v_texCoords.st).rgb;\n\n" +
  236.                                 "       //some bump map programs will need the Y value flipped..\n" +
  237.                                 "       nColor.g = yInvert ? 1.0 - nColor.g : nColor.g;\n\n" +
  238.                                 "       //this is for debugging purposes, allowing us to lower the intensity of our bump map\n" +
  239.                                 "       vec3 nBase = vec3(0.5, 0.5, 1.0);\n" +
  240.                                 "       nColor = mix(nBase, nColor, strength);\n\n" +
  241.                                 "       //normals need to be converted to [-1.0, 1.0] range and normalized\n" +
  242.                                 "       vec3 normal = normalize(nColor * 2.0 - 1.0);\n\n" +
  243.                                 "       //here we do a simple distance calculation\n" +
  244.                                 "       vec3 deltaPos = vec3( (light.xy - gl_FragCoord.xy) / resolution.xy, light.z );\n\n" +
  245.                                 "       vec3 lightDir = normalize(deltaPos);\n" +
  246.                                 "       float lambert = useNormals ? clamp(dot(normal, lightDir), 0.0, 1.0) : 1.0;\n" +
  247.                                 "       \n" +
  248.                                 "       //now let's get a nice little falloff\n" +
  249.                                 "       float d = sqrt(dot(deltaPos, deltaPos));"+
  250.                                 "       \n" +
  251.                                 "       float att = useShadow ? 1.0 / ( attenuation.x + (attenuation.y*d) + (attenuation.z*d*d) ) : 1.0;\n" +
  252.                                 "       \n" +
  253.                                 "       vec3 result = (ambientColor * ambientIntensity) + (lightColor.rgb * lambert) * att;\n" +
  254.                                 "       result *= color.rgb;\n" +
  255.                                 "       \n" +
  256.                                 "       gl_FragColor = v_color * vec4(result, color.a);\n" +
  257.                                 "}";
  258.                 System.out.println("VERTEX PROGRAM:\n------------\n\n"+vert);
  259.                 System.out.println("FRAGMENT PROGRAM:\n------------\n\n"+frag);
  260.                 ShaderProgram program = new ShaderProgram(vert, frag);
  261.                 // u_proj and u_trans will not be active but SpriteBatch will still try to set them...
  262.                 program.pedantic = false;
  263.                 if (program.isCompiled() == false)
  264.                         throw new IllegalArgumentException("couldn't compile shader: "
  265.                                         + program.getLog());
  266.  
  267.                 // set resolution vector
  268.                 resolution.set(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
  269.  
  270.                 // we are only using this many uniforms for testing purposes...!!
  271.                 program.begin();
  272.                 program.setUniformi("u_texture", 0);
  273.                 program.setUniformi("u_normals", 1);
  274.                 program.setUniformf("light", lightPos);
  275.                 program.setUniformf("strength", strength);
  276.                 program.setUniformf("ambientIntensity", ambientIntensity);
  277.                 program.setUniformf("ambientColor", DEFAULT_AMBIENT_COLOR);
  278.                 program.setUniformf("resolution", resolution);
  279.                 program.setUniformf("lightColor", DEFAULT_LIGHT_COLOR);
  280.                 program.setUniformf("attenuation", attenuation);
  281.                 program.setUniformi("useShadow", useShadow ? 1 : 0);
  282.                 program.setUniformi("useNormals", useNormals ? 1 : 0);
  283.                 program.setUniformi("yInvert", flipY ? 1 : 0);
  284.                 program.end();
  285.  
  286.                 return program;
  287.         }
  288.  
  289.         public void dispose() {
  290.                 fxBatch.dispose();
  291.                 batch.dispose();
  292.                 texture.dispose();
  293.                 texture_n.dispose();
  294.         }
  295.        
  296.         public void render() {
  297.                 Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
  298.                
  299.                 // draw our sprites without any effects
  300.                 batch.begin();
  301.                
  302.                 final int IMG_Y = texHeight/2;
  303.                
  304.                 //let's first simulate our resulting normal map by blending a blue square atop it
  305.                 //we also could have achieved this with glTexEnv in the fixed function pipeline
  306.                 NORMAL_VCOLOR.a = 1.0f - strength;
  307.                 batch.draw(texture_n, texWidth + 10, IMG_Y);
  308.                 batch.setColor(NORMAL_VCOLOR);
  309.                 batch.draw(normalBase, texWidth + 10, IMG_Y, texWidth, texHeight);
  310.                 batch.setColor(Color.WHITE);
  311.                 batch.draw(texture, 0, IMG_Y);
  312.                 //now let's simulate how our normal map will be sampled using strength
  313.                 //we can do this simply by blending a blue fill overtop
  314.                
  315.                 String str = MessageFormat.format(TEXT, ambientIntensity,
  316.                                 attenuation.x, attenuation.y, DEC_FMT.format(attenuation.z),
  317.                                 strength, lightPos.z);
  318.                 font.drawMultiLine(batch, str, 10, Gdx.graphics.getHeight()-10);
  319.                
  320.                 font.draw(batch, "Diffuse Color", 10, IMG_Y+texHeight + 30);
  321.                 font.draw(batch, "Normal Map", texWidth+20, IMG_Y+texHeight + 30);
  322.                 font.draw(batch, "Final Color", texWidth*2+30, IMG_Y+texHeight + 30);
  323.                 batch.end();
  324.                
  325.                 // start our FX batch, which will bind our shader program
  326.                 fxBatch.begin();
  327.                
  328.                 // get y-down light position based on mouse/touch
  329.                 lightPos.x = Gdx.input.getX();
  330.                 lightPos.y = Gdx.graphics.getHeight() - Gdx.input.getY();
  331.                
  332.                 // handle attenuation input
  333.                 if (Gdx.input.isKeyPressed(Keys.NUM_4)) {
  334.                         attenuation.x += 0.025f;
  335.                 } else if (Gdx.input.isKeyPressed(Keys.NUM_5)) {
  336.                         attenuation.x -= 0.025f;
  337.                         if (attenuation.x < 0)
  338.                                 attenuation.x = 0;
  339.                 } else if (Gdx.input.isKeyPressed(Keys.NUM_6)) {
  340.                         attenuation.y += 0.25f;
  341.                 } else if (Gdx.input.isKeyPressed(Keys.NUM_7)) {
  342.                         attenuation.y -= 0.25f;
  343.                         if (attenuation.y < 0)
  344.                                 attenuation.y = 0;
  345.                 } else if (Gdx.input.isKeyPressed(Keys.NUM_8)) {
  346.                         attenuation.z += 0.25f;
  347.                 } else if (Gdx.input.isKeyPressed(Keys.NUM_9)) {
  348.                         attenuation.z -= 0.25f;
  349.                         if (attenuation.z < 0)
  350.                                 attenuation.z = 0;
  351.                 } else if (Gdx.input.isKeyPressed(Keys.RIGHT)) {
  352.                         strength += 0.025f;
  353.                         if (strength > 1f)
  354.                                 strength = 1f;
  355.                 } else if (Gdx.input.isKeyPressed(Keys.LEFT)) {
  356.                         strength -= 0.025f;
  357.                         if (strength < 0)
  358.                                 strength = 0;
  359.                 } else if (Gdx.input.isKeyPressed(Keys.UP)) {
  360.                         lightPos.z += 0.0025f;
  361.                 } else if (Gdx.input.isKeyPressed(Keys.DOWN)) {
  362.                         lightPos.z -= 0.0025f;
  363.                 }
  364.                
  365.                 // update our uniforms
  366.                 program.setUniformf("ambientIntensity", ambientIntensity);
  367.                 program.setUniformf("attenuation", attenuation);
  368.                 program.setUniformf("light", lightPos);
  369.                 program.setUniformi("useNormals", useNormals ? 1 : 0);
  370.                 program.setUniformi("useShadow", useShadow ? 1 : 0);
  371.                 program.setUniformf("strength", strength);
  372.                
  373.                 // bind the normal first at texture1
  374.                 texture_n.bind(1);
  375.                
  376.                 // bind the actual texture at texture0
  377.                 texture.bind(0);
  378.                
  379.                 // we bind texture0 second since draw(texture) will end up binding it at
  380.                 // texture0...
  381.                 fxBatch.draw(texture, texWidth*2 + 20, IMG_Y);
  382.                 fxBatch.end();
  383.         }
  384.  
  385.         public void resize(int width, int height) {
  386.                 cam.setToOrtho(false, width, height);
  387.                 resolution.set(width, height);
  388.                 program.setUniformf("resolution", resolution);
  389.         }
  390.  
  391.         public void pause() {
  392.         }
  393.  
  394.         public void resume() {
  395.         }
  396.  
  397.         public static void main(String[] args) {
  398.                 LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
  399.                 cfg.title = "Lighting Test";
  400.                 cfg.useGL20 = true;
  401.                 cfg.width = 1024;
  402.                 cfg.height = 768;
  403.                 cfg.resizable = false;
  404.  
  405.                 new LwjglApplication(new Illumination2D(), cfg);
  406.         }
  407. }