• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright 2011 See AUTHORS file.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  ******************************************************************************/
16 
17 package com.badlogic.gdx.tests.g3d;
18 
19 import com.badlogic.gdx.Gdx;
20 import com.badlogic.gdx.graphics.Camera;
21 import com.badlogic.gdx.graphics.Color;
22 import com.badlogic.gdx.graphics.GL20;
23 import com.badlogic.gdx.graphics.PerspectiveCamera;
24 import com.badlogic.gdx.graphics.VertexAttributes.Usage;
25 import com.badlogic.gdx.graphics.g3d.Attribute;
26 import com.badlogic.gdx.graphics.g3d.Material;
27 import com.badlogic.gdx.graphics.g3d.Model;
28 import com.badlogic.gdx.graphics.g3d.ModelBatch;
29 import com.badlogic.gdx.graphics.g3d.ModelInstance;
30 import com.badlogic.gdx.graphics.g3d.Renderable;
31 import com.badlogic.gdx.graphics.g3d.Shader;
32 import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
33 import com.badlogic.gdx.graphics.g3d.model.Node;
34 import com.badlogic.gdx.graphics.g3d.shaders.BaseShader;
35 import com.badlogic.gdx.graphics.g3d.utils.BaseShaderProvider;
36 import com.badlogic.gdx.graphics.g3d.utils.CameraInputController;
37 import com.badlogic.gdx.graphics.g3d.utils.DefaultShaderProvider;
38 import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
39 import com.badlogic.gdx.graphics.g3d.utils.RenderContext;
40 import com.badlogic.gdx.graphics.glutils.ShaderProgram;
41 import com.badlogic.gdx.math.MathUtils;
42 import com.badlogic.gdx.math.Matrix4;
43 import com.badlogic.gdx.tests.utils.GdxTest;
44 import com.badlogic.gdx.utils.Array;
45 import com.badlogic.gdx.utils.GdxRuntimeException;
46 
47 public class ShaderTest extends GdxTest {
48 	// Create a custom attribute, see https://github.com/libgdx/libgdx/wiki/Material-and-environment
49 	// See also: http://blog.xoppa.com/using-materials-with-libgdx/
50 	public static class TestAttribute extends Attribute {
51 		public final static String Alias = "Test";
52 		public final static long ID = register(Alias);
53 
54 		public float value;
55 
TestAttribute(final float value)56 		protected TestAttribute (final float value) {
57 			super(ID);
58 			this.value = value;
59 		}
60 
61 		@Override
copy()62 		public Attribute copy () {
63 			return new TestAttribute(value);
64 		}
65 
66 		@Override
equals(Attribute other)67 		protected boolean equals (Attribute other) {
68 			return ((TestAttribute)other).value == value;
69 		}
70 
71 		@Override
compareTo(Attribute o)72 		public int compareTo (Attribute o) {
73 			if (type != o.type) return type < o.type ? -1 : 1;
74 			float otherValue = ((TestAttribute)o).value;
75 			return MathUtils.isEqual(value, otherValue) ? 0 : (value < otherValue ? -1 : 1);
76 		}
77 	}
78 
79 	// Create a custom shader, see also http://blog.xoppa.com/creating-a-shader-with-libgdx
80 	// BaseShader adds some basic functionality used to manage uniforms etc.
81 	public static class TestShader extends BaseShader {
82 		// @off
83 		public final static String vertexShader =
84 			  "attribute vec3 a_position;\n"
85 			+ "uniform mat4 u_projTrans;\n"
86 			+ "uniform mat4 u_worldTrans;\n"
87 			+ "void main() {\n"
88 			+ "	gl_Position = u_projTrans * u_worldTrans * vec4(a_position, 1.0);\n"
89 			+ "}\n";
90 
91 		public final static String fragmentShader =
92 			  "#ifdef GL_ES\n"
93 			+ "#define LOWP lowp\n"
94 			+ "precision mediump float;\n"
95 			+ "#else\n"
96 			+ "#define LOWP\n"
97 			+ "#endif\n"
98 
99 			+ "uniform float u_test;\n"
100 			+ "#ifdef HasDiffuseColor\n"
101 			+ "uniform vec4 u_color;\n"
102 			+ "#endif //HasDiffuseColor\n"
103 
104 			+ "void main() {\n"
105 			+ "#ifdef HasDiffuseColor\n"
106 			+ "	gl_FragColor.rgb = u_color.rgb * vec3(u_test);\n"
107 			+ "#else\n"
108 			+ "	gl_FragColor.rgb = vec3(u_test);\n"
109 			+ "#endif //HasDiffuseColor\n"
110 			+ "}\n";
111 		// @on
112 
113 		protected final int u_projTrans = register(new Uniform("u_projTrans"));
114 		protected final int u_worldTrans = register(new Uniform("u_worldTrans"));
115 		protected final int u_test = register(new Uniform("u_test"));
116 		protected final int u_color = register(new Uniform("u_color"));
117 
118 		protected final ShaderProgram program;
119 		private boolean withColor;
120 
TestShader(Renderable renderable)121 		public TestShader (Renderable renderable) {
122 			super();
123 			withColor = renderable.material.has(ColorAttribute.Diffuse);
124 			if (withColor)
125 				Gdx.app.log("ShaderTest", "Compiling test shader with u_color uniform");
126 			else
127 				Gdx.app.log("ShaderTest", "Compiling test shader without u_color uniform");
128 
129 			String prefix = withColor ? "#define HasDiffuseColor\n" : "";
130 			program = new ShaderProgram(vertexShader, prefix + fragmentShader);
131 
132 			if (!program.isCompiled()) throw new GdxRuntimeException("Couldn't compile shader " + program.getLog());
133 			String log = program.getLog();
134 			if (log.length() > 0) Gdx.app.error("ShaderTest", "Shader compilation log: " + log);
135 		}
136 
137 		@Override
init()138 		public void init () {
139 			super.init(program, null);
140 		}
141 
142 		@Override
compareTo(Shader other)143 		public int compareTo (Shader other) {
144 			return 0;
145 		}
146 
147 		@Override
canRender(Renderable instance)148 		public boolean canRender (Renderable instance) {
149 			return instance.material.has(TestAttribute.ID) && (instance.material.has(ColorAttribute.Diffuse) == withColor);
150 		}
151 
152 		@Override
begin(Camera camera, RenderContext context)153 		public void begin (Camera camera, RenderContext context) {
154 			program.begin();
155 			context.setDepthTest(GL20.GL_LEQUAL, 0f, 1f);
156 			context.setDepthMask(true);
157 			set(u_projTrans, camera.combined);
158 		}
159 
160 		@Override
render(Renderable renderable)161 		public void render (Renderable renderable) {
162 			set(u_worldTrans, renderable.worldTransform);
163 
164 			TestAttribute testAttr = (TestAttribute)renderable.material.get(TestAttribute.ID);
165 			set(u_test, testAttr.value);
166 
167 			if (withColor) {
168 				ColorAttribute colorAttr = (ColorAttribute)renderable.material.get(ColorAttribute.Diffuse);
169 				set(u_color, colorAttr.color);
170 			}
171 
172 			renderable.meshPart.render(program);
173 		}
174 
175 		@Override
end()176 		public void end () {
177 			program.end();
178 		}
179 
180 		@Override
dispose()181 		public void dispose () {
182 			super.dispose();
183 			program.dispose();
184 		}
185 	}
186 
187 	public PerspectiveCamera cam;
188 	public CameraInputController camController;
189 	public ModelBatch modelBatch;
190 	public Model model;
191 	public Array<ModelInstance> instances = new Array<ModelInstance>();
192 	public TestAttribute testAttribute1, testAttribute2;
193 
194 	@Override
create()195 	public void create () {
196 		modelBatch = new ModelBatch(new DefaultShaderProvider() {
197 			@Override
198 			protected Shader createShader (Renderable renderable) {
199 				if (renderable.material.has(TestAttribute.ID)) return new TestShader(renderable);
200 				return super.createShader(renderable);
201 			}
202 		});
203 
204 		cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
205 		cam.position.set(0f, 0f, 20f);
206 		cam.lookAt(0, 0, 0);
207 		cam.near = 1f;
208 		cam.far = 300f;
209 		cam.update();
210 
211 		camController = new CameraInputController(cam);
212 		Gdx.input.setInputProcessor(camController);
213 
214 		Material testMaterial1 = new Material("TestMaterial1", new TestAttribute(1f));
215 		Material redMaterial = new Material("RedMaterial", ColorAttribute.createDiffuse(Color.RED));
216 		Material testMaterial2 = new Material("TestMaterial2", new TestAttribute(1f), ColorAttribute.createDiffuse(Color.BLUE));
217 
218 		ModelBuilder builder = new ModelBuilder();
219 		Node node;
220 
221 		builder.begin();
222 		node = builder.node();
223 		node.id = "testCone1";
224 		node.translation.set(-10, 0f, 0f);
225 		builder.part("testCone", GL20.GL_TRIANGLES, Usage.Position, testMaterial1).cone(5, 5, 5, 20);
226 
227 		node = builder.node();
228 		node.id = "redSphere";
229 		builder.part("redSphere", GL20.GL_TRIANGLES, Usage.Position, redMaterial).sphere(5, 5, 5, 20, 20);
230 
231 		node = builder.node();
232 		node.id = "testCone1";
233 		node.translation.set(10, 0f, 0f);
234 		builder.part("testCone", GL20.GL_TRIANGLES, Usage.Position, testMaterial2).cone(5, 5, 5, 20);
235 
236 		model = builder.end();
237 
238 		ModelInstance modelInstance;
239 		modelInstance = new ModelInstance(model);
240 		testAttribute1 = (TestAttribute)modelInstance.getMaterial("TestMaterial1").get(TestAttribute.ID);
241 		testAttribute2 = (TestAttribute)modelInstance.getMaterial("TestMaterial2").get(TestAttribute.ID);
242 		instances.add(modelInstance);
243 	}
244 
245 	private float counter;
246 
247 	@Override
render()248 	public void render () {
249 		counter = (counter + Gdx.graphics.getDeltaTime()) % 2.f;
250 		testAttribute1.value = Math.abs(1f - counter);
251 		testAttribute2.value = 1f - testAttribute1.value;
252 
253 		camController.update();
254 
255 		Gdx.gl.glViewport(0, 0, Gdx.graphics.getBackBufferWidth(), Gdx.graphics.getBackBufferHeight());
256 		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
257 
258 		modelBatch.begin(cam);
259 		modelBatch.render(instances);
260 		modelBatch.end();
261 	}
262 
263 	@Override
dispose()264 	public void dispose () {
265 		modelBatch.dispose();
266 		model.dispose();
267 	}
268 }
269