--- /dev/null
+package com.badlogic.gdx.graphics.g3d;
+
+import com.badlogic.gdx.utils.Array;
+
+/** Extend this class to implement a material attribute.
+ * Register the attribute type by statically calling the {@link #register(String)} method,
+ * whose return value should be used to instantiate the attribute.
+ * A class can implement multiple types
+ * @author Xoppa */
+public abstract class Attribute {
+ /** The registered type aliases */
+ private final static Array<String> types = new Array<String>();
+
+ /** @return The ID of the specified attribute type, or zero if not available */
+ public final static long getAttributeType(final String alias) {
+ for (int i = 0; i < types.size; i++)
+ if (types.get(i).compareTo(alias)==0)
+ return 1L << i;
+ return 0;
+ }
+
+ /** @return The alias of the specified attribute type, or null if not available. */
+ public final static String getAttributeAlias(final long type) {
+ int idx = -1;
+ while (type != 0 && ++idx < 63 && (((type >> idx) & 1) == 0));
+ return (idx >= 0 && idx < types.size) ? types.get(idx) : null;
+ }
+
+ /** Use {@link Attribute#register(String)} instead */
+ protected final static long register(final String alias) {
+ long result = getAttributeType(alias);
+ if (result > 0)
+ return result;
+ types.add(alias);
+ return 1L << (types.size - 1);
+ }
+
+ /** The type of this attribute */
+ public final long type;
+ protected Attribute(final long type) {
+ this.type = type;
+ }
+
+ /** @return An exact copy of this attribute */
+ public abstract Attribute copy();
+
+ protected abstract boolean equals(Attribute other);
+
+ @Override
+ public boolean equals (Object obj) {
+ if (obj == null) return false;
+ if (obj == this) return true;
+ if (!(obj instanceof Attribute)) return false;
+ final Attribute other = (Attribute)obj;
+ if (this.type != other.type) return false;
+ return equals(other);
+ }
+
+ @Override
+ public String toString () {
+ return getAttributeAlias(type);
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.badlogic.gdx.graphics.g3d;
+
+import java.util.Comparator;
+import java.util.Iterator;
+
+import com.badlogic.gdx.utils.Array;
+
+public class Attributes implements Iterable<Attribute>, Comparator<Attribute> {
+ protected long mask;
+ protected final Array<Attribute> attributes = new Array<Attribute>();
+
+ protected boolean sorted = true;
+
+ /** Sort the attributes by their ID */
+ public final void sort() {
+ if (!sorted) {
+ attributes.sort(this);
+ sorted = true;
+ }
+ }
+
+ /** @return Bitwise mask of the ID's of all the containing attributes */
+ public final long getMask() {
+ return mask;
+ }
+
+ /** Example usage: ((BlendingAttribute)material.get(BlendingAttribute.ID)).sourceFunction;
+ * @return The attribute (which can safely be cast) if any, otherwise null */
+ public final Attribute get(final long type) {
+ if (has(type))
+ for (int i = 0; i < attributes.size; i++)
+ if (attributes.get(i).type == type)
+ return attributes.get(i);
+ return null;
+ }
+
+ /** Example usage: ((BlendingAttribute)material.get(BlendingAttribute.ID)).sourceFunction;
+ * @return The attribute if any, otherwise null */
+ public final <T extends Attribute> T get(Class<T> clazz, final long type) {
+ return (T)get(type);
+ }
+
+ /** Get multiple attributes at once.
+ * Example: material.get(out, ColorAttribute.Diffuse | ColorAttribute.Specular | TextureAttribute.Diffuse); */
+ public final Array<Attribute> get(final Array<Attribute> out, final long type) {
+ for (int i = 0; i < attributes.size; i++)
+ if ((attributes.get(i).type & type) != 0)
+ out.add(attributes.get(i));
+ return out;
+ }
+
+ /** Removes all attributes */
+ public final void clear() {
+ mask = 0;
+ attributes.clear();
+ }
+
+ /** @return The amount of attributes this material contains. */
+ public int size() {
+ return attributes.size;
+ }
+
+ private final void enable(final long mask) {
+ this.mask |= mask;
+ }
+ private final void disable(final long mask) {
+ this.mask &= -1L ^ mask;
+ }
+
+ /** Add a attribute to this material.
+ * If the material already contains an attribute of the same type it is overwritten. */
+ public final void set(final Attribute attribute) {
+ final int idx = indexOf(attribute.type);
+ if (idx < 0) {
+ enable(attribute.type);
+ attributes.add(attribute);
+ sorted = false;
+ } else {
+ attributes.set(idx, attribute);
+ }
+ }
+
+ /** Add multiple attributes to this material.
+ * If the material already contains an attribute of the same type it is overwritten. */
+ public final void set(final Attribute attribute1, final Attribute attribute2) {
+ set(attribute1);
+ set(attribute2);
+ }
+
+ /** Add multiple attributes to this material.
+ * If the material already contains an attribute of the same type it is overwritten. */
+ public final void set(final Attribute attribute1, final Attribute attribute2, final Attribute attribute3) {
+ set(attribute1);
+ set(attribute2);
+ set(attribute3);
+ }
+
+ /** Add multiple attributes to this material.
+ * If the material already contains an attribute of the same type it is overwritten. */
+ public final void set(final Attribute attribute1, final Attribute attribute2, final Attribute attribute3, final Attribute attribute4) {
+ set(attribute1);
+ set(attribute2);
+ set(attribute3);
+ set(attribute4);
+ }
+
+ /** Add an array of attributes to this material.
+ * If the material already contains an attribute of the same type it is overwritten. */
+ public final void set(final Attribute... attributes) {
+ for (final Attribute attr : attributes)
+ set(attr);
+ }
+
+ /** Add an array of attributes to this material.
+ * If the material already contains an attribute of the same type it is overwritten. */
+ public final void set(final Iterable<Attribute> attributes) {
+ for (final Attribute attr : attributes)
+ set(attr);
+ }
+
+ /** Removes the attribute from the material, i.e.: material.remove(BlendingAttribute.ID);
+ * Can also be used to remove multiple attributes also, i.e. remove(AttributeA.ID | AttributeB.ID); */
+ public final void remove(final long mask) {
+ for (int i = 0; i < attributes.size; i++) {
+ final long type = attributes.get(i).type;
+ if ((mask & type) == type) {
+ attributes.removeIndex(i);
+ disable(type);
+ sorted = false;
+ }
+ }
+ }
+
+ /** @return True if this collection has the specified attribute, i.e. attributes.has(ColorAttribute.Diffuse);
+ * Or when multiple attribute types are specified, true if this collection has all specified attributes,
+ * i.e. attributes.has(out, ColorAttribute.Diffuse | ColorAttribute.Specular | TextureAttribute.Diffuse); */
+ public final boolean has(final long type) {
+ return type > 0 && (this.mask & type) == type;
+ }
+
+ /** @return the index of the attribute with the specified type or negative if not available. */
+ protected int indexOf(final long type) {
+ if (has(type))
+ for (int i = 0; i < attributes.size; i++)
+ if (attributes.get(i).type == type)
+ return i;
+ return -1;
+ }
+
+ /** Check if this collection has the same attributes as the other collection.
+ * If compareValues is true, it also compares the values of each attribute.
+ * @param compareValues True to compare attribute values, false to only compare attribute types
+ * @return True if this collection contains the same attributes (and optionally attribute values) as the other. */
+ public final boolean same(final Attributes other, boolean compareValues) {
+ if (other == this)
+ return true;
+ if ((other == null) || (mask != other.mask))
+ return false;
+ if (!compareValues)
+ return true;
+ sort();
+ other.sort();
+ for (int i = 0; i < attributes.size; i++)
+ if (!attributes.get(i).equals(other.attributes.get(i)))
+ return false;
+ return true;
+ }
+
+ /** See {@link #same(Attributes, boolean)}
+ * @return True if this collection contains the same attributes (but not values) as the other. */
+ public final boolean same(final Attributes other) {
+ return same(other, false);
+ }
+
+ /** Used for sorting attributes */
+ @Override
+ public final int compare (final Attribute arg0, final Attribute arg1) {
+ return (int)(arg0.type - arg1.type);
+ }
+
+ /** Used for iterating through the attributes */
+ @Override
+ public final Iterator<Attribute> iterator () {
+ return attributes.iterator();
+ }
+}
--- /dev/null
+package com.badlogic.gdx.graphics.g3d;
+
+import java.util.Comparator;
+import java.util.Iterator;
+
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.utils.Array;
+import com.badlogic.gdx.utils.Disposable;
+
+public class Material extends Attributes {
+ private static int counter = 0;
+
+ public String id;
+
+ /** Create an empty material */
+ public Material() {
+ this("mtl"+(++counter));
+ }
+ /** Create an empty material */
+ public Material(final String id) {
+ this.id = id;
+ }
+ /** Create a material with the specified attributes */
+ public Material(final Attribute... attributes) {
+ this();
+ set(attributes);
+ }
+ /** Create a material with the specified attributes */
+ public Material(final String id, final Attribute... attributes) {
+ this(id);
+ set(attributes);
+ }
+ /** Create a material with the specified attributes */
+ public Material(final Array<Attribute> attributes) {
+ this();
+ set(attributes);
+ }
+ /** Create a material with the specified attributes */
+ public Material(final String id, final Array<Attribute> attributes) {
+ this(id);
+ set(attributes);
+ }
+ /** Create a material which is an exact copy of the specified material */
+ public Material(final Material copyFrom) {
+ this(copyFrom.id, copyFrom);
+ }
+ /** Create a material which is an exact copy of the specified material */
+ public Material(final String id, final Material copyFrom) {
+ this(id);
+ for (Attribute attr : copyFrom)
+ set(attr.copy());
+ }
+
+ /** Create a copy of this material */
+ public final Material copy() {
+ return new Material(this);
+ }
+
+ /** @return True if this material equals the other material in every aspect (including the ID) */
+ public final boolean equals (final Material other) {
+ return same(other, true) && id.equals(other.id);
+ }
+
+ /** @return True if this material equals the other material in every aspect (including the ID) */
+ @Override
+ public final boolean equals (final Object obj) {
+ return obj instanceof Material ? equals((Material)obj) : false;
+ }
+}
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes;
-import com.badlogic.gdx.graphics.g3d.materials.BlendingAttribute;
-import com.badlogic.gdx.graphics.g3d.materials.ColorAttribute;
-import com.badlogic.gdx.graphics.g3d.materials.FloatAttribute;
-import com.badlogic.gdx.graphics.g3d.materials.Material;
-import com.badlogic.gdx.graphics.g3d.materials.TextureAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.BlendingAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.FloatAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.TextureAttribute;
import com.badlogic.gdx.graphics.g3d.model.Animation;
import com.badlogic.gdx.graphics.g3d.model.MeshPart;
import com.badlogic.gdx.graphics.g3d.model.NodeAnimation;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Camera;
-import com.badlogic.gdx.graphics.g3d.lights.Lights;
+import com.badlogic.gdx.graphics.g3d.environment.Environment;
import com.badlogic.gdx.graphics.g3d.shaders.DefaultShader;
import com.badlogic.gdx.graphics.g3d.utils.DefaultRenderableSorter;
import com.badlogic.gdx.graphics.g3d.utils.DefaultShaderProvider;
import com.badlogic.gdx.graphics.g3d.utils.DefaultTextureBinder;
+import com.badlogic.gdx.graphics.g3d.utils.GLES10ShaderProvider;
import com.badlogic.gdx.graphics.g3d.utils.RenderContext;
import com.badlogic.gdx.graphics.g3d.utils.RenderableSorter;
import com.badlogic.gdx.graphics.g3d.utils.ShaderProvider;
@Override
public Renderable obtain () {
Renderable renderable = super.obtain();
- renderable.lights = null;
+ renderable.environment = null;
renderable.material = null;
renderable.mesh = null;
renderable.shader = null;
public ModelBatch() {
this(new RenderContext(new DefaultTextureBinder(DefaultTextureBinder.ROUNDROBIN, 1)),
true,
- new DefaultShaderProvider(),
+ Gdx.graphics.isGL20Available() ? new DefaultShaderProvider() : new GLES10ShaderProvider(),
new DefaultRenderableSorter());
}
* with the given lights. Can only be called after a call to {@link #begin(Camera)} and before a call to {@link #end()}.
* @param renderableProvider the renderable provider
* @param lights the lights to use for the renderables */
- public void render(final RenderableProvider renderableProvider, final Lights lights) {
+ public void render(final RenderableProvider renderableProvider, final Environment lights) {
render(renderableProvider, lights, null);
}
* with the given lights. Can only be called after a call to {@link #begin(Camera)} and before a call to {@link #end()}.
* @param renderableProviders one or more renderable providers
* @param lights the lights to use for the renderables */
- public <T extends RenderableProvider> void render(final Iterable<T> renderableProviders, final Lights lights) {
+ public <T extends RenderableProvider> void render(final Iterable<T> renderableProviders, final Environment lights) {
render(renderableProviders, lights, null);
}
* @param renderableProvider the renderable provider
* @param lights the lights to use for the renderables
* @param shader the shader to use for the renderables */
- public void render(final RenderableProvider renderableProvider, final Lights lights, final Shader shader) {
+ public void render(final RenderableProvider renderableProvider, final Environment lights, final Shader shader) {
final int offset = renderables.size;
renderableProvider.getRenderables(renderables, renderablesPool);
for (int i = offset; i < renderables.size; i++) {
Renderable renderable = renderables.get(i);
- renderable.lights = lights;
+ renderable.environment = lights;
renderable.shader = shader;
renderable.shader = shaderProvider.getShader(renderable);
reuseableRenderables.add(renderable);
* @param renderableProviders one or more renderable providers
* @param lights the lights to use for the renderables
* @param shader the shader to use for the renderables */
- public <T extends RenderableProvider> void render(final Iterable<T> renderableProviders, final Lights lights, final Shader shader) {
+ public <T extends RenderableProvider> void render(final Iterable<T> renderableProviders, final Environment lights, final Shader shader) {
for (final RenderableProvider renderableProvider : renderableProviders)
render(renderableProvider, lights, shader);
}
package com.badlogic.gdx.graphics.g3d;
import com.badlogic.gdx.Gdx;
-import com.badlogic.gdx.graphics.g3d.materials.Material;
import com.badlogic.gdx.graphics.g3d.model.Animation;
import com.badlogic.gdx.graphics.g3d.model.MeshPart;
import com.badlogic.gdx.graphics.g3d.model.NodeAnimation;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Mesh;
-import com.badlogic.gdx.graphics.g3d.lights.Lights;
-import com.badlogic.gdx.graphics.g3d.materials.Material;
+import com.badlogic.gdx.graphics.g3d.environment.Environment;
import com.badlogic.gdx.graphics.g3d.model.Node;
import com.badlogic.gdx.graphics.g3d.utils.ShaderProvider;
import com.badlogic.gdx.math.Matrix4;
public Material material;
/** the bones transformations used for skinning, or null if not applicable */
public Matrix4 bones[];
- /** the {@link Lights} to be used to render this Renderable, may be null **/
- public Lights lights;
+ /** the {@link Environment} to be used to render this Renderable, may be null **/
+ public Environment environment;
/** the {@link Shader} to be used to render this Renderable, may be null.
* It is not guaranteed that the shader will be used, the used {@link ShaderProvider} is responsible
* for actually choosing the correct shader to use. **/
-package com.badlogic.gdx.graphics.g3d.materials;
+package com.badlogic.gdx.graphics.g3d.attributes;
import com.badlogic.gdx.graphics.GL10;
-import com.badlogic.gdx.graphics.g3d.materials.Material.Attribute;
+import com.badlogic.gdx.graphics.g3d.Attribute;
import com.badlogic.gdx.utils.GdxRuntimeException;
-public class BlendingAttribute extends Material.Attribute {
+public class BlendingAttribute extends Attribute {
public final static String Alias = "blended";
public final static long Type = register(Alias);
-package com.badlogic.gdx.graphics.g3d.materials;
+package com.badlogic.gdx.graphics.g3d.attributes;
import com.badlogic.gdx.graphics.Color;
-import com.badlogic.gdx.graphics.g3d.materials.Material.Attribute;
+import com.badlogic.gdx.graphics.g3d.Attribute;
import com.badlogic.gdx.utils.GdxRuntimeException;
-public class ColorAttribute extends Material.Attribute {
+public class ColorAttribute extends Attribute {
public final static String DiffuseAlias = "diffuseColor";
public final static long Diffuse = register(DiffuseAlias);
public final static String SpecularAlias = "specularColor";
public static final long Emissive = register(EmissiveAlias);
public final static String ReflectionAlias = "reflectionColor";
public static final long Reflection = register(ReflectionAlias);
+ public final static String AmbientLightAlias = "ambientLightColor";
+ public static final long AmbientLight = register(AmbientLightAlias);
- protected static long Mask = Ambient | Diffuse | Specular | Emissive | Reflection;
+ protected static long Mask = Ambient | Diffuse | Specular | Emissive | Reflection | AmbientLight;
public final static boolean is(final long mask) {
return (mask & Mask) != 0;
-package com.badlogic.gdx.graphics.g3d.materials;
+package com.badlogic.gdx.graphics.g3d.attributes;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL10;
-import com.badlogic.gdx.graphics.g3d.materials.Material.Attribute;
+import com.badlogic.gdx.graphics.g3d.Attribute;
import com.badlogic.gdx.utils.GdxRuntimeException;
-public class DepthTestAttribute extends Material.Attribute {
+public class DepthTestAttribute extends Attribute {
public final static String Alias = "depthStencil";
public final static long Type = register(Alias);
-package com.badlogic.gdx.graphics.g3d.materials;
+package com.badlogic.gdx.graphics.g3d.attributes;
-import com.badlogic.gdx.graphics.g3d.materials.Material.Attribute;
+import com.badlogic.gdx.graphics.g3d.Attribute;
import com.badlogic.gdx.utils.GdxRuntimeException;
-public class FloatAttribute extends Material.Attribute {
+public class FloatAttribute extends Attribute {
public static final String ShininessAlias = "shininess";
public static final long Shininess = register(ShininessAlias);
-package com.badlogic.gdx.graphics.g3d.materials;
+package com.badlogic.gdx.graphics.g3d.attributes;
-import com.badlogic.gdx.graphics.g3d.materials.Material.Attribute;
+import com.badlogic.gdx.graphics.g3d.Attribute;
-public class IntAttribute extends Material.Attribute {
+public class IntAttribute extends Attribute {
public static final String CullFaceAlias = "cullface";
public static final long CullFace = register(CullFaceAlias);
-package com.badlogic.gdx.graphics.g3d.materials;
+package com.badlogic.gdx.graphics.g3d.attributes;
import com.badlogic.gdx.graphics.Texture;
-import com.badlogic.gdx.graphics.g3d.materials.Material.Attribute;
+import com.badlogic.gdx.graphics.g3d.Attribute;
import com.badlogic.gdx.graphics.g3d.utils.TextureDescriptor;
import com.badlogic.gdx.utils.GdxRuntimeException;
-public class TextureAttribute extends Material.Attribute {
+public class TextureAttribute extends Attribute {
public final static String DiffuseAlias = "diffuseTexture";
public final static long Diffuse = register(DiffuseAlias);
public final static String SpecularAlias = "specularTexture";
-package com.badlogic.gdx.graphics.g3d.lights;
+package com.badlogic.gdx.graphics.g3d.environment;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Vector3;
-package com.badlogic.gdx.graphics.g3d.lights;
+package com.badlogic.gdx.graphics.g3d.environment;
import com.badlogic.gdx.graphics.Color;
-package com.badlogic.gdx.graphics.g3d.lights;
+package com.badlogic.gdx.graphics.g3d.environment;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Vector3;
-package com.badlogic.gdx.graphics.g3d.lights;
+package com.badlogic.gdx.graphics.g3d.environment;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Camera;
-package com.badlogic.gdx.graphics.g3d.lights;
+package com.badlogic.gdx.graphics.g3d.environment;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Cubemap;
+import com.badlogic.gdx.graphics.g3d.Attributes;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;
-public class Lights {
- public final Color ambientLight = new Color(0,0,0,1);
+public class Environment extends Attributes {
public Color fog;
/** @deprecated Experimental, likely to change, do not use! */
public ShadowMap shadowMap;
public final Array<DirectionalLight> directionalLights = new Array<DirectionalLight>();
public final Array<PointLight> pointLights = new Array<PointLight>();
- public Lights() {}
+ public Environment() {}
- public Lights(final Color ambient) {
- ambientLight.set(ambient);
- }
-
- public Lights(final float ambientRed, final float ambientGreen, final float ambientBlue) {
- ambientLight.set(ambientRed, ambientGreen, ambientBlue, 1f);
- }
-
- public Lights(final Color ambient, final BaseLight... lights) {
- this(ambient);
- add(lights);
- }
-
- public Lights clear() {
- ambientLight.set(0,0,0,1);
- directionalLights.clear();
- pointLights.clear();
- return this;
- }
-
- public Lights add(final BaseLight... lights) {
+ public Environment add(final BaseLight... lights) {
for (final BaseLight light : lights)
add(light);
return this;
}
- public Lights add(final Array<BaseLight> lights) {
+ public Environment add(final Array<BaseLight> lights) {
for (final BaseLight light : lights)
add(light);
return this;
}
- public Lights add(BaseLight light) {
+ public Environment add(BaseLight light) {
if (light instanceof DirectionalLight)
directionalLights.add((DirectionalLight)light);
else if (light instanceof PointLight)
-package com.badlogic.gdx.graphics.g3d.lights;
+package com.badlogic.gdx.graphics.g3d.environment;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Vector3;
-package com.badlogic.gdx.graphics.g3d.lights;
+package com.badlogic.gdx.graphics.g3d.environment;
import com.badlogic.gdx.graphics.g3d.utils.TextureDescriptor;
import com.badlogic.gdx.math.Matrix4;
--- /dev/null
+package com.badlogic.gdx.graphics.g3d.environment;
+
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.utils.GdxRuntimeException;
+
+public class SphericalHarmonics {
+ // <kalle_h> last term is no x*x * y*y but x*x - y*y
+ private final static float coeff[] = {0.282095f, 0.488603f, 0.488603f, 0.488603f, 1.092548f, 1.092548f, 1.092548f, 0.315392f, 0.546274f};
+ private final static float clamp(final float v) {
+ return v < 0f ? 0f : (v > 1f ? 1f : v);
+ }
+
+ public final float data[];
+
+ public SphericalHarmonics() {
+ data = new float[9*3];
+ }
+
+ public SphericalHarmonics(final float copyFrom[]) {
+ if (copyFrom.length != (9*3))
+ throw new GdxRuntimeException("Incorrect array size");
+ data = copyFrom.clone();
+ }
+
+ public SphericalHarmonics set(final float values[]) {
+ for (int i = 0; i < data.length; i++)
+ data[i] = values[i];
+ return this;
+ }
+
+ public SphericalHarmonics set(final AmbientCubemap other) {
+ return set(other.data);
+ }
+
+ public SphericalHarmonics set(final Color color) {
+ return set(color.r, color.g, color.b);
+ }
+
+ public SphericalHarmonics set(float r, float g, float b) {
+ for (int idx = 0; idx < data.length;) {
+ data[idx++] = r;
+ data[idx++] = g;
+ data[idx++] = b;
+ }
+ return this;
+ }
+}
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
-import com.badlogic.gdx.graphics.g3d.materials.ColorAttribute;
-import com.badlogic.gdx.graphics.g3d.materials.Material;
-import com.badlogic.gdx.graphics.g3d.materials.TextureAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.TextureAttribute;
+import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.graphics.g3d.model.data.ModelData;
import com.badlogic.gdx.graphics.g3d.model.data.ModelMaterial;
+++ /dev/null
-package com.badlogic.gdx.graphics.g3d.materials;
-
-import java.util.Comparator;
-import java.util.Iterator;
-
-import com.badlogic.gdx.graphics.Texture;
-import com.badlogic.gdx.utils.Array;
-import com.badlogic.gdx.utils.Disposable;
-
-public class Material implements Iterable<Material.Attribute>, Comparator<Material.Attribute> {
- /** Extend this class to implement a material attribute.
- * Register the attribute type by statically calling the {@link #register(String)} method,
- * whose return value should be used to instantiate the attribute.
- * A class can implement multiple types */
- public static abstract class Attribute {
- protected static long register(final String type) {
- return Material.register(type);
- }
- /** The type of this attribute */
- public final long type;
- protected Attribute(final long type) {
- this.type = type;
- }
- /** @return An exact copy of this attribute */
- public abstract Attribute copy();
- protected abstract boolean equals(Attribute other);
- @Override
- public boolean equals (Object obj) {
- if (obj == null) return false;
- if (obj == this) return true;
- if (!(obj instanceof Attribute)) return false;
- final Attribute other = (Attribute)obj;
- if (this.type != other.type) return false;
- return equals(other);
- }
- @Override
- public String toString () {
- return Material.getAttributeAlias(type);
- }
- }
-
- /** The registered type aliases */
- private final static Array<String> types = new Array<String>();
-
- private static int counter = 0;
-
- /** @return The ID of the specified attribute type, or zero if not available */
- protected final static long getAttributeType(final String alias) {
- for (int i = 0; i < types.size; i++)
- if (types.get(i).compareTo(alias)==0)
- return 1L << i;
- return 0;
- }
-
- /** @return The alias of the specified attribute type, or null if not available. */
- protected final static String getAttributeAlias(final long type) {
- int idx = -1;
- while (type != 0 && ++idx < 63 && (((type >> idx) & 1) == 0));
- return (idx >= 0 && idx < types.size) ? types.get(idx) : null;
- }
-
- /** Use {@link Attribute#register(String)} instead */
- protected final static long register(final String alias) {
- long result = getAttributeType(alias);
- if (result > 0)
- return result;
- types.add(alias);
- return 1L << (types.size - 1);
- }
-
- public String id;
- protected long mask;
- protected final Array<Attribute> attributes = new Array<Attribute>();
- protected boolean sorted = true;
-
- /** Create an empty material */
- public Material() {
- this("mtl"+(++counter));
- }
- /** Create an empty material */
- public Material(final String id) {
- this.id = id;
- }
- /** Create a material with the specified attributes */
- public Material(final Attribute... attributes) {
- this();
- set(attributes);
- }
- /** Create a material with the specified attributes */
- public Material(final String id, final Attribute... attributes) {
- this(id);
- set(attributes);
- }
- /** Create a material with the specified attributes */
- public Material(final Array<Attribute> attributes) {
- this();
- set(attributes);
- }
- /** Create a material with the specified attributes */
- public Material(final String id, final Array<Attribute> attributes) {
- this(id);
- set(attributes);
- }
- /** Create a material which is an exact copy of the specified material */
- public Material(final Material copyFrom) {
- this(copyFrom.id, copyFrom);
- }
- /** Create a material which is an exact copy of the specified material */
- public Material(final String id, final Material copyFrom) {
- this(id);
- for (Attribute attr : copyFrom)
- set(attr.copy());
- }
-
- private final void enable(final long mask) {
- this.mask |= mask;
- }
- private final void disable(final long mask) {
- this.mask &= -1L ^ mask;
- }
-
- /** @return Bitwise mask of the ID's of all the containing attributes */
- public final long getMask() {
- return mask;
- }
-
- /** @return True if this material has the specified attribute, i.e. material.has(BlendingAttribute.ID); */
- public final boolean has(final long type) {
- return type > 0 && (this.mask & type) == type;
- }
-
- /** @return the index of the attribute with the specified type or negative if not available. */
- protected int indexOf(final long type) {
- if (has(type))
- for (int i = 0; i < attributes.size; i++)
- if (attributes.get(i).type == type)
- return i;
- return -1;
- }
-
- /** Add a attribute to this material.
- * If the material already contains an attribute of the same type it is overwritten. */
- public final void set(final Attribute attribute) {
- final int idx = indexOf(attribute.type);
- if (idx < 0) {
- enable(attribute.type);
- attributes.add(attribute);
- sorted = false;
- } else {
- attributes.set(idx, attribute);
- }
- }
-
- /** Add an array of attributes to this material.
- * If the material already contains an attribute of the same type it is overwritten. */
- public final void set(final Attribute... attributes) {
- for (final Attribute attr : attributes)
- set(attr);
- }
-
- /** Add an array of attributes to this material.
- * If the material already contains an attribute of the same type it is overwritten. */
- public final void set(final Iterable<Attribute> attributes) {
- for (final Attribute attr : attributes)
- set(attr);
- }
-
- /** Removes the attribute from the material, i.e.: material.remove(BlendingAttribute.ID);
- * Can also be used to remove multiple attributes also, i.e. remove(AttributeA.ID | AttributeB.ID); */
- public final void remove(final long mask) {
- for (int i = 0; i < attributes.size; i++) {
- final long type = attributes.get(i).type;
- if ((mask & type) == type) {
- attributes.removeIndex(i);
- disable(type);
- sorted = false;
- }
- }
- }
-
- /** Example usage: ((BlendingAttribute)material.get(BlendingAttribute.ID)).sourceFunction;
- * @return The attribute (which can safely be cast) if any, otherwise null */
- public final Attribute get(final long type) {
- if (has(type))
- for (int i = 0; i < attributes.size; i++)
- if (attributes.get(i).type == type)
- return attributes.get(i);
- return null;
- }
-
- /** Get multiple attributes at once.
- * Example: material.get(out, AttributeA.ID | AttributeB.ID | AttributeC.ID); */
- public final Array<Attribute> get(final Array<Attribute> out, final long type) {
- for (int i = 0; i < attributes.size; i++)
- if ((attributes.get(i).type & type) != 0)
- out.add(attributes.get(i));
- return out;
- }
-
- /** Removes all attributes */
- public final void clear() {
- mask = 0;
- attributes.clear();
- }
-
- /** @return The amount of attributes this material contains. */
- public int size() {
- return attributes.size;
- }
-
- /** Create a copy of this material */
- public final Material copy() {
- return new Material(this);
- }
-
- /** Used for sorting attributes */
- @Override
- public final int compare (final Attribute arg0, final Attribute arg1) {
- return (int)(arg0.type - arg1.type);
- }
-
- /** Sort the attributes by their ID */
- public final void sort() {
- if (!sorted) {
- attributes.sort(this);
- sorted = true;
- }
- }
-
- /** Check if this Material has the same attributes as the other Material.
- * If compareValues is true, it also compares the values of each attribute.
- * Use {@link #equals(Material)} to compare Materials including ID.
- * @param compareValues True to compare attribute values, false to only compare attribute types
- * @return True if this material contains the same attributes (and optionally attribute values) as the other. */
- public final boolean same(final Material other, boolean compareValues) {
- if (other == this)
- return true;
- if ((other == null) || (mask != other.mask))
- return false;
- if (!compareValues)
- return true;
- sort();
- other.sort();
- for (int i = 0; i < attributes.size; i++)
- if (!attributes.get(i).equals(other.attributes.get(i)))
- return false;
- return true;
- }
-
- /** See {@link #same(Material, boolean)}
- * @return True if this material contains the same attributes (but not values) as the other. */
- public final boolean same(final Material other) {
- return same(other, false);
- }
-
- /** @return True if this material equals the other material in every aspect (including the ID) */
- public final boolean equals (final Material other) {
- return same(other, true) && id.equals(other.id);
- }
-
- /** @return True if this material equals the other material in every aspect (including the ID) */
- @Override
- public final boolean equals (final Object obj) {
- return obj instanceof Material ? equals((Material)obj) : false;
- }
-
- /** Used for iterating through the attributes */
- @Override
- public final Iterator<Attribute> iterator () {
- return attributes.iterator();
- }
-}
package com.badlogic.gdx.graphics.g3d.model;
+import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.Model;
-import com.badlogic.gdx.graphics.g3d.materials.Material;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Quaternion;
import com.badlogic.gdx.math.Vector3;
package com.badlogic.gdx.graphics.g3d.model;
+import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.Renderable;
-import com.badlogic.gdx.graphics.g3d.materials.Material;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ArrayMap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes;
+import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.Renderable;
import com.badlogic.gdx.graphics.g3d.Shader;
-import com.badlogic.gdx.graphics.g3d.materials.Material;
-import com.badlogic.gdx.graphics.g3d.materials.TextureAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.TextureAttribute;
import com.badlogic.gdx.graphics.g3d.utils.RenderContext;
import com.badlogic.gdx.graphics.g3d.utils.TextureDescriptor;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes;
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.Renderable;
import com.badlogic.gdx.graphics.g3d.Shader;
-import com.badlogic.gdx.graphics.g3d.lights.AmbientCubemap;
-import com.badlogic.gdx.graphics.g3d.lights.DirectionalLight;
-import com.badlogic.gdx.graphics.g3d.lights.Lights;
-import com.badlogic.gdx.graphics.g3d.lights.PointLight;
-import com.badlogic.gdx.graphics.g3d.materials.BlendingAttribute;
-import com.badlogic.gdx.graphics.g3d.materials.ColorAttribute;
-import com.badlogic.gdx.graphics.g3d.materials.DepthTestAttribute;
-import com.badlogic.gdx.graphics.g3d.materials.FloatAttribute;
-import com.badlogic.gdx.graphics.g3d.materials.IntAttribute;
-import com.badlogic.gdx.graphics.g3d.materials.Material;
-import com.badlogic.gdx.graphics.g3d.materials.TextureAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.BlendingAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.DepthTestAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.FloatAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.IntAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.TextureAttribute;
+import com.badlogic.gdx.graphics.g3d.environment.AmbientCubemap;
+import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
+import com.badlogic.gdx.graphics.g3d.environment.Environment;
+import com.badlogic.gdx.graphics.g3d.environment.PointLight;
import com.badlogic.gdx.graphics.g3d.utils.RenderContext;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.math.Matrix3;
public class DefaultShader extends BaseShader {
public static class Config {
- public boolean lighting;
- public boolean environmentCubemap;
- public boolean shadowMap;
- public boolean fog;
- public int numDirectional;
- public int numPoint;
- public int numSpot;
- public int numBones;
+ /** The uber vertex shader to use, null to use the default vertex shader. */
+ public String vertexShader = null;
+ /** The uber fragment shader to use, null to use the default fragment shader. */
+ public String fragmentShader = null;
+ /** The number of directional lights to use */
+ public int numDirectionalLights = 2;
+ /** The number of point lights to use */
+ public int numPointLights = 5;
+ /** The number of spot lights to use */
+ public int numSpotLights = 0;
+ /** The number of bones to use */
+ public int numBones = 12;
+
+ public Config() { }
+
+ public Config(final String vertexShader, final String fragmentShader) {
+ this.vertexShader = vertexShader;
+ this.fragmentShader = fragmentShader;
+ }
}
public static class Inputs {
}
@Override public boolean isGlobal (BaseShader shader, int inputID) { return false; }
@Override public void set (BaseShader shader, int inputID, Renderable renderable) {
- if (renderable.lights == null)
+ if (renderable.environment == null)
shader.program.setUniform3fv(shader.loc(inputID), ones, 0, ones.length);
else {
renderable.worldTransform.getTranslation(tmpV1);
- cacheAmbientCubemap.set(renderable.lights.ambientLight);
+ if (renderable.environment.has(ColorAttribute.AmbientLight))
+ cacheAmbientCubemap.set(((ColorAttribute)renderable.environment.get(ColorAttribute.AmbientLight)).color);
- for (int i = dirLightsOffset; i < renderable.lights.directionalLights.size; i++)
- cacheAmbientCubemap.add(renderable.lights.directionalLights.get(i).color, renderable.lights.directionalLights.get(i).direction);
+ for (int i = dirLightsOffset; i < renderable.environment.directionalLights.size; i++)
+ cacheAmbientCubemap.add(renderable.environment.directionalLights.get(i).color, renderable.environment.directionalLights.get(i).direction);
- for (int i = pointLightsOffset; i < renderable.lights.pointLights.size; i++)
- cacheAmbientCubemap.add(renderable.lights.pointLights.get(i).color, renderable.lights.pointLights.get(i).position, tmpV1, renderable.lights.pointLights.get(i).intensity);
+ for (int i = pointLightsOffset; i < renderable.environment.pointLights.size; i++)
+ cacheAmbientCubemap.add(renderable.environment.pointLights.get(i).color, renderable.environment.pointLights.get(i).position, tmpV1, renderable.environment.pointLights.get(i).intensity);
cacheAmbientCubemap.clamp();
public final static Setter environmentCubemap = new Setter() {
@Override public boolean isGlobal (BaseShader shader, int inputID) { return false; }
@Override public void set (BaseShader shader, int inputID, Renderable renderable) {
- if (renderable.lights != null && renderable.lights.environmentCubemap != null) {
- final int unit = shader.context.textureBinder.bind(renderable.lights.environmentCubemap);
+ if (renderable.environment != null && renderable.environment.environmentCubemap != null) {
+ final int unit = shader.context.textureBinder.bind(renderable.environment.environmentCubemap);
shader.set(inputID, unit);
}
}
/** Material attributes which are not required but always supported. */
private final static long optionalAttributes = IntAttribute.CullFace | DepthTestAttribute.Type;
- public DefaultShader(final Renderable renderable, boolean lighting, boolean environmentCubemap, boolean shadowMap, boolean fog, int numDirectional, int numPoint, int numSpot, int numBones) {
- this(getDefaultVertexShader(), getDefaultFragmentShader(), renderable, lighting, environmentCubemap, shadowMap, fog, numDirectional, numPoint, numSpot, numBones);
+ public DefaultShader(final Renderable renderable) {
+ this(renderable, new Config());
}
- public DefaultShader(final String vertexShader, final String fragmentShader, final Renderable renderable, boolean lighting, boolean environmentCubemap, boolean shadowMap, boolean fog, int numDirectional, int numPoint, int numSpot, int numBones) {
- this(createPrefix(renderable, lighting, environmentCubemap, shadowMap, fog, numDirectional, numPoint, numSpot, numBones),
- vertexShader, fragmentShader, renderable, lighting, environmentCubemap, shadowMap, fog, numDirectional, numPoint, numSpot, numBones);
+ public DefaultShader(final Renderable renderable, final Config config) {
+ this(renderable, config, createPrefix(renderable, config));
}
- public DefaultShader(final String prefix, final String vertexShader, final String fragmentShader, final Renderable renderable, boolean lighting, boolean environmentCubemap, boolean shadowMap, boolean fog, int numDirectional, int numPoint, int numSpot, int numBones) {
- this(new ShaderProgram(prefix + vertexShader, prefix + fragmentShader), renderable, lighting, environmentCubemap, shadowMap, fog, numDirectional, numPoint, numSpot, numBones);
+ public DefaultShader(final Renderable renderable, final Config config, final String prefix) {
+ this(renderable, config, prefix,
+ config.vertexShader != null ? config.vertexShader : getDefaultVertexShader(),
+ config.fragmentShader != null ? config.fragmentShader : getDefaultFragmentShader());
+ }
+
+ public DefaultShader(final Renderable renderable, final Config config, final String prefix, final String vertexShader, final String fragmentShader) {
+ this(renderable, config, new ShaderProgram(prefix + vertexShader, prefix + fragmentShader));
}
- public DefaultShader(final ShaderProgram shaderProgram, final Renderable renderable, boolean lighting, boolean environmentCubemap, boolean shadowMap, boolean fog, int numDirectional, int numPoint, int numSpot, int numBones) {
+ public DefaultShader(final Renderable renderable, final Config config, final ShaderProgram shaderProgram) {
this.program = shaderProgram;
- this.lighting = lighting;
- this.environmentCubemap = environmentCubemap;
- this.shadowMap = shadowMap;
- this.fog = fog;
+ this.lighting = renderable.environment != null;
+ this.environmentCubemap = lighting && renderable.environment.environmentCubemap != null;
+ this.shadowMap = lighting && renderable.environment.shadowMap != null;
+ this.fog = lighting && renderable.environment.fog != null;
this.renderable = renderable;
materialMask = renderable.material.getMask() | optionalAttributes;
vertexMask = renderable.mesh.getVertexAttributes().getMask();
- this.directionalLights = new DirectionalLight[lighting && numDirectional > 0 ? numDirectional : 0];
+ this.directionalLights = new DirectionalLight[lighting && config.numDirectionalLights > 0 ? config.numDirectionalLights : 0];
for (int i = 0; i < directionalLights.length; i++)
directionalLights[i] = new DirectionalLight();
- this.pointLights = new PointLight[lighting && numPoint > 0 ? numPoint : 0];
+ this.pointLights = new PointLight[lighting && config.numPointLights > 0 ? config.numPointLights : 0];
for (int i = 0; i < pointLights.length; i++)
pointLights[i] = new PointLight();
u_viewWorldTrans = register(Inputs.worldViewTrans, Setters.worldViewTrans);
u_projViewWorldTrans = register(Inputs.projViewWorldTrans, Setters.projViewWorldTrans);
u_normalMatrix = register(Inputs.normalMatrix, Setters.normalMatrix);
- u_bones = numBones > 0 ? register(Inputs.bones, new Setters.Bones(numBones)) : -1;
+ u_bones = (renderable.bones != null && config.numBones > 0) ? register(Inputs.bones, new Setters.Bones(config.numBones)) : -1;
u_shininess = register(Inputs.shininess, Setters.shininess);
u_opacity = register(Inputs.opacity);
u_normalTexture = register(Inputs.normalTexture, Setters.normalTexture);
u_alphaTest = register(Inputs.alphaTest);
- u_ambientCubemap = lighting ? register(Inputs.ambientCube, new Setters.ACubemap(numDirectional, numPoint)) : -1;
+ u_ambientCubemap = lighting ? register(Inputs.ambientCube, new Setters.ACubemap(config.numDirectionalLights, config.numPointLights)) : -1;
u_environmentCubemap = environmentCubemap ? register(Inputs.environmentCubemap, Setters.environmentCubemap) : -1;
}
return (mask & flag) != 0;
}
- public static String createPrefix(final Renderable renderable, boolean lighting, boolean environmentCubemap, boolean shadowMap, boolean fog, int numDirectional, int numPoint, int numSpot, int numBones) {
+ public static String createPrefix(final Renderable renderable, final Config config) {
String prefix = "";
final long mask = renderable.material.getMask();
final long attributes = renderable.mesh.getVertexAttributes().getMask();
if (and(attributes, Usage.Normal))
prefix += "#define normalFlag\n";
if (and(attributes, Usage.Normal) || and(attributes, Usage.Tangent | Usage.BiNormal)) {
- if (lighting) {
+ if (renderable.environment != null) {
prefix += "#define lightingFlag\n";
prefix += "#define ambientCubemapFlag\n";
- prefix += "#define numDirectionalLights "+numDirectional+"\n";
- prefix += "#define numPointLights "+numPoint+"\n";
- if (fog) {
+ prefix += "#define numDirectionalLights "+config.numDirectionalLights+"\n";
+ prefix += "#define numPointLights "+config.numPointLights+"\n";
+ if (renderable.environment.fog != null) {
prefix += "#define fogFlag\n";
}
- if (shadowMap)
+ if (renderable.environment.shadowMap != null)
prefix += "#define shadowMapFlag\n";
- if (environmentCubemap)
+ if (renderable.environment.environmentCubemap != null)
prefix += "#define environmentCubemapFlag\n";
}
}
prefix += "#define "+FloatAttribute.ShininessAlias+"Flag\n";
if ((mask & FloatAttribute.AlphaTest) == FloatAttribute.AlphaTest)
prefix += "#define "+FloatAttribute.AlphaTestAlias+"Flag\n";
- if (numBones > 0)
- prefix += "#define numBones "+numBones+"\n";
+ if (renderable.bones != null && config.numBones > 0)
+ prefix += "#define numBones "+config.numBones+"\n";
Gdx.app.log("Prefix","\n"+prefix);
return prefix;
}
public boolean canRender(final Renderable renderable) {
return (materialMask == (renderable.material.getMask() | optionalAttributes)) &&
(vertexMask == renderable.mesh.getVertexAttributes().getMask()) &&
- (renderable.lights != null) == lighting &&
- ((renderable.lights != null && renderable.lights.fog != null) == fog);
+ (renderable.environment != null) == lighting &&
+ ((renderable.environment != null && renderable.environment.fog != null) == fog);
}
@Override
boolean depthMask = true;
currentMaterial = renderable.material;
- for (final Material.Attribute attr : currentMaterial) {
+ for (final Attribute attr : currentMaterial) {
final long t = attr.type;
if (BlendingAttribute.is(t)) {
context.setBlending(true, ((BlendingAttribute)attr).sourceFunction, ((BlendingAttribute)attr).destFunction);
private final Vector3 tmpV1 = new Vector3();
protected final void bindLights(final Renderable renderable) {
- final Lights lights = renderable.lights;
+ final Environment lights = renderable.environment;
final Array<DirectionalLight> dirs = lights.directionalLights;
final Array<PointLight> points = lights.pointLights;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.graphics.g3d.Renderable;
-import com.badlogic.gdx.graphics.g3d.materials.BlendingAttribute;
-import com.badlogic.gdx.graphics.g3d.materials.TextureAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.BlendingAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.TextureAttribute;
+import com.badlogic.gdx.graphics.g3d.shaders.DefaultShader.Config;
import com.badlogic.gdx.graphics.g3d.utils.RenderContext;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
public class DepthShader extends DefaultShader {
+ public static class Config extends DefaultShader.Config {
+ public boolean depthBufferOnly = false;
+
+ public Config () {
+ super();
+ }
+ public Config (String vertexShader, String fragmentShader) {
+ super(vertexShader, fragmentShader);
+ }
+ }
+
private static String defaultVertexShader = null;
public final static String getDefaultVertexShader() {
if (defaultVertexShader == null)
return defaultFragmentShader;
}
- public static String createPrefix(final Renderable renderable, int numBones, boolean depthBufferOnly) {
+ public static String createPrefix(final Renderable renderable, final Config config) {
String prefix = "";
final long mask = renderable.material.getMask();
final long attributes = renderable.mesh.getVertexAttributes().getMask();
// prefix += "#define "+BlendingAttribute.Alias+"Flag\n";
// if ((mask & TextureAttribute.Diffuse) == TextureAttribute.Diffuse)
// prefix += "#define "+TextureAttribute.DiffuseAlias+"Flag\n";
- if (numBones > 0)
- prefix += "#define numBones "+numBones+"\n";
- if (!depthBufferOnly)
+ if (renderable.bones != null && config.numBones > 0)
+ prefix += "#define numBones "+config.numBones+"\n";
+ if (!config.depthBufferOnly)
prefix += "#define PackedDepthFlag\n";
return prefix;
}
public final int numBones;
public final int weights;
-
- public DepthShader(final Renderable renderable, int numBones, boolean depthBufferOnly) {
- this(getDefaultVertexShader(), getDefaultFragmentShader(), renderable, numBones, depthBufferOnly);
+
+ public DepthShader(final Renderable renderable) {
+ this(renderable, new Config());
}
- public DepthShader(final String vertexShader, final String fragmentShader, final Renderable renderable, int numBones, boolean depthBufferOnly) {
- this(createPrefix(renderable, numBones, depthBufferOnly), vertexShader, fragmentShader, renderable, numBones);
+ public DepthShader(final Renderable renderable, final Config config) {
+ this(renderable, config, createPrefix(renderable, config));
+ }
+
+ public DepthShader(final Renderable renderable, final Config config, final String prefix) {
+ this(renderable, config, prefix,
+ config.vertexShader != null ? config.vertexShader : getDefaultVertexShader(),
+ config.fragmentShader != null ? config.fragmentShader : getDefaultFragmentShader());
}
- public DepthShader(final String prefix, final String vertexShader, final String fragmentShader, final Renderable renderable, int numBones) {
- this(new ShaderProgram(prefix + vertexShader, prefix + fragmentShader), renderable, numBones);
+ public DepthShader(final Renderable renderable, final Config config, final String prefix, final String vertexShader, final String fragmentShader) {
+ this(renderable, config, new ShaderProgram(prefix + vertexShader, prefix + fragmentShader));
}
- public DepthShader(final ShaderProgram shaderProgram, final Renderable renderable, int numBones) {
- super(shaderProgram, renderable, false, false, false, false, 0, 0, 0, numBones);
- this.numBones = numBones;
+ public DepthShader(final Renderable renderable, final Config config, final ShaderProgram shaderProgram) {
+ super(renderable, config, shaderProgram);
+ this.numBones = renderable.bones == null ? 0 : config.numBones;
int w = 0;
final int n = renderable.mesh.getVertexAttributes().size();
for (int i = 0; i < n; i++) {
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g3d.Attribute;
+import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.Renderable;
import com.badlogic.gdx.graphics.g3d.Shader;
-import com.badlogic.gdx.graphics.g3d.lights.DirectionalLight;
-import com.badlogic.gdx.graphics.g3d.lights.Lights;
-import com.badlogic.gdx.graphics.g3d.lights.PointLight;
-import com.badlogic.gdx.graphics.g3d.materials.BlendingAttribute;
-import com.badlogic.gdx.graphics.g3d.materials.ColorAttribute;
-import com.badlogic.gdx.graphics.g3d.materials.IntAttribute;
-import com.badlogic.gdx.graphics.g3d.materials.Material;
-import com.badlogic.gdx.graphics.g3d.materials.TextureAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.BlendingAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.IntAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.TextureAttribute;
+import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
+import com.badlogic.gdx.graphics.g3d.environment.Environment;
+import com.badlogic.gdx.graphics.g3d.environment.PointLight;
import com.badlogic.gdx.graphics.g3d.utils.RenderContext;
import com.badlogic.gdx.graphics.g3d.utils.TextureDescriptor;
import com.badlogic.gdx.math.MathUtils;
private final float[] lightVal = {0,0,0,0};
private final float[] zeroVal4 = {0,0,0,0};
private final float[] oneVal4 = {1,1,1,1};
- private void bindLights(Lights lights) {
+ private void bindLights(Environment lights) {
if (lights == null) {
Gdx.gl10.glDisable(GL10.GL_LIGHTING);
return;
}
Gdx.gl10.glEnable(GL10.GL_LIGHTING);
- Gdx.gl10.glLightModelfv(GL10.GL_LIGHT_MODEL_AMBIENT, getValues(lightVal, lights.ambientLight), 0);
+ if (lights.has(ColorAttribute.AmbientLight))
+ Gdx.gl10.glLightModelfv(GL10.GL_LIGHT_MODEL_AMBIENT, getValues(lightVal, ((ColorAttribute)lights.get(ColorAttribute.AmbientLight)).color), 0);
+ else
+ Gdx.gl10.glLightModelfv(GL10.GL_LIGHT_MODEL_AMBIENT, zeroVal4, 0);
Gdx.gl10.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, zeroVal4, 0);
int idx=0;
Gdx.gl10.glPushMatrix();
context.setBlending(false, GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
if (!currentMaterial.has(ColorAttribute.Diffuse)) {
Gdx.gl10.glColor4f(1,1,1,1);
- if (renderable.lights != null)
+ if (renderable.environment != null)
Gdx.gl10.glDisable(GL10.GL_COLOR_MATERIAL);
} if (!currentMaterial.has(TextureAttribute.Diffuse))
Gdx.gl10.glDisable(GL10.GL_TEXTURE_2D);
int cullFace = defaultCullFace;
- for (final Material.Attribute attribute : currentMaterial) {
+ for (final Attribute attribute : currentMaterial) {
if (attribute.type == BlendingAttribute.Type)
context.setBlending(true, ((BlendingAttribute)attribute).sourceFunction, ((BlendingAttribute)attribute).destFunction);
else if (attribute.type == ColorAttribute.Diffuse) {
Gdx.gl10.glColor4f(((ColorAttribute)attribute).color.r, ((ColorAttribute)attribute).color.g, ((ColorAttribute)attribute).color.b, ((ColorAttribute)attribute).color.a);
- if (renderable.lights != null) {
+ if (renderable.environment != null) {
Gdx.gl10.glEnable(GL10.GL_COLOR_MATERIAL);
Gdx.gl10.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, getValues(lightVal, ((ColorAttribute)attribute).color), 0);
Gdx.gl10.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, getValues(lightVal, ((ColorAttribute)attribute).color), 0);
Gdx.gl10.glPushMatrix();
Gdx.gl10.glLoadMatrixf(currentTransform.val, 0);
}
- bindLights(renderable.lights);
+ bindLights(renderable.environment);
if (currentMesh != renderable.mesh) {
if (currentMesh != null)
currentMesh.unbind();
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.g3d.Renderable;
-import com.badlogic.gdx.graphics.g3d.materials.BlendingAttribute;
+import com.badlogic.gdx.graphics.g3d.attributes.BlendingAttribute;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;
public class DefaultShaderProvider extends BaseShaderProvider {
- /** The overall default number of directional lights to use (can be overridden using the {@link #numDirectionalLights} value) */
- public static int defaultNumDirectionalLights = 2;
- /** The overall default number of point lights to use (can be overridden using the {@link #numPointLights} value) */
- public static int defaultNumPointLights = 5;
- /** The overall default number of spot lights to use (can be overridden using the {@link #numSpotLights} value) */
- public static int defaultNumSpotLights = 3;
- /** The overall default number of bones to use (can be overridden using the {@link #numBones} value) */
- public static int defaultNumBones = 12;
+ public final DefaultShader.Config config;
- /** The uber vertex shader to use. */
- public String vertexShader;
- /** The uber fragment shader to use. */
- public String fragmentShader;
- /** The number of directional lights to use (negative to use {@link #defaultNumDirectionalLights}) */
- public int numDirectionalLights = -1;
- /** The number of point lights to use (negative to use {@link #defaultNumPointLights}) */
- public int numPointLights = -1;
- /** The number of spot lights to use (negative to use {@link #defaultNumSpotLights}) */
- public int numSpotLights = -1;
- /** The number of bones to use (negative to use {@link #defaultNumBones}) */
- public int numBones = -1;
+ public DefaultShaderProvider(final DefaultShader.Config config) {
+ if (!Gdx.graphics.isGL20Available())
+ throw new RuntimeException("The default shader requires OpenGL ES 2.0");
+ this.config = (config == null) ? new DefaultShader.Config() : config;
+ }
public DefaultShaderProvider(final String vertexShader, final String fragmentShader) {
- this.vertexShader = vertexShader;
- this.fragmentShader = fragmentShader;
+ this(new DefaultShader.Config(vertexShader, fragmentShader));
}
public DefaultShaderProvider(final FileHandle vertexShader, final FileHandle fragmentShader) {
}
public DefaultShaderProvider() {
- this(DefaultShader.getDefaultVertexShader(), DefaultShader.getDefaultFragmentShader());
+ this(null);
}
@Override
protected Shader createShader(final Renderable renderable) {
- Gdx.app.log("DefaultShaderProvider", "Creating new shader");
- if (Gdx.graphics.isGL20Available()) {
- return new DefaultShader(
- vertexShader,
- fragmentShader,
- renderable,
- renderable.lights != null,
- renderable.lights != null && renderable.lights.environmentCubemap != null,
- renderable.lights != null && renderable.lights.shadowMap != null,
- renderable.lights != null && renderable.lights.fog != null,
- renderable.lights == null ? 0 : (numDirectionalLights < 0 ? defaultNumDirectionalLights : numDirectionalLights),
- renderable.lights == null ? 0 : (numPointLights < 0 ? defaultNumPointLights : numPointLights),
- renderable.lights == null ? 0 : (numSpotLights < 0 ? defaultNumSpotLights : numSpotLights),
- renderable.bones == null ? 0 : (numBones < 0 ? defaultNumBones : numBones));
- }
- return new GLES10Shader();
+ return new DefaultShader(renderable, config);
}
}
import com.badlogic.gdx.utils.GdxRuntimeException;
public class DepthShaderProvider extends BaseShaderProvider {
- public String vertexShader;
- public String fragmentShader;
- public static boolean depthBufferOnly = false;
+ public final DepthShader.Config config;
- public DepthShaderProvider(final String vertexShader, final String fragmentShader) {
- this.vertexShader = vertexShader;
- this.fragmentShader = fragmentShader;
+ public DepthShaderProvider(final DepthShader.Config config) {
if (!Gdx.graphics.isGL20Available())
- throw new GdxRuntimeException("DepthShaderProvider requires OpenGL ES 2.0");
+ throw new RuntimeException("The default shader requires OpenGL ES 2.0");
+ this.config = (config == null) ? new DepthShader.Config() : config;
+ }
+
+ public DepthShaderProvider(final String vertexShader, final String fragmentShader) {
+ this(new DepthShader.Config(vertexShader, fragmentShader));
}
public DepthShaderProvider(final FileHandle vertexShader, final FileHandle fragmentShader) {
}
public DepthShaderProvider() {
- this(DepthShader.getDefaultVertexShader(), DepthShader.getDefaultFragmentShader());
+ this(null);
}
@Override
protected Shader createShader(final Renderable renderable) {
- Gdx.app.log("DepthShaderProvider", "Creating new shader");
- return new DepthShader(vertexShader, fragmentShader, renderable, renderable.bones == null ? 0 : 12, depthBufferOnly);
+ return new DepthShader(renderable, config);
}
}
\ No newline at end of file
--- /dev/null
+package com.badlogic.gdx.graphics.g3d.utils;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.files.FileHandle;
+import com.badlogic.gdx.graphics.g3d.Renderable;
+import com.badlogic.gdx.graphics.g3d.Shader;
+import com.badlogic.gdx.graphics.g3d.shaders.DefaultShader;
+import com.badlogic.gdx.graphics.g3d.shaders.GLES10Shader;
+
+public class GLES10ShaderProvider extends BaseShaderProvider {
+ @Override
+ protected Shader createShader(final Renderable renderable) {
+ return new GLES10Shader();
+ }
+}
\ No newline at end of file
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.VertexAttributes;
+import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.Model;
-import com.badlogic.gdx.graphics.g3d.materials.Material;
import com.badlogic.gdx.graphics.g3d.model.MeshPart;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
+import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.Model;
-import com.badlogic.gdx.graphics.g3d.materials.Material;
import com.badlogic.gdx.graphics.g3d.model.MeshPart;
import com.badlogic.gdx.graphics.g3d.model.NodePart;
import com.badlogic.gdx.graphics.g3d.model.Node;
package com.badlogic.gdx.graphics.g3d.utils;
+import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.Renderable;
import com.badlogic.gdx.graphics.g3d.Shader;
-import com.badlogic.gdx.graphics.g3d.materials.Material;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
/**