Nice effect from mystirous game

Recently started to play a game and there is really interesting for me effect. When you are under something (house, mountain…) your model displayed x-rayed (I saw the thread about x-ray shader). If only part of the model is under something then that part of the model displayed x-rayed.



Does anyone have a clue how this can be done?



Attached some screenshots for you to understand the idea

Just like this, except you would also have the shader in the pass. Its pretty self explanitory.



import com.jme.app.SimpleGame;
import com.jme.app.SimplePassGame;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.Renderer;
import com.jme.renderer.pass.OutlinePass;
import com.jme.renderer.pass.RenderPass;
import com.jme.scene.Spatial;
import com.jme.scene.shape.RoundedBox;
import com.jme.scene.state.CullState;
import com.jme.scene.state.RenderState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.scene.state.CullState.Face;
import com.jme.scene.state.ZBufferState.TestFunction;
import com.jme.util.TextureManager;

public class TestRoundedBox extends SimplePassGame {
   private Quaternion rotQuat = new Quaternion();
   private float angle = 0;
   private Vector3f axis = new Vector3f(1, 1, 0);
   private RoundedBox s;
   
   /**
    * Entry point for the test,
    *
    * @param args
    */
   public static void main(String[] args) {
      TestRoundedBox app = new TestRoundedBox();
      app.setConfigShowMode(ConfigShowMode.AlwaysShow);
      app.start();

   }

   protected void simpleUpdate() {
      if (tpf < 1) {
         angle = angle + (tpf * 1);
         if (angle > 360) {
            angle = 0;
         }
      }
      rotQuat.fromAngleAxis(angle, axis);
      s.setLocalRotation(rotQuat);
   }

   protected void simpleInitGame() {
      display.setTitle("jME - Sphere");

       s = new RoundedBox("Sphere", new Vector3f(10,10,10), new Vector3f(0.5f, 0.5f, 0.5f), new Vector3f(0.5f, 0.5f, 0.5f));
       s.setLocalTranslation(new Vector3f(0,0,-40));
       s.setModelBound(new BoundingBox());
       s.updateModelBound();
       rootNode.attachChild(s);

       RoundedBox s2 = new RoundedBox("Sphere", new Vector3f(10,10,10), new Vector3f(0.5f, 0.5f, 0.5f), new Vector3f(0.5f, 0.5f, 0.5f));
       s2.setLocalTranslation(new Vector3f(0,0,-80));
       s2.setModelBound(new BoundingBox());
       s2.updateModelBound();
       rootNode.attachChild(s2);
      
       RenderPass pass = new RenderPass();
      pass.add(rootNode);
      pass.setEnabled(true);
      pManager.add(pass);
      
      
      
      final ZBufferState zb = display.getRenderer().createZBufferState();
       zb.setFunction(TestFunction.GreaterThan);
       zb.setWritable(true);
      
      final CullState cs = display.getRenderer().createCullState();
      cs.setCullFace(Face.Back);
      cs.setEnabled(true);
      
       final TextureState ts = display.getRenderer().createTextureState();
       ts.setEnabled(true);
       ts.setTexture(
           TextureManager.loadTexture(
           TestSphere.class.getClassLoader().getResource(
           "jmetest/data/images/Monkey.jpg"),
           Texture.MinificationFilter.Trilinear,
           Texture.MagnificationFilter.Bilinear));
      
      RenderPass shade = new RenderPass() {
         public void doRender(Renderer r) {
            
            context.enforceState(zb);
            context.enforceState(cs);
            context.enforceState(ts);
            for (int i = 0, sSize = spatials.size(); i < sSize; i++) {
                  Spatial s = spatials.get(i);
                  r.draw(s);
              }
              r.renderQueue();
             
              context.clearEnforcedStates();
         }
      };
      shade.add(s2);
      shade.setEnabled(true);
      pManager.add(shade);
   }
}

Think he was talking more how to do it in the shader itself. I don't know, but since you want to know if the character can be seen or not, I'd bet the depth buffer is used to determine if that pixel should be rendered normally, or rendered using the x-ray effect.

Starnick said:

Think he was talking more how to do it in the shader itself. I don't know, but since you want to know if the character can be seen or not, I'd bet the depth buffer is used to determine if that pixel should be rendered normally, or rendered using the x-ray effect.


Yes... The question really is how to determine that one object or part of it is under another object and apply effect to it's vertexes that are currently under another object.... I haven't seen any examples of working with depth buffer... Are there any examples available ?

Thats exactly what my example showed. Except I applied a texture state instead of a glslobjectstate. Tho if you wanted to do it in the glsl, then im not sure what method would be best. Is this a coursework question? does it especially say to do it all in glsl?

AlexChux said:

Starnick said:

Think he was talking more how to do it in the shader itself. I don't know, but since you want to know if the character can be seen or not, I'd bet the depth buffer is used to determine if that pixel should be rendered normally, or rendered using the x-ray effect.


Yes... The question really is how to determine that one object or part of it is under another object and apply effect to it's vertexes that are currently under another object.... I haven't seen any examples of working with depth buffer... Are there any examples available ?


Most likely, you'll have to keep track of the depth buffer yourself, that is, you save the contents into a texture and pass that into your shader when you render the character. Pretty sure you can google for examples on that.
d0md0md0m said:

Thats exactly what my example showed. Except I applied a texture state instead of a glslobjectstate. Tho if you wanted to do it in the glsl, then im not sure what method would be best. Is this a coursework question? does it especially say to do it all in glsl?


I've looked throught your code more in deph and understood the idea !!! Thank you very much !!

You don't need to save the depth buffer to texture, there's a more efficient way. You just need a 1 bit stencil buffer. Render the character model with stencil that writes 1 when depth test fails, then render the xray shader applied to character with stencil test equal to 1.