Today Morning I found the ConeStepMapDemo.
http://www.lonesock.net/files/ConeStepMapDemo.zip
I like it, and I wanted to use the GLSL SHader in Jmonkey, but I am confused, noting works
My TestCode:
package parallax;
import java.net.URISyntaxException;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme.app.SimpleGame;
import com.jme.image.Image;
import com.jme.image.Texture;
import com.jme.input.FirstPersonHandler;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.light.DirectionalLight;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.shape.Box;
import com.jme.scene.state.GLSLShaderObjectsState;
import com.jme.scene.state.MaterialState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.TextureManager;
import com.jme.util.resource.ResourceLocatorTool;
import com.jme.util.resource.SimpleResourceLocator;
public class Test extends SimpleGame {
private static final Logger logger = Logger.getLogger(Test.class
.getName());
private Vector3f lightDir = new Vector3f();
private GLSLShaderObjectsState so;
private String vertexString = "resources/csm/shared.vert";
private String fragmentString = "resources/csm/relief.frag";
public static void main(String[] args) {
Test app = new Test();
app.setDialogBehaviour(AbstractGame.ALWAYS_SHOW_PROPS_DIALOG);
app.start();
}
protected void simpleUpdate() {
if (KeyBindingManager.getKeyBindingManager().isValidCommand(
"reloadShader", false)) {
reloadShader();
}
float spinValX = FastMath.sin(timer.getTimeInSeconds() * 2.0f);
float spinValY = FastMath.cos(timer.getTimeInSeconds() * 2.0f);
lightDir.set(spinValX, spinValY, -1.0f).normalizeLocal();
}
public void reloadShader() {
GLSLShaderObjectsState testShader = DisplaySystem.getDisplaySystem()
.getRenderer().createGLSLShaderObjectsState();
try {
testShader.load(Test.class.getClassLoader()
.getResource(vertexString),
Test.class.getClassLoader().getResource(
fragmentString));
testShader.apply();
DisplaySystem.getDisplaySystem().getRenderer().checkCardError();
} catch (JmeException e) {
logger.log(Level.WARNING, "Failed to reload shader", e);
return;
}
so.load(Test.class.getClassLoader().getResource(
vertexString), Test.class
.getClassLoader().getResource(fragmentString));
so.setUniform("csm_gain",.1f);
so.setUniform("csm_offset",.25f);
so.setUniform("texsize",.25f);
so.setUniform("depth",.1f);
so.setUniform("linear_search_steps",3);
so.setUniform("binary_search_steps",3);
so.setUniform("reliefmap", 0);
so.setUniform("texmap", 1);
logger.info("Shader reloaded...");
}
protected void simpleInitGame() {
KeyBindingManager.getKeyBindingManager().set("reloadShader",
KeyInput.KEY_F);
// Our model is Z up so orient the camera properly.
cam.setAxes(new Vector3f(-1, 0, 0), new Vector3f(0, 0, 1),
new Vector3f(0, 1, 0));
cam.setLocation(new Vector3f(0, -100, 0));
// Create a directional light
DirectionalLight dr = new DirectionalLight();
dr.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
dr.setAmbient(new ColorRGBA(0.2f, 0.2f, 0.2f, 1.0f));
dr.setSpecular(new ColorRGBA(0.7f, 0.7f, 0.7f, 1.0f));
dr.setDirection(lightDir);
dr.setEnabled(true);
lightState.detachAll();
lightState.attach(dr);
Box box = new Box("box", new Vector3f(), 25, 25, 25);
rootNode.attachChild(box);
try {
ResourceLocatorTool.addResourceLocator(
ResourceLocatorTool.TYPE_SHADER,
new SimpleResourceLocator(getClass().getResource("../resources/csm/")));
} catch (URISyntaxException e1) {
logger.warning("Unable to add texture directory to RLT: "
+ e1.toString());
}
so = display.getRenderer().createGLSLShaderObjectsState();
// Check is GLSL is supported on current hardware.
if (!so.isSupported()) {
logger.severe("Your graphics card does not support GLSL programs, and thus cannot run this test.");
quit();
}
reloadShader();
TextureState ts = display.getRenderer().createTextureState();
Texture heightMap = TextureManager.loadTexture(Test.class
.getClassLoader().getResource(
"resources/csm/collage_height.jpg"),
Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR,
Image.GUESS_FORMAT_NO_S3TC, 0.0f, true);
heightMap.setWrap(Texture.WM_WRAP_S_WRAP_T);
ts.setTexture(heightMap, 0);
Texture baseMap = TextureManager.loadTexture(Test.class
.getClassLoader().getResource(
"resources/csm/collage_base.jpg"),
Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR);
baseMap.setWrap(Texture.WM_WRAP_S_WRAP_T);
ts.setTexture(baseMap, 1);
MaterialState ms = display.getRenderer().createMaterialState();
ms.setColorMaterial(MaterialState.CM_AMBIENT_AND_DIFFUSE);
ms.setAmbient(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
ms.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
ms.setSpecular(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
ms.setShininess(1.0f);
// Set all states on model
box.setRenderState(ts);
box.setRenderState(so);
box.setRenderState(ms);
box.updateRenderState();
rootNode.updateGeometricState(0, true);
input = new FirstPersonHandler( cam, 80, 1 );
}
}
and the original Shaders:
shared.vert
// input from the user
uniform float csm_gain;
uniform float csm_offset;
uniform float texsize;
// interpolate these and pass
// them into the fragment shader
varying vec2 texCoord;
varying vec3 vertex_pos;
varying vec3 light_pos;
varying float vertex_dist;
varying float light_dist;
// distance to the point
varying float dist_val;
void main(void)
{
// location of the vertex in eye space
vec3 eyeSpaceVert = (gl_ModelViewMatrix * gl_Vertex).xyz;
// convert to eyeSpace for programs other than Irrlicht
//eyeSpaceLight = (gl_ModelViewMatrix * vec4(gl_LightSource[0].position.xyz,1.0)).xyz;
// gl_LightSource[n].position is already in eyeSpace from Irrlicht!
vec3 eyeSpaceLight = gl_LightSource[0].position.xyz;
// the matrix needed to convert to eye space
// (this is local, and should already be normalized, I think)
vec3 eyeSpaceTangent = normalize(gl_NormalMatrix * gl_MultiTexCoord1.xyz); //tangent;
vec3 eyeSpaceBinormal = normalize(gl_NormalMatrix * (-gl_MultiTexCoord2.xyz)); //binormal;
vec3 eyeSpaceNormal = normalize(gl_NormalMatrix * gl_Normal); //normal
// now convert the light and position, and pass in the texture coordinate
vertex_pos = vec3 (
dot (eyeSpaceTangent, eyeSpaceVert),
dot (eyeSpaceBinormal, eyeSpaceVert),
dot (eyeSpaceNormal, eyeSpaceVert));
light_pos = vec3 (
dot (eyeSpaceTangent, eyeSpaceLight),
dot (eyeSpaceBinormal, eyeSpaceLight),
dot (eyeSpaceNormal, eyeSpaceLight))
- vertex_pos;
vertex_dist = length (eyeSpaceVert);
light_dist = length (light_pos);
//light_pos /= light_dist;
texCoord = gl_MultiTexCoord0.xy;
// for the LOD
dist_val = (0.00333 * vertex_dist * csm_gain + csm_offset)
/ texsize;
// done
gl_Position = ftransform();
}
relief.frag
uniform float depth;
uniform float texsize;
uniform int linear_search_steps;
uniform int binary_search_steps;
varying vec2 texCoord;
varying vec3 vertex_pos;
varying vec3 light_pos;
varying float vertex_dist;
varying float light_dist;
varying float dist_val;
uniform sampler2D reliefmap;
uniform sampler2D texmap;
void ray_intersect_rm (inout vec3 dp, in vec3 ds);
void main(void)
{
vec4 t,c;
vec3 l,s;
vec3 pt_eye, pt_light;
float a;
// ray intersect in view direction
a = -depth / vertex_pos.z;
s = vertex_pos * a;
s.z = 1.0;
// find the distance to the actualy heightfield
pt_eye = vec3 (texCoord, 0.0);
ray_intersect_rm (pt_eye, s);
/*
gl_FragColor = vec4(pt_eye.z, 0, 0, 0);
return;//*/
// get rm and color texture points
c=texture2D(texmap,pt_eye.xy);
// expand normal from normal map in local polygon space
// blue = df/dx
// alpha = df/dy (image coords are no longer backward!)
// note: I _need_ the texture size to scale the normal properly!
t=texture2D(reliefmap, pt_eye.xy);
t = vec4 ((t.ba-0.5) * (-depth * texsize), 1.0, 0.0);
t=normalize(t);
// adjust the hit-position
// (only useful if the light is near relative
// to the depth)
//p -= v*d*a;
// compute attenuation
float att = gl_LightSource[0].linearAttenuation;
att = min (1.0, 1.0 / (light_dist*att));
// rescale the light vector
l = att * normalize(light_pos);
// compute the final color
gl_FragColor = vec4(
gl_LightSource[0].ambient.xyz*c.xyz
+gl_LightSource[0].diffuse.xyz*c.xyz*max(0.0,dot(l,t.xyz)),
1.0);
}
// vanilla Relief Mapping
void ray_intersect_rm (inout vec3 dp, in vec3 ds)
{
float depth_step=1.0/float(linear_search_steps);
// linear steps
for (int i = 0; i < linear_search_steps; ++i)
{
vec4 t=texture2D(reliefmap,dp.xy);
dp += ds * depth_step * step (dp.z, t.r);
}
// binary search
for (int i = 0; i < binary_search_steps; ++i)
{
vec4 t=texture2D(reliefmap,dp.xy);
dp += ds * depth_step * (step (dp.z, t.r) - 0.5);
depth_step *= 0.5;
}
// all done
return;
}
Now I always get the Error:
23.04.2008 18:56:02 com.jme.scene.state.lwjgl.shader.LWJGLShaderUtil updateUniformLocation
SCHWERWIEGEND: Shader uniform [csm_offset] could not be located in shader
23.04.2008 18:56:02 com.jme.scene.state.lwjgl.shader.LWJGLShaderUtil updateUniformLocation
SCHWERWIEGEND: Shader uniform [csm_gain] could not be located in shader
I dont understand this, these both values are needed in the Vertex Shader. Also when I copy them in the FragmentShader, nothing else comes.
Can SomeBody look at this? the Shaders are realy nice and the Monkey would be also happy :)