com.badlogic.gdx.tests.g3d.ShaderTest Maven / Gradle / Ivy
The newest version!
/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.badlogic.gdx.tests.g3d;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.graphics.g3d.Attribute;
import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.graphics.g3d.ModelBatch;
import com.badlogic.gdx.graphics.g3d.ModelInstance;
import com.badlogic.gdx.graphics.g3d.Renderable;
import com.badlogic.gdx.graphics.g3d.Shader;
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
import com.badlogic.gdx.graphics.g3d.model.Node;
import com.badlogic.gdx.graphics.g3d.shaders.BaseShader;
import com.badlogic.gdx.graphics.g3d.utils.CameraInputController;
import com.badlogic.gdx.graphics.g3d.utils.DefaultShaderProvider;
import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
import com.badlogic.gdx.graphics.g3d.utils.RenderContext;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.tests.utils.GdxTest;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;
public class ShaderTest extends GdxTest {
// Create a custom attribute, see https://github.com/libgdx/libgdx/wiki/Material-and-environment
// See also: http://blog.xoppa.com/using-materials-with-libgdx/
public static class TestAttribute extends Attribute {
public final static String Alias = "Test";
public final static long ID = register(Alias);
public float value;
protected TestAttribute (final float value) {
super(ID);
this.value = value;
}
@Override
public Attribute copy () {
return new TestAttribute(value);
}
@Override
protected boolean equals (Attribute other) {
return ((TestAttribute)other).value == value;
}
@Override
public int compareTo (Attribute o) {
if (type != o.type) return type < o.type ? -1 : 1;
float otherValue = ((TestAttribute)o).value;
return MathUtils.isEqual(value, otherValue) ? 0 : (value < otherValue ? -1 : 1);
}
}
// Create a custom shader, see also http://blog.xoppa.com/creating-a-shader-with-libgdx
// BaseShader adds some basic functionality used to manage uniforms etc.
public static class TestShader extends BaseShader {
// @off
public final static String vertexShader =
"attribute vec3 a_position;\n"
+ "uniform mat4 u_projTrans;\n"
+ "uniform mat4 u_worldTrans;\n"
+ "void main() {\n"
+ " gl_Position = u_projTrans * u_worldTrans * vec4(a_position, 1.0);\n"
+ "}\n";
public final static String fragmentShader =
"#ifdef GL_ES\n"
+ "#define LOWP lowp\n"
+ "precision mediump float;\n"
+ "#else\n"
+ "#define LOWP\n"
+ "#endif\n"
+ "uniform float u_test;\n"
+ "#ifdef HasDiffuseColor\n"
+ "uniform vec4 u_color;\n"
+ "#endif //HasDiffuseColor\n"
+ "void main() {\n"
+ "#ifdef HasDiffuseColor\n"
+ " gl_FragColor.rgb = u_color.rgb * vec3(u_test);\n"
+ "#else\n"
+ " gl_FragColor.rgb = vec3(u_test);\n"
+ "#endif //HasDiffuseColor\n"
+ "}\n";
// @on
protected final int u_projTrans = register(new Uniform("u_projTrans"));
protected final int u_worldTrans = register(new Uniform("u_worldTrans"));
protected final int u_test = register(new Uniform("u_test"));
protected final int u_color = register(new Uniform("u_color"));
protected final ShaderProgram program;
private boolean withColor;
public TestShader (Renderable renderable) {
super();
withColor = renderable.material.has(ColorAttribute.Diffuse);
if (withColor)
Gdx.app.log("ShaderTest", "Compiling test shader with u_color uniform");
else
Gdx.app.log("ShaderTest", "Compiling test shader without u_color uniform");
String prefix = withColor ? "#define HasDiffuseColor\n" : "";
program = new ShaderProgram(vertexShader, prefix + fragmentShader);
if (!program.isCompiled()) throw new GdxRuntimeException("Couldn't compile shader " + program.getLog());
String log = program.getLog();
if (log.length() > 0) Gdx.app.error("ShaderTest", "Shader compilation log: " + log);
}
@Override
public void init () {
super.init(program, null);
}
@Override
public int compareTo (Shader other) {
return 0;
}
@Override
public boolean canRender (Renderable instance) {
return instance.material.has(TestAttribute.ID) && (instance.material.has(ColorAttribute.Diffuse) == withColor);
}
@Override
public void begin (Camera camera, RenderContext context) {
program.bind();
context.setDepthTest(GL20.GL_LEQUAL, 0f, 1f);
context.setDepthMask(true);
set(u_projTrans, camera.combined);
}
@Override
public void render (Renderable renderable) {
set(u_worldTrans, renderable.worldTransform);
TestAttribute testAttr = (TestAttribute)renderable.material.get(TestAttribute.ID);
set(u_test, testAttr.value);
if (withColor) {
ColorAttribute colorAttr = (ColorAttribute)renderable.material.get(ColorAttribute.Diffuse);
set(u_color, colorAttr.color);
}
renderable.meshPart.render(program);
}
@Override
public void dispose () {
super.dispose();
program.dispose();
}
}
public PerspectiveCamera cam;
public CameraInputController camController;
public ModelBatch modelBatch;
public Model model;
public Array instances = new Array();
public TestAttribute testAttribute1, testAttribute2;
@Override
public void create () {
modelBatch = new ModelBatch(new DefaultShaderProvider() {
@Override
protected Shader createShader (Renderable renderable) {
if (renderable.material.has(TestAttribute.ID)) return new TestShader(renderable);
return super.createShader(renderable);
}
});
cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
cam.position.set(0f, 0f, 20f);
cam.lookAt(0, 0, 0);
cam.near = 1f;
cam.far = 300f;
cam.update();
camController = new CameraInputController(cam);
Gdx.input.setInputProcessor(camController);
Material testMaterial1 = new Material("TestMaterial1", new TestAttribute(1f));
Material redMaterial = new Material("RedMaterial", ColorAttribute.createDiffuse(Color.RED));
Material testMaterial2 = new Material("TestMaterial2", new TestAttribute(1f), ColorAttribute.createDiffuse(Color.BLUE));
ModelBuilder builder = new ModelBuilder();
Node node;
builder.begin();
node = builder.node();
node.id = "testCone1";
node.translation.set(-10, 0f, 0f);
builder.part("testCone", GL20.GL_TRIANGLES, Usage.Position, testMaterial1).cone(5, 5, 5, 20);
node = builder.node();
node.id = "redSphere";
builder.part("redSphere", GL20.GL_TRIANGLES, Usage.Position, redMaterial).sphere(5, 5, 5, 20, 20);
node = builder.node();
node.id = "testCone1";
node.translation.set(10, 0f, 0f);
builder.part("testCone", GL20.GL_TRIANGLES, Usage.Position, testMaterial2).cone(5, 5, 5, 20);
model = builder.end();
ModelInstance modelInstance;
modelInstance = new ModelInstance(model);
testAttribute1 = (TestAttribute)modelInstance.getMaterial("TestMaterial1").get(TestAttribute.ID);
testAttribute2 = (TestAttribute)modelInstance.getMaterial("TestMaterial2").get(TestAttribute.ID);
instances.add(modelInstance);
}
private float counter;
@Override
public void render () {
counter = (counter + Gdx.graphics.getDeltaTime()) % 2.f;
testAttribute1.value = Math.abs(1f - counter);
testAttribute2.value = 1f - testAttribute1.value;
camController.update();
Gdx.gl.glViewport(0, 0, Gdx.graphics.getBackBufferWidth(), Gdx.graphics.getBackBufferHeight());
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
modelBatch.begin(cam);
modelBatch.render(instances);
modelBatch.end();
}
@Override
public void dispose () {
modelBatch.dispose();
model.dispose();
}
}