How i simulate reflections in my scene?

I need to create a ground-floor mirrored … I wonder if I make this floor mirrored in 3d studio max and imported into my scene, this floor imporated will simulate reflections in my scene … That's right?



if this isn't gonna work, how i simulate reflections in a texture in jmonkey?

No, that's not correct. 



One way to do a mirrored floor (or a mirror in general) is use the methods of the water simulation tests and use a plane with a water render pass with zero distortion.  Objects that you want reflected will have to be identified in the code.



See:



http://code.google.com/p/jmonkeyengine/source/browse/trunk/src/jmetest/effects/water/TestQuadWater.java



to get started.

Since you ask for ways to simulate them:



Many old games (Deus Ex, Unreal) fake refelctions this way:



Have a room, then do a upside down version directly below it, and use a sthe ground texture something half transparent.



Some szenes here shows this very good

http://www.youtube.com/watch?v=FdoCdvLPEH4

Hm now i feel really retro :confused:

ashtonv , thank so much… im will study this code of simulate water…







Empire Phoenix , great idea that … I like to do something so … I should like it very realistic … and save computer processing … I have much to learn from the older games hauHAUhuHAU



but I need to put a texture on the ground floor … Can I make textures with transparency? if so what is the code for me to do this? you can give me an example using a box?

Flag Rush tutorial will teach you how to use transparent textures. Go about 1/4 the way down that page where it adds the fence to the environment.

For transparent textures, simple way would be to use Photoshop and save it then as a png, since they store transparency directly. Then you need to set it to the right renderque (transparent should be the right one).



If you don't have photoshop, try gimp, it's a bit harder to understand/use but works as well and is opensource.

HI,



I tried to put the effect of water on the texture to get a texture with reflexes, but it's never right … I can not put a texture in waterEffectRenderPass …



someone could give me an example code to help me entente?

What do you mean by "it is never right"?  How about a screenshot to show what is going on and the slice of your code that you are using to implement the reflector and reflectees?

here is all you need:



RenderPass:



import java.net.URL;
import java.util.ArrayList;

import org.lwjgl.opengl.OpenGLException;
import org.lwjgl.opengl.Util;

import com.jme.image.Texture;
import com.jme.image.Texture2D;
import com.jme.image.Texture.MagnificationFilter;
import com.jme.image.Texture.MinificationFilter;
import com.jme.image.Texture.RenderToTextureType;
import com.jme.image.Texture.WrapMode;
import com.jme.math.Plane;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.renderer.TextureRenderer;
import com.jme.renderer.TextureRenderer.Target;
import com.jme.renderer.pass.Pass;
import com.jme.scene.Spatial;
import com.jme.scene.state.CullState;
import com.jme.scene.state.GLSLShaderObjectsState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.CullState.Face;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;


/**
 * <code>ReflectRenderPass</code> Reflect effect pass.
 *
 * @author Rikard Herlitz (MrCoder)
 * @version $Id: ReflectRenderPass.java,v 1.10 2007/02/05 16:51:22 nca Exp $
 */
public class ReflectionRenderPass extends Pass {

  private static final long serialVersionUID = 1L;

  private Camera cam;

  private TextureRenderer tRenderer;

  private Texture2D textureReflect;

  private ArrayList<Spatial> renderList;

  private ArrayList<Texture> texArray = new ArrayList<Texture>();

  private GLSLShaderObjectsState reflectionShader;

  private CullState cullBackFace;

  private TextureState ts;

  private Plane reflectPlane;

  private Vector3f calcVect = new Vector3f();

  private boolean supported = true;

  private int renderScale;

  private URL vert, frag, texture;


  public void resetParameters() {
    reflectPlane = new Plane(new Vector3f(0.0f, 1.0f, 0.0f), 0.0f);

  }


  /**
   * Release pbuffers in TextureRenderer's. Preferably called from user cleanup method.
   */
  public void cleanup() {
    if (isSupported())
      tRenderer.cleanup();
  }


  public boolean isSupported() {
    return supported;
  }


  /**
   * Creates a new ReflectRenderPass
   *
   * @param cam main rendercam to use for reflection settings etc
   * @param renderScale how many times smaller the reflection/refraction textures should be compared to the main display
   */
  public ReflectionRenderPass(Camera cam, int renderScale, boolean useProjectedShader, boolean useRefraction, URL vert,
      URL frag, URL texture) {
    this.cam = cam;
    this.renderScale = renderScale;
    this.vert = vert;
    this.frag = frag;
    this.texture = texture;
    resetParameters();
    initialize();
  }


  private void initialize() {

    DisplaySystem display = DisplaySystem.getDisplaySystem();

    reflectionShader = display.getRenderer().createGLSLShaderObjectsState();

    if (!reflectionShader.isSupported()) {
      supported = false;
    } else {
    }

    cullBackFace = display.getRenderer().createCullState();
    cullBackFace.setEnabled(true);
    cullBackFace.setCullFace(Face.None);

    if (isSupported()) {
      tRenderer =
          display.createTextureRenderer(display.getWidth() / renderScale, display.getHeight() / renderScale,
              8, Target.Texture2D);

      if (tRenderer.isSupported()) {
        tRenderer.setBackgroundColor(new ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f));
        tRenderer.getCamera().setFrustum(cam.getFrustumNear(), cam.getFrustumFar(), cam.getFrustumLeft(),
            cam.getFrustumRight(), cam.getFrustumTop(), cam.getFrustumBottom());

        textureReflect = new Texture2D();
        textureReflect.setWrap(WrapMode.Clamp);
        textureReflect.setMinificationFilter(MinificationFilter.Trilinear);
        textureReflect.setMagnificationFilter(MagnificationFilter.Bilinear);
        textureReflect.setScale(new Vector3f(-1.0f, 1.0f, 1.0f));
        textureReflect.setTranslation(new Vector3f(1.0f, 0.0f, 0.0f));
        tRenderer.setupTexture(textureReflect);

        ts = display.getRenderer().createTextureState();
        ts.setEnabled(true);
        Texture tex = TextureManager.loadTexture(texture, MinificationFilter.Trilinear, MagnificationFilter.Bilinear);
        tex.setWrap(WrapMode.Repeat);
        ts.setTexture(tex, 0);
        ts.setTexture(textureReflect, 1);
        textureReflect.setRenderToTextureType(RenderToTextureType.RGBA);

        reloadShader();
      } else {
        supported = false;
      }
    }

  }


  @Override
  protected void doUpdate(float tpf) {
    super.doUpdate(tpf);

    if (!camLocation.equals(cam.getLocation())) {
      camLocation.set(cam.getLocation());

      float planeDistance = reflectPlane.pseudoDistance(camLocation);
      calcVect.set(reflectPlane.getNormal()).multLocal(planeDistance * 2.0f);
      camReflectPos.set(camLocation.subtractLocal(calcVect));

      camLocation.set(cam.getLocation()).addLocal(cam.getDirection());
      planeDistance = reflectPlane.pseudoDistance(camLocation);
      calcVect.set(reflectPlane.getNormal()).multLocal(planeDistance * 2.0f);
      camReflectDir.set(camLocation.subtractLocal(calcVect)).subtractLocal(camReflectPos).normalizeLocal();

      camLocation.set(cam.getLocation()).addLocal(cam.getUp());
      planeDistance = reflectPlane.pseudoDistance(camLocation);
      calcVect.set(reflectPlane.getNormal()).multLocal(planeDistance * 2.0f);
      camReflectUp.set(camLocation.subtractLocal(calcVect)).subtractLocal(camReflectPos).normalizeLocal();

      camReflectLeft.set(camReflectDir).crossLocal(camReflectUp).normalizeLocal();

      camLocation.set(cam.getLocation());

      tRenderer.getCamera().getLocation().set(camReflectPos);
      tRenderer.getCamera().getDirection().set(camReflectDir);
      tRenderer.getCamera().getUp().set(camReflectUp);
      tRenderer.getCamera().getLeft().set(camReflectLeft);

      texArray.clear();
      texArray.add(textureReflect);

    } // if

  }


  public void doRender(Renderer r) {
    float camPlaneDist = reflectPlane.pseudoDistance(cam.getLocation());

    if (isSupported()) {
      reflectionShader.clearUniforms();

      reflectionShader.setUniform("tex", 0);
      reflectionShader.setUniform("reflection", 1);

      reflectionShader.apply();

      renderReflection();

    } else {
      ts.getTexture().setTranslation(new Vector3f(0, 0, 0));
    }
  }


  public void reloadShader() {

    GLSLShaderObjectsState testShader = DisplaySystem.getDisplaySystem().getRenderer().createGLSLShaderObjectsState();
    try {
      testShader.load(vert, frag);
      testShader.apply();
      Util.checkGLError();
    } catch(OpenGLException e) {
      e.printStackTrace();
      return;
    }

    reflectionShader.load(vert, frag);

  }


  public void setReflectEffectOnSpatial(Spatial spatial) {
    spatial.setRenderState(cullBackFace);
    spatial.setRenderQueueMode(Renderer.QUEUE_SKIP);
    spatial.setRenderState(reflectionShader);
    spatial.setRenderState(ts);
    spatial.updateRenderState();
  }

  // temporary vectors for mem opt.
  private Vector3f tmpLocation = new Vector3f();

  private Vector3f camReflectPos = new Vector3f();

  private Vector3f camReflectDir = new Vector3f();

  private Vector3f camReflectUp = new Vector3f();

  private Vector3f camReflectLeft = new Vector3f();

  private Vector3f camLocation = new Vector3f();


  private void renderReflection() {
    tRenderer.render(renderList, texArray);

  }


  public void clearReflectedScene() {
    if (renderList != null) {
      renderList.clear();
    }
  }


  public void setReflectedScene(Spatial renderNode) {
    if (renderList == null) {
      renderList = new ArrayList<Spatial>();
    }
    renderList.clear();
    renderList.add(renderNode);
    renderNode.updateRenderState();
  }


  public void addReflectedScene(Spatial renderNode) {
    if (renderList == null) {
      renderList = new ArrayList<Spatial>();
    }
    if (!renderList.contains(renderNode)) {
      renderList.add(renderNode);
      renderNode.updateRenderState();
    }
  }


  public Camera getCam() {
    return cam;
  }


  public void setCam(Camera cam) {
    this.cam = cam;
  }


  public float getPlaneHeight() {
    return reflectPlane.getConstant();
  }


  public void setPlaneHeight(float planeHeight) {
    this.reflectPlane.setConstant(planeHeight);
  }


  public Vector3f getNormal() {
    return reflectPlane.getNormal();
  }


  public void setNormal(Vector3f normal) {
    reflectPlane.setNormal(normal);
  }


  public Plane getReflectPlane() {
    return reflectPlane;
  }


  public void setReflectPlane(Plane reflectPlane) {
    this.reflectPlane = reflectPlane;
  }


  public Texture getTextureReflect() {
    return textureReflect;
  }


  public int getRenderScale() {
    return renderScale;
  }


  public void setRenderScale(int renderScale) {
    this.renderScale = renderScale;
  }
}



vertex shader:


varying vec4 viewCoords;

void main()
{
gl_TexCoord[0]  = gl_MultiTexCoord0;
viewCoords = ftransform();
gl_Position = viewCoords;
}



fragment shader:


varying vec4 viewCoords;

uniform sampler2D reflection;
uniform sampler2D tex;


void main()
{
vec4 projCoord = viewCoords / viewCoords.q;
projCoord = (projCoord + 1.0) * 0.5;
vec4 reflectionColor = 0.5 * (texture2D(reflection, projCoord.xy) + texture2D(tex,gl_TexCoord[0].st));
gl_FragColor = reflectionColor;
}

thanks for your help … but this code is not working …



I need a code that allows me to reflect in my textures … for example, simulate the bodywork of a car reflecting the environment … is what I need



code already tested the water and saw that reflects very well the environment, but I could not put that reflection into a texture of a model …



if someone has a simple code by placing the reflection of water in a texture of a model … would help me a lot …

just set the normal texture  of the car to texture 0 and the reflecting texture to 1 with


textureStateCar.setTexture(normalTex, 0);
textureStateCar.setTexture(reflectingTex, 1);



you should be able to get the reflectingTexture from a few modifications in the WaterRenderPass i guess you are using. Then you just have to play around with Texture Combine Modes.

hi,





i try it:




        myStuff.attachChild(n);
       myStuff.attachChild(m);
       myStuff.setModelBound(new BoundingSphere());
       myStuff.updateWorldBound();
       myStuff.updateModelBound();
       myStuff.updateRenderState();
   myStuff.updateGeometricState( 0, true );

        waterRenderPass = new WaterRenderPass(cam, 1, true, false);
        waterRenderPass.setWaterPlane(new Plane(new Vector3f(0.0f, 1.0f,0.0f), 0.0f));
        waterRenderPass.setReflectedScene(myStuff);
        Texture reflectTexture = waterRenderPass.getTextureReflect();

        Texture loadTexture = TextureManager.loadTexture(Main.class
            .getResource("/").getPath()
            + "BACK_LIG.jpg",
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);


        ts.setTexture(loadTexture, 0);
        ts.setTexture(reflectTexture, 1);
        n.setRenderState(ts);



       rootNode.attachChild(myStuff);




(m and n are 2 spheres....)


but the sphere "n", got the blue texture the invez to reflect the other sphere ....

what is my mistake? how to fix this problem and do the work reflection?

the code i gave you only works on planes, but you can easily change that. just take a look at TestCubeMapGLSL.java in the jmetest package and instead of using a Cube map you use the reflection part from the shader above. good luck.

so I realized this method of mapping of TestCubeMapGLSL reflects only the texture introduced …



but I want something more real …



imagine a mobile that has a texture of wood and wood that reflects the other furniture in the room …



that kind of reflection that I want to do …



I know I have to use the method of water … but how I do it?

My simple and probably not working guess is to simply attacha  glsl renderstate with the water effect to the object and hope.

sarkozy said:

so I realized this method of mapping of TestCubeMapGLSL reflects only the texture introduced ...


which is exactly why i have written "instead of using a Cube map you use the reflection part from the shader above".

HELLO,



I tested the code in this example:



http://code.google.com/p/jmonkeyengine/source/browse/trunk/src/jmetest/effects/water/TestSimpleQuadWater.java



… and managed to make the cubes and torus reflect the environment … . was very good effect … :D… but I could only do reflect like a mirror … I could not get the effect of a laminated texture for example … and what I need is to simulate a car’s bodywork that reflects the environment …



the code where I put the texture that reflects the scene:


TextureState ts = display.getRenderer().createTextureState();
        Texture t0 = TextureManager.loadTexture(
                agua.class.getClassLoader().getResource(
                        "BACK_LIG.jpg"),
                Texture.MinificationFilter.Trilinear,
                Texture.MagnificationFilter.Bilinear);
      
       
        ts.setEnabled(true);
       

       
        Texture reflectTexture = waterEffectRenderPass.getTextureReflect();

        ts.setTexture(t0,1);
        ts.setTexture(reflectTexture , 0);



anyone know how I can do this effect laminated texture?