package com.nilunder.bdx.gl; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.g3d.Attributes; import com.badlogic.gdx.graphics.g3d.Renderable; import com.badlogic.gdx.graphics.g3d.Shader; 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.shaders.DefaultShader; import com.badlogic.gdx.graphics.g3d.utils.DefaultShaderProvider; import com.nilunder.bdx.Bdx; import com.nilunder.bdx.Scene; class BDXDefaultShader extends DefaultShader { public final int u_shadeless = register("u_shadeless"); public final int u_tintColor = register("u_tintColor"); public final int u_emitColor = register("u_emitColor"); public final int u_fogRange = register("u_fogRange"); public final int u_camRange = register("u_camRange"); BDXShaderProvider shaderProvider; Material applyingMaterial = null; public BDXDefaultShader(Renderable renderable, Config config) { super(renderable, config); } public BDXDefaultShader(Renderable renderable, DefaultShader.Config config, MaterialShader materialShader) { super(renderable, config, materialShader.setPrefix(createPrefix(renderable, config)).compile().programData); } public void render(Renderable renderable, Attributes combinedAttributes) { if(renderable.material.has(BlendingAttribute.Type)) { BlendingAttribute ba = (BlendingAttribute) renderable.material.get(BlendingAttribute.Type); Gdx.gl.glBlendFuncSeparate(ba.sourceFunction, ba.destFunction, GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA); } IntAttribute shadeless = (IntAttribute) renderable.material.get(Scene.BDXIntAttribute.Shadeless); if (shadeless == null) set(u_shadeless, 0); else set(u_shadeless, shadeless.value); ColorAttribute tint = (ColorAttribute) renderable.material.get(Scene.BDXColorAttribute.Tint); if (tint == null) set(u_tintColor, new Color()); else set(u_tintColor, tint.color); ColorAttribute emit = (ColorAttribute) renderable.material.get(Scene.BDXColorAttribute.Emit); if (emit == null) set(u_emitColor, new Color()); else set(u_emitColor, emit.color); if (shaderProvider.scene != null) { ColorAttribute fog = (ColorAttribute) renderable.environment.get(ColorAttribute.Fog); if (fog == null) set(u_fogRange, 0f, 0f); else set(u_fogRange, shaderProvider.scene.fogRange().x, shaderProvider.scene.fogRange().y); set(u_camRange, shaderProvider.scene.camera.near(), shaderProvider.scene.camera.far()); } super.render(renderable, combinedAttributes); } public boolean canRender(Renderable renderable) { Material bdxMat = null; if (renderable.material instanceof Material) bdxMat = (Material) renderable.material; if (bdxMat != null) { if (bdxMat.shader != null && bdxMat.shader.active) // Is there a custom shader specified for the rendered material? If so, return bdxMat.shader.programData == program; // Use this shader only if this is the shader for the material. else // Otherwise, the rendered material doesn't have a custom shader specified, so return applyingMaterial == null && super.canRender(renderable); // Use this shader only if it's not a custom shader } else // We're rendering something that isn't even a BDX Material, so never mind return super.canRender(renderable); } } public class BDXShaderProvider extends DefaultShaderProvider { Scene scene; public BDXShaderProvider(){ super(new DefaultShader.Config(Gdx.files.internal("bdx/shaders/3d/default.vert").readString(), Gdx.files.internal("bdx/shaders/3d/default.frag").readString())); config.numPointLights = 8; config.numSpotLights = 8; config.numDirectionalLights = 2; } public Shader createShader(Renderable renderable) { BDXDefaultShader bdxDefaultShader; Material bdxMat = null; if (renderable.material instanceof Material) bdxMat = (Material) renderable.material; if (bdxMat != null && bdxMat.shader != null && bdxMat.shader.active) { bdxDefaultShader = new BDXDefaultShader(renderable, config, bdxMat.shader); bdxDefaultShader.applyingMaterial = bdxMat; } else { if (Bdx.Display.advancedLighting()) bdxDefaultShader = new BDXDefaultShader(renderable, config); else { DefaultShader.Config lowConfig = new DefaultShader.Config(Gdx.files.internal("bdx/shaders/3d/vertexLighting.vert").readString(), Gdx.files.internal("bdx/shaders/3d/vertexLighting.frag").readString()); lowConfig.numPointLights = config.numPointLights; lowConfig.numSpotLights = config.numSpotLights; lowConfig.numDirectionalLights = config.numDirectionalLights; bdxDefaultShader = new BDXDefaultShader(renderable, lowConfig); } } bdxDefaultShader.shaderProvider = this; return bdxDefaultShader; } public void update(Scene scene){ this.scene = scene; } public void deleteShaders(){ for (Shader s : shaders){ BDXDefaultShader bdxDefaultShader = (BDXDefaultShader) s; if (bdxDefaultShader.applyingMaterial != null && bdxDefaultShader.applyingMaterial.shader != null) bdxDefaultShader.applyingMaterial.shader.dispose(); // "Empty" (dispose()) the MaterialShader. else s.dispose(); } shaders.clear(); } }