Here is a slamm shader i did today, just for fun.
I don’t know the english name of this thing (used to display different advertising) … hell, i don’t even know the french name of it, if it has one.
The result first:
Here is the code. It could/should be improved but i was tired of doing a lot of thing and let them in a non-finished state on my computer, i wanted to have at least something released even if not perfect.
There IS thing in the code that are not usefull and comes from the copy past of the unshaded shader. However i didn’t have time to remove and try and remove and try again.
Advertiser.frag
#if defined(HAS_GLOWMAP) || defined(HAS_COLORMAP) || (defined(HAS_LIGHTMAP) && !defined(SEPARATE_TEXCOORD))
#define NEED_TEXCOORD1
#endif
#if defined(DISCARD_ALPHA)
uniform float m_AlphaDiscardThreshold;
#endif
uniform vec4 m_Color;
uniform sampler2D m_Texture1;
uniform sampler2D m_Texture2;
uniform int m_Fan;
uniform float m_Percent;
varying vec2 texCoord;
varying vec4 vertColor;
void main() {
vec4 color = vec4(1.0);
float val;
float percent;
float base;
#ifdef VERTICAL
val = texCoord.y;
#else
val = texCoord.x;
#endif
val *= m_Fan;
base = floor(val);
val -= base;
base /= m_Fan;
#ifdef DIRECTION
percent = 1 - m_Percent;
#else
percent = m_Percent;
#endif
if ( val <= percent )
{
#ifdef STRETCH
#ifdef VERTICAL
color *= texture2D(m_Texture1, vec2(texCoord.x, base + (texCoord.y-base) / percent ));
#else
color *= texture2D(m_Texture1, vec2(base + (texCoord.x-base) / percent, texCoord.y));
#endif
#else
#ifdef VERTICAL
color *= texture2D(m_Texture1, vec2(texCoord.x, texCoord.y - (percent-1)/m_Fan));
#else
color *= texture2D(m_Texture1, vec2(texCoord.x - (percent-1)/m_Fan, texCoord.y));
#endif
#endif
}
else
{
#ifdef STRETCH
#ifdef VERTICAL
color *= texture2D(m_Texture2, vec2(texCoord.x, base + (val-percent) / ( (1-percent)*m_Fan) ));
#else
color *= texture2D(m_Texture2, vec2(base + (val-percent) / ( (1-percent)*m_Fan), texCoord.y));
#endif
#else
#ifdef VERTICAL
color *= texture2D(m_Texture2, vec2(texCoord.x, texCoord.y - (percent / m_Fan)));
#else
color *= texture2D(m_Texture2, vec2(texCoord.x - (percent / m_Fan), texCoord.y));
#endif
#endif
}
#ifdef HAS_VERTEXCOLOR
color *= vertColor;
#endif
#ifdef HAS_COLOR
color *= m_Color;
#endif
// Set the fragment color for example to gray, alpha 1.0
gl_FragColor = color;
}
Advertiser.j3md
MaterialDef Simple {
MaterialParameters {
Boolean VertexColor (UseVertexColor)
Boolean Direction
Boolean Vertical
Boolean Stretch
Color Color
Texture2D Texture1
Texture2D Texture2
Float Percent
Int Fan
}
Technique {
VertexShader GLSL100: Shaders/Advertiser/Advertiser.vert
FragmentShader GLSL100: Shaders/Advertiser/Advertiser.frag
WorldParameters {
WorldViewProjectionMatrix
}
Defines {
SEPARATE_TEXCOORD : SeparateTexCoord
HAS_VERTEXCOLOR : VertexColor
HAS_COLOR : Color
DIRECTION : Direction
VERTICAL : Vertical
STRETCH : Stretch
}
}
}
Advertiser.vert
#import "Common/ShaderLib/Skinning.glsllib"
#if defined(HAS_COLORMAP) || (defined(HAS_LIGHTMAP) && !defined(SEPARATE_TEXCOORD))
#define NEED_TEXCOORD1
#endif
uniform mat4 g_WorldViewProjectionMatrix;
attribute vec3 inPosition;
attribute vec2 inTexCoord;
attribute vec4 inColor;
varying vec2 texCoord;
varying vec4 vertColor;
void main() {
// Vertex transformation
texCoord = inTexCoord;
#ifdef HAS_VERTEXCOLOR
vertColor = inColor;
#endif
gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);
}
However this shader doesn’t work by itself (i didn’t found a way to have time inside a shader) so here is the controller i wrote to use its functionnality (basic, only two image, can be extended to more without too much difficulties)
Advertiser.java
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package avarra.misc;
import com.jme3.material.Material;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import com.jme3.texture.Texture;
/**
*
* @author Bubuche
*/
public class Advertiser extends AbstractControl
{
private float sleepLength;
private float animationLength;
private float percent;
private float sleep;
private Material material;
public Advertiser(float animationLength, float sleepLength)
{
this.animationLength = animationLength;
this.sleepLength = sleepLength;
}
@Override
public void setSpatial(Spatial spatial)
{
super.setSpatial(spatial);
if ( spatial == null )
return;
material = ((Geometry) spatial).getMaterial();
}
@Override
protected void controlUpdate(float tpf)
{
if ( percent == 1 )
{
sleep += tpf;
if ( sleep >= sleepLength )
{
Texture t1, t2;
t1 = material.getTextureParam("Texture1").getTextureValue();
t2 = material.getTextureParam("Texture2").getTextureValue();
material.setTexture("Texture1", t2);
material.setTexture("Texture2", t1);
percent = 0;
material.setFloat("Percent", percent);
}
}
else
{
sleep = 0;
percent += tpf / animationLength;
if ( percent > 1 ) percent = 1;
material.setFloat("Percent", percent);
}
}
@Override
protected void controlRender(RenderManager rm, ViewPort vp)
{
}
}
And the application/main
AvertiserMain.java
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package avarra.misc;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.VideoRecorderAppState;
import com.jme3.material.Material;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import java.io.File;
/**
*
* @author Bubuche
*/
public class AdvertiserMain extends SimpleApplication
{
public static void main(String args[])
{
SimpleApplication sa = new AdvertiserMain();
sa.start();
}
@Override
public void simpleInitApp()
{
stateManager.attach(new VideoRecorderAppState(new File("advertiser.avi")));
float w = 10;
Geometry geom = new Geometry("Advertiser", new Quad(w, w/2f));
geom.setLocalTranslation(-w/2f, -w/4f, 0);
Material mat = new Material(assetManager, "Shaders/Advertiser/Advertiser.j3md");
mat.setInt("Fan", 6);
mat.setTexture("Texture1", assetManager.loadTexture("Textures/xii/image3.png"));
mat.setTexture("Texture2", assetManager.loadTexture("Textures/xii/image4.PNG"));
mat.setBoolean("Direction", false);
mat.setBoolean("Vertical", true);
mat.setBoolean("Stretch", false);
geom.setMaterial(mat);
geom.addControl(new Advertiser(2, 2));
rootNode.attachChild(geom);
}
}
You can have either a vertical of horizontal replacement, you can specify the number of fans (once again: don’t know the real name of this thing, the rectangle containing a piece of the image) you can choose the direction (left to right, right to left etc) and you can decide if the replacement is be stretching or by sliding.
For this last thing: stretch mode should be used when you have a lot of fans, because it will “emulate” (a bit) the fact that it’s triangles that turns.
You’ll need to edit the package of the java files, the path to images ofc.