Confused with GLSL Shader

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 :frowning:



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 :)

I'd guess that your shader URLs are null.

No the shaders are found. I can out of the this fragmentshader a color on the Cube, if I outcomment one Line (perhabs for debugging). But more not :frowning:

I guess you need to put the variables in the fragment shader as well?


uniform float csm_gain;
uniform float csm_offset;



You should properly debug your shaders in a shader IDE like RenderMonkey before using them in jME, that way you would have to waste less time trying to get them to work in-game.

P.S: I am tired of those monkeys being everywhere..

Jeah, Tanks, I will test it out again