Background Gradient

Hello,



is there a possibility to directly write openGL commands in a PreViewPort so that I can use openGL to draw a background gradient before drawing the scene?



Thanks.



Regards,

Equi

What openGL commands? Generally no, but you can use a shader to draw the background.

It’s not as simple as it sounds, you would have 2 ways :

use a skybox with a gradient texture (use sphere mapping not cube mapping)

or

create a quad place it far away, use the lighting material with vertex color on it to make your gradient and put the quad it the sky bucket.

Create a camNode for the camera, and attach the quad to it.



I didn’t test any of these methods, that’s pure guess, but try to experiment with that.

Hello,



I can remember in JME 2 it was quite easy. There was a part of the render pipe which could be overwritten. You could use the gl openGL commands using the gl wrapper methods of the native openGL commands. Its strange that something like this does not exist in JME 3.



Thanks.



Regards,

Equi

I honestly don’t know what was done in JME2, but that sounds very error prone.

I doubt something like that will be implemented in JME3.



What is this gl command you are talking about, is there really something to make a gradient background?

JME 2 snippet



[java]

private class BackgroundRenderPass extends RenderPass {



@Override

public void doRender(Renderer renderer) {

GL11.glDisable(GL11.GL_DEPTH_TEST);

GL11.glMatrixMode(GL11.GL_PROJECTION);

GL11.glLoadIdentity();





GL11.glMatrixMode(GL11.GL_MODELVIEW);

GL11.glLoadIdentity();



GL11.glBegin(GL11.GL_QUADS);



float[] rgba = getFirstColor().getColorArray();

GL11.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);

GL11.glVertex2f(-1.0f, 1.0f);

GL11.glVertex2f(-1.0f, -1.0f);



rgba = getSecondColor().getColorArray();

GL11.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);

GL11.glVertex2f(1.0f, -1.0f);

GL11.glVertex2f(1.0f, 1.0f);

GL11.glEnd();

GL11.glEnable(GL11.GL_DEPTH_TEST);

}

}

[/java]



Regards,

Equi

This will screw up jME2’s render context state. You’re assuming depth test was enabled, you’re overriding the opengl matrices, and you’re changing the color.

You will have the same issue in jME3 since it also uses a render context state.

Hello,



don’t understand me wrong. The code above is only a snippet. It could be that there were other code parts which totally correct saved all matrices etc. to restore them after painting the background. I only want to know HOW I can do something like this in JME3. Do I have to add asomething to the viewport, are there also such GL11 methods available etc…



Thanks.



Regards,

Equi

You could make your own SceneProcessor.

What I don’t understand though, is why can’t you just use normal jME3 methods to achieve this. It’s just a simple background

Hello,



i do not want to have a plain one color background but a color gradient background. I do not know how to achieve this with JME3. In JME2 it was rather easy beacause I could use the glXXXX commands.



Thanks.



Regards,

Equi

Create an ortho space quad, set it to use the VertexColor material, set the colors on it, then render it, clear depth after that

Hello,



what exactly is an ortho space quad? I have created a geometry, attached a quad mesh to it and a VertexColorMaterial. I set the colors to the quad mesh. I can add this geometry to my scene graph and it is displayed. In the TestOrth.java file you put the Picture to the GUI bucket. I want to have the background gradient behind everything so I assumed to add it to the Sky bucket. This does not work. Where do I have to put my geometry so that it is always displayed behind everything else and rendered orthogonal to the camera direction?



Thanks.



Regards,

Equi

Ok, I am currently trying following approach.



I created a new “Pre” ViewPort called “backgroundViewPort” and a backgroundCamera. The ClearEnabled flag of the backgroundViewPort is set to false. A backgroundNode is attached to the backgroundViewPort. I add my geometry to the backgroundNode. I do not see anything.



[java]

private void initBackgroundViewPort() {

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

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

backgroundCamera.setLocation(new Vector3f(0f, 0f, 10f));

backgroundCamera.lookAt(new Vector3f(0f, 0f, 0f), Vector3f.UNIT_Y);

backgroundCamera.setParallelProjection(true);



backgroundViewPort = renderManager.createPreView(“Background ViewPort”, backgroundCamera);

backgroundViewPort.setClearEnabled(false);



//DO I NEED THIS?

//backgroundNode.setQueueBucket(Bucket.Gui);

//backgroundNode.setCullHint(CullHint.Never);



backgroundViewPort.attachScene(backgroundNode);

}

[/java]





The backgroundNode is of course updetd within my Application update method…

[java]

…

backgroundNode.updateLogicalState(tpf);

rootNode.updateLogicalState(tpf);

guiNode.updateLogicalState(tpf);



backgroundNode.updateGeometricState();

rootNode.updateGeometricState();

guiNode.updateGeometricState();

…

[/java]



I also do not completely understand what is the difference between a ViewPort created with createPreView method a normal viewPort and a ViewPort created with createPostView method. Wouldn’t it be easier to render the viewPorts which are contained within a list (e.g. ArrayList). The viewPort first in the list is rendered first, the next on top of it etc…



Thanks.



Regards,

Equi

I am having the same problem with a background viewport. I set the background to clear all, and the main viewport to clear depth and stencil buffers only.



The result is that the screen background is not cleared each frame, and the background scene is not rendered. It seems that the PreView is not working at all, though I can’t seem to find why.



[java]

private ViewPort backgroundViewPort;

protected Node backgroundNode = new Node(“Background Node”);



private void initBackgroundViewPort()

{

// Set the main viewport to not clear colour buffer

viewPort.setClearEnabled(true);

viewPort.setClearFlags(false, true, true);



// Create the background 2d viewport

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

backgroundViewPort = renderManager.createPreView(“Background Default”, backgroundCam);

backgroundViewPort.setClearEnabled(true);

// backgroundViewPort.setBackgroundColor(ColorRGBA.Black);

// backgroundViewPort.setClearFlags(true, true, true);



// These are all true as expected:

System.out.println("backgroundViewPort.isClearEnabled() = " + backgroundViewPort.isClearEnabled());

System.out.println("backgroundViewPort.isClearColor() = " + backgroundViewPort.isClearColor());

System.out.println("backgroundViewPort.isClearDepth() = " + backgroundViewPort.isClearDepth());

System.out.println("backgroundViewPort.isClearStencil() = " + backgroundViewPort.isClearStencil());



backgroundNode.setQueueBucket(RenderQueue.Bucket.Gui);

backgroundNode.setCullHint(Spatial.CullHint.Never);

backgroundViewPort.attachScene(backgroundNode);

}

[/java]



When I create it as a MainView instead of a PreView, it renders its contents as expected (though obviously in front of my real main view).



Any thoughts?



-davidc

A preview is not rendered to screen but to a texture or to memory, use the normal ViewPort and add a scene.

Hm are you sure? The RenderManager.render() method seems to render all PreView, MainView and PostView ViewPorts in the same way, in that order.



Assuming you’re right though, I guess I would need to remove Application’s default ViewPort and create a replacement, in order to get mine behind it (my background viewport is 2D behind a 3D scene)?



David

No actually I am not, but the preView ports I created until now never showed up when I didn’t add a target texture… The main views are rendered “equal” so I guess it wouldn’t solve your problem as the objects would overlap normally.

I removed the Application default ViewPort, added my own ViewPort as a MainView, and then added a new default ViewPort as a MainView in front of it…



[java]

// Remove the default MainView

renderManager.removeMainView(“Default”);

viewPort.detachScene(rootNode);



// Create the background 2d viewport

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

backgroundViewPort = renderManager.createMainView(“Background Default”, backgroundCam);

backgroundViewPort.setClearEnabled(true);

backgroundViewPort.setBackgroundColor(ColorRGBA.Black);



backgroundNode.setQueueBucket(RenderQueue.Bucket.Gui);

backgroundNode.setCullHint(Spatial.CullHint.Never);

backgroundViewPort.attachScene(backgroundNode);



// Recreate the default MainView

viewPort = renderManager.createMainView(“Default”, cam);

viewPort.setClearEnabled(true);

viewPort.setClearFlags(false, true, true);

viewPort.attachScene(rootNode);

[/java]



… and I have the same problem as before, with the screen background not being cleared and the background ViewPort not being rendered. So I think I may be doing something more fundamentally wrong?







-davidc

The problem appears to be that I have a FilterPostProcessor SceneProcessor on my main ViewPort, which causes mainViewPort.getOutputFrameBuffer() to be not null. Will have to track down a solution for this.



-davidc

I have created the following test case. It creates a background PreView viewport behind the main viewport. The main viewport is then set to not clear the colour buffer.



As it stands, it works fine. But if you uncomment the four lines at the end of simpleInit(), which adds a FilterPostProcessor to the main viewport, the background is no longer cleared and the PreView viewPort is no longer rendered.



Any suggestions on how to fix this? Or another way to achieve my goal (which is to have 2d images in the background behind my 3d main scene, but still have the ability to have filter effects?)



[java]

package net.davidc.egp.wiseup.tests;



import com.jme3.app.SimpleApplication;

import com.jme3.font.BitmapFont;

import com.jme3.font.BitmapText;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.post.FilterPostProcessor;

import com.jme3.post.filters.RadialBlurFilter;

import com.jme3.renderer.Camera;

import com.jme3.renderer.ViewPort;

import com.jme3.renderer.queue.RenderQueue;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.Spatial;

import com.jme3.scene.shape.Quad;



/**

  • @author David Croft (david@davidc.net)
  • @version $Id$

    */

    public class TestFilterPostProcessor extends SimpleApplication

    {

    private Node backgroundNode;



    @Override

    public void simpleInitApp()

    {

    // Set the main viewport to not clear colour buffer

    viewPort.setClearEnabled(true);

    viewPort.setClearFlags(false, true, true);



    // Create the background 2d viewport as a PreView, behind our main viewport

    int w = settings.getWidth();

    int h = settings.getHeight();

    Camera backgroundCam = new Camera(w, h);

    ViewPort backgroundViewPort = renderManager.createPreView("Background Default", backgroundCam);

    backgroundViewPort.setClearEnabled(true);

    backgroundViewPort.setBackgroundColor(ColorRGBA.Black);



    // Create the background root note

    backgroundNode = new Node("Background Node");

    backgroundNode.setQueueBucket(RenderQueue.Bucket.Gui);

    backgroundNode.setCullHint(Spatial.CullHint.Never);

    backgroundViewPort.attachScene(backgroundNode);



    // load font

    BitmapFont font = assetManager.loadFont("res/fonts/demo.fnt");



    // Draw a red quad in the 2d background viewport

    Geometry bgQuad = new Geometry("bgQuad", new Quad(100, 100));

    Material bgMaterial = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");

    bgMaterial.setColor("Color", ColorRGBA.Red);

    bgQuad.setMaterial(bgMaterial);

    bgQuad.setLocalTranslation(100, 300, 0);

    backgroundNode.attachChild(bgQuad);



    // Draw a blue quad in the 3d main viewport

    Geometry fgQuad = new Geometry("fgQuad", new Quad(5, 5));

    Material fgMaterial = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");

    fgMaterial.setColor("Color", ColorRGBA.Blue);

    fgQuad.setMaterial(fgMaterial);

    fgQuad.setLocalTranslation(1, 1, -20);

    rootNode.attachChild(fgQuad);



    // Add a blur filter to the main viewport.

    // When this is added, the background viewport no longer renders or even clears.

    // FilterPostProcessor fpp = new FilterPostProcessor(assetManager);

    // viewPort.addProcessor(fpp);

    // RadialBlurFilter blur = new RadialBlurFilter(2, 2);

    // fpp.addFilter(blur);

    }



    @Override

    public void simpleUpdate(float tpf)

    {

    backgroundNode.updateLogicalState(tpf);

    backgroundNode.updateGeometricState();

    }



    public static void main(String[] args)

    {

    TestFilterPostProcessor app = new TestFilterPostProcessor();

    app.setShowSettings(false);

    app.start();

    }

    }

    [/java]
1 Like