소스 검색

Example showing lighting with normals.

NathanSweet 12 년 전
부모
커밋
09a0ac5bbc

+ 222 - 0
spine-libgdx/test/com/esotericsoftware/spine/NormalMapTest.java

@@ -0,0 +1,222 @@
+/******************************************************************************
+ * Spine Runtime Software License - Version 1.1
+ * 
+ * Copyright (c) 2013, Esoteric Software
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms in whole or in part, with
+ * or without modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. A Spine Essential, Professional, Enterprise, or Education License must
+ *    be purchased from Esoteric Software and the license must remain valid:
+ *    http://esotericsoftware.com/
+ * 2. Redistributions of source code must retain this license, which is the
+ *    above copyright notice, this declaration of conditions and the following
+ *    disclaimer.
+ * 3. Redistributions in binary form must reproduce this license, which is the
+ *    above copyright notice, this declaration of conditions and the following
+ *    disclaimer, in the documentation and/or other materials provided with the
+ *    distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+package com.esotericsoftware.spine;
+
+import com.badlogic.gdx.ApplicationAdapter;
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
+import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.GL10;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.SpriteBatch;
+import com.badlogic.gdx.graphics.g2d.TextureAtlas;
+import com.badlogic.gdx.graphics.glutils.ShaderProgram;
+import com.badlogic.gdx.math.Vector2;
+import com.badlogic.gdx.math.Vector3;
+
+public class NormalMapTest extends ApplicationAdapter {
+	SpriteBatch batch;
+	float time;
+	SkeletonRenderer renderer;
+	Texture atlasTexture, normalMapTexture;
+	ShaderProgram program;
+
+	SkeletonData skeletonData;
+	Skeleton skeleton;
+	Animation animation;
+
+	final Vector3 ambientColor = new Vector3(1, 1, 1);
+	final Vector3 lightColor = new Vector3(1, 0.7f, 0.6f);
+	final Vector3 lightPosition = new Vector3(0, 0, 0.07f);
+	final Vector2 resolution = new Vector2();
+	final Vector3 attenuation = new Vector3(0.4f, 3.0f, 5);
+	float ambientIntensity = 0.35f;
+	float strength = 1.0f;
+	boolean useShadow = true;
+	boolean useNormals = true;
+	boolean flipY = false;
+
+	public void create () {
+		program = createShader();
+		batch = new SpriteBatch();
+		batch.setShader(program);
+		renderer = new SkeletonRenderer();
+
+		TextureAtlas atlas = new TextureAtlas(Gdx.files.internal("spineboy-ws.atlas"));
+		atlasTexture = atlas.getRegions().first().getTexture();
+		normalMapTexture = new Texture(Gdx.files.internal("spineboy-normal.png"));
+
+		SkeletonJson json = new SkeletonJson(atlas);
+		// json.setScale(2);
+		skeletonData = json.readSkeletonData(Gdx.files.internal("spineboy.json"));
+		animation = skeletonData.findAnimation("walk");
+
+		skeleton = new Skeleton(skeletonData);
+		skeleton.setToSetupPose();
+		skeleton = new Skeleton(skeleton);
+		skeleton.setX(200);
+		skeleton.setY(100);
+		skeleton.updateWorldTransform();
+	}
+
+	public void render () {
+		float lastTime = time;
+		time += Gdx.graphics.getDeltaTime();
+		animation.apply(skeleton, lastTime, time, true, null);
+		skeleton.updateWorldTransform();
+		skeleton.update(Gdx.graphics.getDeltaTime());
+
+		lightPosition.x = Gdx.input.getX();
+		lightPosition.y = (Gdx.graphics.getHeight() - Gdx.input.getY());
+
+		Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
+
+		batch.begin();
+		program.setUniformf("ambientIntensity", ambientIntensity);
+		program.setUniformf("attenuation", attenuation);
+		program.setUniformf("light", lightPosition);
+		program.setUniformi("useNormals", useNormals ? 1 : 0);
+		program.setUniformi("useShadow", useShadow ? 1 : 0);
+		program.setUniformf("strength", strength);
+		normalMapTexture.bind(1);
+		atlasTexture.bind(0);
+		renderer.draw(batch, skeleton);
+		batch.end();
+	}
+
+	public void resize (int width, int height) {
+		batch.getProjectionMatrix().setToOrtho2D(0, 0, width, height);
+	}
+
+	private ShaderProgram createShader () {
+		String vert = "attribute vec4 a_position;\n" //
+			+ "attribute vec4 a_color;\n" //
+			+ "attribute vec2 a_texCoord0;\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 = a_color;\n" //
+			+ "   v_texCoords = a_texCoord0;\n" //
+			+ "   gl_Position =  u_projTrans * a_position;\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" //
+			+ "uniform float strength;\n" //
+			+ "uniform bool yInvert;\n" //
+			+ "\n" //
+			+ "void main() {\n" //
+			+ "  // sample color & normals from our textures\n" //
+			+ "  vec4 color = texture2D(u_texture, v_texCoords.st);\n" //
+			+ "  vec3 nColor = texture2D(u_normals, v_texCoords.st).rgb;\n" //
+			+ "\n" //
+			+ "  // some bump map programs will need the Y value flipped..\n" //
+			+ "  nColor.g = yInvert ? 1.0 - nColor.g : nColor.g;\n" //
+			+ "\n" //
+			+ "  // this is for debugging purposes, allowing us to lower the intensity of our bump map\n" //
+			+ "  vec3 nBase = vec3(0.5, 0.5, 1.0);\n" //
+			+ "  nColor = mix(nBase, nColor, strength);\n" //
+			+ "\n" //
+			+ "  // normals need to be converted to [-1.0, 1.0] range and normalized\n" //
+			+ "  vec3 normal = normalize(nColor * 2.0 - 1.0);\n" //
+			+ "\n" //
+			+ "  // here we do a simple distance calculation\n" //
+			+ "  vec3 deltaPos = vec3( (light.xy - gl_FragCoord.xy) / resolution.xy, light.z );\n" //
+			+ "\n" //
+			+ "  vec3 lightDir = normalize(deltaPos);\n" //
+			+ "  float lambert = useNormals ? clamp(dot(normal, lightDir), 0.0, 1.0) : 1.0;\n" //
+			+ "  \n" //
+			+ "  // now let's get a nice little falloff\n" //
+			+ "  float d = sqrt(dot(deltaPos, deltaPos));  \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" //
+			+ "}";
+
+		System.out.println("VERTEX PROGRAM:\n------------\n\n" + vert);
+		System.out.println("FRAGMENT PROGRAM:\n------------\n\n" + frag);
+		ShaderProgram program = new ShaderProgram(vert, frag);
+
+		ShaderProgram.pedantic = false;
+		if (!program.isCompiled()) throw new IllegalArgumentException("Error compiling shader: " + program.getLog());
+
+		resolution.set(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
+
+		program.begin();
+		program.setUniformi("u_texture", 0);
+		program.setUniformi("u_normals", 1);
+		program.setUniformf("light", lightPosition);
+		program.setUniformf("strength", strength);
+		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.setUniformi("yInvert", flipY ? 1 : 0);
+		program.end();
+
+		return program;
+	}
+
+	public static void main (String[] args) throws Exception {
+		LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
+		config.useGL20 = true;
+		new LwjglApplication(new NormalMapTest(), config);
+	}
+}

BIN
spine-libgdx/test/spineboy-normal.png


+ 166 - 0
spine-libgdx/test/spineboy-ws.atlas

@@ -0,0 +1,166 @@
+
+spineboy-ws.png
+format: RGBA8888
+filter: Linear,Linear
+repeat: none
+eyes
+  rotate: false
+  xy: 230, 102
+  size: 34, 27
+  orig: 34, 27
+  offset: 0, 0
+  index: -1
+eyes-closed
+  rotate: true
+  xy: 273, 163
+  size: 34, 27
+  orig: 34, 27
+  offset: 0, 0
+  index: -1
+head
+  rotate: false
+  xy: 2, 120
+  size: 121, 132
+  orig: 121, 132
+  offset: 0, 0
+  index: -1
+left-ankle
+  rotate: false
+  xy: 118, 50
+  size: 25, 32
+  orig: 25, 32
+  offset: 0, 0
+  index: -1
+left-arm
+  rotate: false
+  xy: 230, 131
+  size: 35, 29
+  orig: 35, 29
+  offset: 0, 0
+  index: -1
+left-foot
+  rotate: false
+  xy: 381, 222
+  size: 65, 30
+  orig: 65, 30
+  offset: 0, 0
+  index: -1
+left-hand
+  rotate: true
+  xy: 233, 162
+  size: 35, 38
+  orig: 35, 38
+  offset: 0, 0
+  index: -1
+left-lower-leg
+  rotate: false
+  xy: 125, 122
+  size: 49, 64
+  orig: 49, 64
+  offset: 0, 0
+  index: -1
+left-pant-bottom
+  rotate: false
+  xy: 2, 2
+  size: 44, 22
+  orig: 44, 22
+  offset: 0, 0
+  index: -1
+left-shoulder
+  rotate: true
+  xy: 448, 218
+  size: 34, 53
+  orig: 34, 53
+  offset: 0, 0
+  index: -1
+left-upper-leg
+  rotate: true
+  xy: 243, 219
+  size: 33, 67
+  orig: 33, 67
+  offset: 0, 0
+  index: -1
+neck
+  rotate: true
+  xy: 118, 84
+  size: 34, 28
+  orig: 34, 28
+  offset: 0, 0
+  index: -1
+pelvis
+  rotate: false
+  xy: 178, 205
+  size: 63, 47
+  orig: 63, 47
+  offset: 0, 0
+  index: -1
+right-ankle
+  rotate: false
+  xy: 182, 90
+  size: 25, 30
+  orig: 25, 30
+  offset: 0, 0
+  index: -1
+right-arm
+  rotate: true
+  xy: 72, 25
+  size: 21, 45
+  orig: 21, 45
+  offset: 0, 0
+  index: -1
+right-foot
+  rotate: false
+  xy: 312, 222
+  size: 67, 30
+  orig: 67, 30
+  offset: 0, 0
+  index: -1
+right-foot-idle
+  rotate: false
+  xy: 178, 175
+  size: 53, 28
+  orig: 53, 28
+  offset: 0, 0
+  index: -1
+right-hand
+  rotate: false
+  xy: 148, 88
+  size: 32, 32
+  orig: 32, 32
+  offset: 0, 0
+  index: -1
+right-lower-leg
+  rotate: false
+  xy: 125, 188
+  size: 51, 64
+  orig: 51, 64
+  offset: 0, 0
+  index: -1
+right-pant-bottom
+  rotate: false
+  xy: 243, 199
+  size: 46, 18
+  orig: 46, 18
+  offset: 0, 0
+  index: -1
+right-shoulder
+  rotate: false
+  xy: 176, 122
+  size: 52, 51
+  orig: 52, 51
+  offset: 0, 0
+  index: -1
+right-upper-leg
+  rotate: false
+  xy: 72, 48
+  size: 44, 70
+  orig: 44, 70
+  offset: 0, 0
+  index: -1
+torso
+  rotate: false
+  xy: 2, 26
+  size: 68, 92
+  orig: 68, 92
+  offset: 0, 0
+  index: -1

BIN
spine-libgdx/test/spineboy-ws.png