Viewport "resets" when adding a FilterPostProcessor (BloomFilter)

Well… When I run TestMultiViewsFilter, things seem to work great. No contest. But it’s not in my game.



But I do things very differently.



For starters, TestMultiViewsFilter clone the main camera and apply a filter to it. I don’t do that. I make a new camera and I think that’s why I’m having a totally different result.



I do things this way because the object in the viewports is NOT in the main view. All objects in the main game view are only colored dots representing stars and that wouldn’t work with a cloned camera. So I build a scene with a sphere with some material and stick a camera close to it and apply this to a viewport.



Here’s the complete class. This should be easier to understand than my ramblings.

[java]

package com.madjack.games.sc.scenes;



import com.jme3.light.PointLight;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.post.FilterPostProcessor;

import com.jme3.post.filters.BloomFilter;

import com.jme3.post.filters.FogFilter;

import com.jme3.renderer.Camera;

import com.jme3.renderer.ViewPort;

import com.jme3.texture.Texture;

import com.madjack.games.sc.Base;

import com.madjack.games.sc.GameLogic;

import com.madjack.games.sc.galaxy.Galaxy;

import com.madjack.games.sc.galaxy.spacebodies.SolarSystem;

import com.madjack.games.sc.galaxy.spacebodies.Star;

import com.madjack.games.sc.utils.GameManagers;

import com.madjack.games.sc.utils.GameNode;



/**

*

  • @author MadJack

    /

    public class PreviewScene extends Base {



    private ViewPort panelViewPort;

    private Camera panelCam;

    private GameNode panelNode;

    private static GameLogic gProc;

    private static GameManagers gMgrs;

    private String viewportName;

    private ObjectPreviewScene objectPreviewScene;

    private boolean isRotatable = true;

    private PointLight pointLight;

    Object objectInView;



    /

  • Constructor
  • @param gProcessor, GameProcessor used to load assets

    /

    public PreviewScene(GameLogic gProc, GameManagers gMgrs) {

    if (gProc == null || gMgrs == null) {

    throw new IllegalStateException("GameProcessor and/or GameManagers not initialized.");

    }

    initPreviewScene();

    this.gProc = gProc;

    this.gMgrs = gMgrs;

    }



    /

  • PreviewScene

    *
  • @param gProc GameProcessor
  • @param gMgrs GameManagers
  • @param viewportName Name of the viewport to create
  • @param pickedObject Object we want a preview of

    *

    /

    public PreviewScene(GameLogic gProc, GameManagers gMgrs, String viewportName, Object pickedObject) {

    this(gProc, gMgrs);

    initPreviewScene();

    makePreviewScene(viewportName, pickedObject);

    }



    /

  • PreviewScene

    *
  • @param viewportName Name of the viewport to create
  • @param pickedObject Object we want a preview of

    *
  • NOTE: if either GameProcessor or GameManagers haven’t been set before
  • the method will throw an IllegalStateException.

    *

    /

    public PreviewScene(String viewportName, Object pickedObject) {

    if (gProc == null || gMgrs == null) {

    throw new IllegalStateException("GameProcessor and/or GameManagers not initialized.");

    }

    initPreviewScene();

    makePreviewScene(viewportName, pickedObject);

    }



    private void initPreviewScene() {

    objectPreviewScene = new ObjectPreviewScene(gMgrs);

    }



    /

  • makePreviewScene
  • @param viewportName Name of the ViewPort
  • @param pickedObject Object selected to make a preview of

    *
  • makePreviewScene will setup the PreviewScene with the main selected object
  • and all subobjects if applicable (moons for a planet).

    /

    final public void makePreviewScene(String viewportName, Object pickedObject) {

    System.out.println("…Making viewport named: " + viewportName);

    this.objectInView = pickedObject;

    this.viewportName = viewportName;



    setPanelCamera(viewportName);

    panelNode = objectPreviewScene.getScene(objectInView);

    if (objectInView instanceof Star) {

    panelCam.setLocation(new Vector3f(10, 0, 0));

    panelCam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);

    isRotatable = true;

    pointLight = new PointLight();

    pointLight.setColor(((Star) objectInView).getColor());

    pointLight.setPosition(panelCam.getLocation());

    pointLight.setRadius(50f);

    } else if (objectInView instanceof Galaxy) {

    isRotatable = false;

    } else if (objectInView instanceof SolarSystem) {

    isRotatable = false;

    }



    setViewPort(viewportName);

    attachNewSceneToViewport(panelNode);

    setViewPortEnabled(true);

    setPostProcess();

    }



    /

  • Deletes named viewport
  • @param viewPortName Name of the viewport to remove.

    /

    public void deleteViewPort(String viewPortName) {

    System.out.println("…Destroyed viewport: " + viewPortName);

    gMgrs.getRenderManager().removeMainView(viewPortName);

    panelViewPort = null;

    }



    /

  • Removes all children from preview node.

    /

    public void deleteAll() {

    panelNode.detachAllChildren();

    isRotatable = false;

    }



    /

  • Deletes default (rightPanel) viewport

    /

    void deleteViewPort() {

    deleteViewPort(panelViewPort.getName());

    }



    /

  • updatePreviewScene
  • updates the preview scene.
  • @param pickedObject Object selected.

    */

    final void updatePreviewScene(Object pickedObject) {

    // don’t process if same object

    if (objectInView == pickedObject) {

    return;

    }

    objectInView = pickedObject;

    changeObjectParams();

    }



    private void changeObjectParams() {

    System.out.println("…Updating viewport named: " + viewportName);



    if (viewportName.equals(“listPreview”)) {



    // System.out.println("…Object to change to -> " + objectInView);

    panelNode = objectPreviewScene.getScene(objectInView);

    isRotatable = true;

    attachNewSceneToViewport(panelNode);



    } else if (viewportName.equals(“rightPreview”)) {

    // we’re in the right preview viewport; update star there

    if (objectInView instanceof Star) {

    retextureStar((Star) objectInView);

    }

    }

    // System.out.println(“Fully updated viewport.n”);

    }



    private void retextureStar(Star star) {

    Texture texture = gMgrs.getAssetManager().loadTexture(

    “Textures/Stars/Class”
  • star.getSpectralClass()
  • ".png");

    Material material = gMgrs.getAssetManager().loadMaterial(

    "Materials/Stars/Class"
  • star.getSpectralClass()
  • "Star.j3m");

    ColorRGBA color = star.getColor();

    objectPreviewScene.retextureBody(texture, material, color);

    }



    /*
  • getPanelNode returns the GameNode that is attached to the viewport
  • @return GameNode

    /

    GameNode getPanelNode() {

    return panelNode;

    }



    /

  • setViewPort
  • @param previewName String, name of the preview

    *
  • Sets basic viewport properties.

    /

    private void setViewPort(String viewportName) {

    panelViewPort = gMgrs.getRenderManager().createMainView(viewportName, panelCam);

    panelViewPort.setBackgroundColor(ColorRGBA.DarkGray);



    if (viewportName.equals("listPreview")) {

    setListPreviewSceneParams();

    } else if (viewportName.equals("rightPreview")) {

    setRightPreviewSceneParams();

    }

    }



    private void setListPreviewSceneParams() {

    // set viewport params

    setViewPortAreas(2.46f, 3.46f, 2.76f, 3.76f);

    setViewPortCamSize(165, 165);

    setCameraLocation(new Vector3f(10, 0, 0));

    setCameraLookAt(Vector3f.ZERO);

    }



    private void setRightPreviewSceneParams() {

    setViewPortAreas(5.23f, 6.33f, 0.56f, 1.66f);

    setViewPortCamSize(200, 200);

    setCameraLocation(new Vector3f(10, 0, 0));

    setCameraLookAt(Vector3f.ZERO);

    }



    /

  • attachNewSceneToViewport
  • @param noteToAttach
  •  new node to attach to viewport<br />
    

/

private void attachNewSceneToViewport(GameNode nodeToAttach) {

panelViewPort.clearScenes();

panelViewPort.attachScene(nodeToAttach);

System.out.println("…Attached scene on: " + panelViewPort);

}



private void setPostProcess() {

FilterPostProcessor fpp = new FilterPostProcessor(globalAssetManager);



FogFilter ff = new FogFilter(ColorRGBA.Magenta, .25f, .75f);



BloomFilter bf = new BloomFilter(BloomFilter.GlowMode.Objects);

bf.setExposurePower(10f);



// fpp.addFilter(bf);

fpp.addFilter(ff);



panelViewPort.addProcessor(fpp);



System.out.println("…PostProcess set on: " + panelViewPort);

}



/

  • setViewPortEnabled
  • @param state, boolean state to set the viewport at.

    /

    public void setViewPortEnabled(boolean state) {

    if (panelViewPort.getScenes().isEmpty()) {

    throw new IllegalStateException("Viewport does not have a scene attached.");

    }

    panelViewPort.setEnabled(state);

    }



    /

  • isViewPortExist()
  • @return Returns viewport’s state

    /

    public boolean isViewPortExist() {

    if (panelViewPort == null) {

    return false;

    } else {

    return true;

    }

    }



    private void setPanelCamera(String viewportName) {

    panelCam = new Camera(165, 165);

    panelCam.setName(viewportName);

    panelCam.setFrustumPerspective(90.0f, 1f, 1f, 75f);

    }



    protected void setCameraLocation(Vector3f location) {

    panelCam.setLocation(location);

    }



    protected void setCameraLookAt(Vector3f lookAt) {

    panelCam.lookAt(lookAt, Vector3f.UNIT_Y);

    }



    /

  • setViewPortAreas
  • @param float left
  • @param float right
  • @param float bottom
  • @param float top

    *
  • Used to set the viewport areas

    /

    private void setViewPortAreas(float left, float right, float bottom, float top) {

    panelCam.setViewPort(left, right, bottom, top);

    }



    /

  • setViewPortCamSize
  • @param int width
  • @param int height

    *
  • Height and width of the viewport camera.

    /

    private void setViewPortCamSize(int width, int height) {

    panelCam.resize(width, height, true);

    }



    /

  • getPreviewName
  • @return String PreviewName

    /

    String getPreviewName() {

    return viewportName;

    }



    /

  • isRotatable
  • @return true if the preview is stand-alone and not an image.

    */

    boolean isRotating() {

    return isRotatable;

    }

    }

    [/java]



    If you have suggestions or fixes I’ll gladly take them.

DOH! Forgot to tell what the result looks like here.



Well, first, in the main game viewport, BloomFilter doesn’t seem to work anymore. FogFilter works. Preview viewports look like they are not there at all.



If I remove Filter(s) from the main game viewport, the preview viewports work without any Filter but still is transparent (like the screenshot above). If I use filter(s) on those viewports, there is nothing to be seen. It’s like the viewports are nonexistent. There is no fog and nothing at all.



HTH

Mhh ok, why do you change the camera size? I mean you should keep the camera fullscreen size, and just tweak the viewport.

This way cam.setViewport values are from 0 to 1.

for example :



panelCam.resize(cam.getWItdh(),cam.getHeight(),true);

panelCam.setViewPort(0.8f,0.9f,0.8f,0.9f);



I’m gonna try to create a test case like your game.

That was some months ago, so I don’t recall the exact reasons why I went this way, but I think I remember having issues with distortions when the viewport was resized. There’s also the fact that where the previews are attached on the screen are 165x165 and 200x200 pixels respectively and that’s much easier to make a camera that size than to find the proper ratio to set the viewport to (like 0.22458f).



I’ll admit that I’m bit confused what the setViewPort(x,x,x,x) do exactly. I know it’s the boundaries, but applied on what? From my tests, I use:



setViewPortBoundaries(2.46f, 3.46f, 2.76f, 3.76f);



and



setViewPortBoundaries(5.23f, 6.33f, 0.56f, 1.66f);



Those two place the viewports where they are on the screen, but how do they achieve it? I’m clueless. By default the game’s resolution is 1280x1024 and I don’t understand how those numbers relate to the resolution. Call it a hack if you want and that may be what’s giving me problems.

Well, it’s simple setViewport crop the camera view. so if you have a 640 x 480 camera and set the view port to left= 0.25, right= 0.75,bottom = 0.25, top = 0.75, you’ll have a centered view of 320 x 240 IN the original camera view.



When you resize your camera to 200 x 200 and set the view port to values above 1, it means that your view port is outside of the original camera view. I guess it’s what messing with the filters.



If you want t use pixels to define your viewport’s width and height just divide them by the camera width and height like this :



float viewPortLeft=300 / panelCam.getWidth().; //300 pixels ;

float viewPortWidth=200 / panelCam.getWidth().; //200 pixels ;



this way it more convenient and you won’t bother with decimals values.

Huh, ok. I think I get it.



Trying to follow your explanation above using 640x480.

left = 640x.25 = 160

right = 640x.75 = 480

top = 480x.25 = 120

bottom = 480x.75 = 360



right - left = 320

bottom - top = 240



So that would create a viewport the size of the camera centered on 320x240 of the game screen. Do I get this right?



For different screen resolutions I can always use a fixed point derived from with and height. That would work.



What I don’t get though is how come if I don’t apply a Filter, the object in the viewports are rendered properly, but not if I apply a BloomFilter for exemple?



I don’t know if that makes a difference or not, but I don’t “resize” the cameras, I create them at those sizes (165x165 and 200x200).

For the viewport calculation at the beginning of your post, you got it right, except you inverted top and bottom values. Y coordinates go from bottom to top.



Viewport are rendered properly without filters, because Filters does not support viewports the same way and in your case it fails.



I won’t go into technical details it would be too long but :

A Filter is a quad rendered in full screen on which you apply the rendered scene as a texture. You just apply the desired effect in the material you apply to this quad.



So to make it short, to render a filter on a viewport, I create a filter cam that has the size of the screen, I create a quad that has the size of the viewport.

The viewport cam is resized to the size of the viewport and the setViewport params are set to default (0,1,0,1) (would be 320 x 240 in the previous example).

I render the scene in a frame buffer, in a texture that has the size of the viewport.

Then I render on screen the quad with this texture positioned where the viewport should be.



And the problem with your game is in this very last operation, for it to work, your viewport HAS to be inside the camera view. Because the quad won’t be rendered if it’s outside of the view frustum.



I didn’t test it so it’s pure theory, just try to position your viewport like I explained and see what it does.

I’ll have to do this later when I’ll be working on the project. I’ll let you know how it turns out.

I’ve tried getting some results but didn’t get very far.



I’ve checked the camera and how things are set and RenderManager.java sets the camera in setViewPort(Camera cam). It goes like this:



Lines 602+

[java]

private void setViewPort(Camera cam) {

// this will make sure to update viewport only if needed

if (cam != prevCam || cam.isViewportChanged()) {

viewX = (int) (cam.getViewPortLeft() * cam.getWidth());

viewY = (int) (cam.getViewPortBottom() * cam.getHeight());

viewWidth = (int) ((cam.getViewPortRight() - cam.getViewPortLeft()) * cam.getWidth());

viewHeight = (int) ((cam.getViewPortTop() - cam.getViewPortBottom()) * cam.getHeight());

renderer.setViewPort(viewX, viewY, viewWidth, viewHeight);

renderer.setClipRect(viewX, viewY, viewWidth, viewHeight);

cam.clearViewportChanged();

prevCam = cam;



[/java]



I’ve done some tests and if I set my camera at 200x200 pixels and sets the viewport to 0,1,0,1, I’ll get a viewport (and its content) in the lower left corner of the main screen (0x0). That viewport remains the same size as the camera → 200x200. If I use 1,2,1,2, I still get a viewport 200x200 but starting at 200x200 on the main screen, 200 wide and 200 high. As I use different values for panelCam.setViewPort(left, right, bottom, top); the result is the same (viewport keeps the same size but displayed at different areas on the screen) as long as I keep a ratio of 1 for left/right, top/bottom.



This tells me that, when I used:



[java]panelCam.setViewPort(5.23f, 6.33f, 0.56f, 1.66f);[/java]



It is doing exactly what I thought it was doing; it locates the viewport relative to the cam’s width onto the main screen.



So what it actually does is when I use those values above, the viewport is located at:1046x112 and is 220 wide x 220 high.



Further tests showed me that using fractions would resize the viewports. So if I use 0, .5, 0, .5, everything would be shrinked by half. The spot where it’ll be placed and also the viewport’s size, and that even if I use a camera of say 200x200 pixels, because of the viewport’s values, it will get resized.



I know it’s obvious to you guys but I’m trying to figure it all out and also trying to explain the discrepancies I’m getting. So far, no explanations I can conclude. :frowning:



After the ellipsis above, setViewPort sets some orthoMatrix. I won’t even go into what that could be doing as I have no idea. But one thing I know is that what I see on the screen goes with what I pasted.



Anyway. Long story has to end; what exactly is it I’m doing wrong?



Also @nehon, I’ve tried real hard to set things up with what you suggested but I only could get a “blank” preview. My guess is, where ever it is, it’s off-screen because there’s nothing displaying in the viewport but the FPS dips by about 20-35 FPS.



If anyone cares, the viewport should be centered at: 1152x225 (if I use nehon’s suggestion posted above) and should be 220 wide x 220 high.



Can’t wait to have all this make sense. :confused:

ok maybe i need to re-re-think this in order filter viewports to work as standard viewports…

Also I don’t if it’s gonna be possible

I sure you’ll come up with some brilliant idea and fix it @nehon. I believe! :smiley:

Ok I tested it again using your parameters but converted so that the viewport is inside of the camera view, and it works flawlessly.

Well almost …there was just an aspect ratio issue, and i fixed it (you may need to update)

this



Camera cam5 = new Camera(200, 200);

cam5.setFrustumPerspective(45f, (float)cam.getWidth() / cam.getHeight(), 1f, 1000f);

cam5.setViewPort(5.23f, 6.33f, 0.56f, 1.66f);



can be changed to this

[java]

Camera cam5 = new Camera(settings.getWidth(), settings.getHeight();

cam5.setFrustumPerspective(45f, (float)cam.getWidth() / cam.getHeight(), 1f, 1000f);

cam5.setViewPort(1046f/settings.getWidth(), 1266f/settings.getWidth(), 112f/settings.getHeight(), 332f/settings.getHeight());

[/java]

the 1046, 1266, 112, 332 are just your params multiplied by 200.

here is the result with a bloom filter (see the greenish glowy teapot in the bottom right)



Could you please try this in your app?

1 Like

It seems to be working, but I must lack something in the preview as the viewport is entirely black. For testing purpose I only changed the settings in the right preview viewport.



So we’re clear while using post processing:

  • For now the scene is all black (read below), nothing is in there.
  • With those new “settings”, I do have a viewport.
  • It ignores the background color set in viewport
  • If I keep the new way to set things up and not use post processing, the viewport vanishes (effectively inverting the situation we had in the first place, but that can be fixed if game option to use post processing is disabled).



    Anyway. Take those results as preliminary. I just woke up, maybe like 1/2 hour ago, and I’ll do things the right way instead of putting static values. It is entirely possible I missed something. So I’ll do a thorough investigation and report back.



    BTW, to have a successful Glow, what is needed? Light? Certain kind of texture? Would point light, ambient or directional work the same? Just want to make sure I have things set up right before saying it’s not working properly.



    Thanks a ton @nehon You’ve been a great help. :smiley:

Damn typo!



Ok. The GlowFilter now works. It’s not pretty, but it does. Looks more like an X-Ray in black & white to be honest. :wink:



The other issues are still there though.

Plus, viewports without a post process filter are transparent.







What I’d like the Glow filter to look like is to use the color of the star, not black and white. :confused: How does the filter come up with the colors to use? I use a point light right now, but I’ll try other kind of lights and see what happens.

Just set the GlowColor attribute to the material of the planet

to achieve the glowing teapot , I just did teapot.getMaterial.setColor(“GlowColor”,ColorRGBA.Green);

Also set the bloomFilter mode to GlowMode.Objects.

Anyway your black and white image is still strange…



For the dark background with the glow filter it’s another issue, i’m gonna look into it.



For the transparent background with standard viewport I guess It’s a clear issue

Hmmm… I might have a problem with the textures I’m using because if I use what you’re saying, I don’t get the glow. It looks “normal”.



I looked up how to do GlowMaps on some site some time ago and they were saying to take the texture that I wanted glowing, remove anything that I didn’t want to glow and make the rest white and shades of white. Then in the GlowColor, give the color I wanted that glow texture to be. Does that sound right to you?



Here’s the material definition.





Oh btw, you should use:



[java]

cam5.setFrustumPerspective(45f, 1f, 1f, 1000f);

[/java]



instead of:



[java]

cam5.setFrustumPerspective(45f, (float)cam.getWidth() / cam.getHeight(), 1f, 1000f);

[/java]



That way your viewport won’t be squished. At that point the viewport is at 200x200, you don’t want it ratio’d since it already is.

I was successful in having a glow by removing the GlowMap texture. Now, the sun looks like a ball of glowing red, but it has lost its underlying texture…



The question is, is that right? I mean, if I use a GlowMap texture (as explained above), shouldn’t the color be applied to that texture? Then the texture be applied to the object on top of the textures defined in the material?



If that’s the case I’ll start a new thread specifically for that, but I’ll wait for a confirmation first.

Dude…i’m sorry about that…it’s not really in my habit…but I’m gonna have to RTFM you… :evil:

https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:bloom_and_glow



Here you’ll find all you want to know about glowmap, glow color, how to weak the bloom filter.

haha good one! :stuck_out_tongue:



Seriously though, I’ll give this a read later as I get back to “work”. But, to my defense, the Glow filter I read was what I did. It was based on shaders and … Oh well. I’ll compare what the jME3 docs say and with what I have and fix it accordingly.



As I said, it does work, and I think it does look good, but it’d be preferable to have the underlying textures there too. In a way they looked realistic if you compare to what you would see to the naked eye, but it’s not what I want. :wink:



But that doesn’t matter. I’ll report on my fixing when it’s done.

We can almost wrap this up. Except for the above little things the viewports now seem to be working correctly.



I’ll post a new thread for the Glow/Bloom.