Long answer 1: You could drop the fog filter and compute the fog in every materials of the scene. Meaning changing the lighting j3md so that it computes the fog (maybe the sky material too…if you have one). Add a define to the shader to switch fog on off, then switch it off for your particular cube.
Long answer 2: Keep the filter but overlay another viewport on top of it. and render your cube in this viewport while the rest of the scene is rendered in the background viewport. There may be some frame buffer wiring to do to setup this correctly but it might work.
there could be a long answer 3 where you would render a stencil mask in the lighting.frag then read it in the fog filter shader… but IMO that doubles the work of the 2 previous answers.
Add custom SceneProcessor at the end of the pipeline. Rerender your geometry there using default technique. This is how I made this (highlight on item in the middle):
ViewPort view2 = renderManager.createMainView("overlay", camera);//use the same viewport camera
view2.setClearFlags(false, false, false); // set it to not clear the colors/depth/stencil rendered by the first viewport
view2.attachScene(cube);
Edit: Note that you have to call updateLogicalState() and updateGeometricState() on the cube on each update though.
It’s like three lines of code to add fog to a regular shader and is technically the “right answer”. You will have so much more control this way… whether letting lights not have fog or using different fog colors for different objects, etc…
To me, it is by far the easiest way… to the point where this is 100% how I’ve always done fog in JME and only used the FogFilter once for about 5 seconds 6+ years ago.
It’s not too hard to make a fog shader, but soon I’m facing another problem:
How to apply the fog shader with Lighting.j3md or Unshaded.j3md?
I think the surest way is to rewrite the Lighting.vert / Lighting.frag, and add fog shader into it. But before that I wanna try to reuse the code.
Maybe I can:
Only rewrite a .j3md file and add a Technique to it, is a Technique equals a Pass?
Make a FogControl and override the controlRender method?
or SceneProcessor?
I tried the 1st way, but I failed.
FATAL: Uncaught exception thrown in Thread[jME3 Main,5,main]
com.jme3.asset.AssetLoadException: An exception has occured while loading asset:
Materials/Fog/Lighting.j3md
at
com.jme3.asset.DesktopAssetManager.loadLocatedAsset(DesktopAssetManager.java:261)
at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:373)
at com.jme3.material.Material.<init>(Material.java:108)
at net.jmecn.effect.TestFogLightingShader.createScene(TestFogLightingShader.java:42)
at net.jmecn.effect.TestFogLightingShader.simpleInitApp(TestFogLightingShader.java:26)
at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:220)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:130)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:211)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.IOException: Shader statement syntax incorrect: VertexShader GLSL100
GLSL150: Common/MatDefs/Light/SPLighting.vert
at com.jme3.material.plugins.J3MLoader.readShaderStatement(J3MLoader.java:103)
at com.jme3.material.plugins.J3MLoader.readTechniqueStatement(J3MLoader.java:543)
at com.jme3.material.plugins.J3MLoader.readTechnique(J3MLoader.java:613)
at com.jme3.material.plugins.J3MLoader.loadFromRoot(J3MLoader.java:736)
at com.jme3.material.plugins.J3MLoader.load(J3MLoader.java:757)
at
com.jme3.asset.DesktopAssetManager.loadLocatedAsset(DesktopAssetManager.java:259)
... 8 more
What I did is just copied the Lighting.j3md and add some MaterialParameters and one Technique at end of the file. This is my code.
The exception confused me, why it happend? I read the source of J3MLoader#readShaderStatement, then I’m more confused…
I modified every statement with mult GLSL Version declaration…