I experience artefacts when rendering to texture with renderManager.renderViewPort(vp), like this:
public void paint(Spatial cloud)
{
// Cloud and misc. parameters
float radius=1000.0f;
Vector3f sunLightDirection=visual.getSunLight().getDirection();
Vector3f viewDir=cloud.getWorldTranslation().negate().normalize();
Vector3f viewUp=sunLightDirection.cross(viewDir).normalize();
// Setup renderer as seen from the sun
// --------------------------------------------------------------------------
int sunCamWidth=256;
int sunCamHeight=256;
// Create framebuffer
sunTex=new Texture2D(sunCamWidth, sunCamHeight, Image.Format.RGBA8);
sunDepthTex=new Texture2D(sunCamWidth, sunCamHeight, Image.Format.Depth);
sunFB=new FrameBuffer(sunCamWidth, sunCamHeight, 1);
sunFB.setColorTexture(sunTex);
sunFB.setDepthTexture(sunDepthTex);
// Create camera
sunCam=new Camera(sunCamWidth, sunCamHeight);
sunCam.setFrustum(VisualSystem.CLIP_NEAR,VisualSystem.CLIP_FAR,-radius,radius,radius,-radius) ;
sunCam.setParallelProjection(true);
sunCam.setLocation(sunLightDirection.mult(-VisualSystem.CLIP_NEAR-radius));
sunCam.lookAt(sunLightDirection, viewUp);
sunCam.update();
// Create view port
sunVP=new ViewPort("CLOUDPAINTER_SUN_VIEWPORT", sunCam);
sunVP.setOutputFrameBuffer(sunFB);
sunVP.attachScene(cloud);
// Render cloud as seen from the sun
// --------------------------------------------------------------------------
cloud.updateGeometricState();
visual.getRenderManager().renderViewPort(sunVP, 0.0f);
}
The spatial is simply a blue sphere. The artefacts look like this:
I assume that this is a GPU related problem, since I it is a NVIDIA GeForce 9400M made in 2009. Has anyone experienced similar problems and/or knows a workaround?
Unfortunately setting the clear flags does not fully resolve the issue. I figured that I have to do the first render-to-texture at frame #2 or after (of the main application) like this:
boolean first=true;
boolean isPainted=false;
public void update(float tpf) {
if (!first && !isPainted) {
paint(cloud);
isPainted=true;
}
first=false;
}
I have had the same issue when precomputing look up tables for the atmospheric scattering shader. Still it is quite annoying. It probably has to do with some initialization that is not complete when the first frame gets rendered, or it is my hardware.
I have this issue too for PBR.
The TestPBRLighting does this exact same workaround , to be able to off render the env map into a cube map.
Rendering it in the simpleInit just doesn not work, and I have to wait for frame 2 in order for it to work.
I didn’t dig too much into it. @Momoko_Fan, any idea?
I’ve put together a simple test case. The interesting thing is that it also works to render in simpleInitApp(), as long as the clear flags are set. So I cannot reproduce the artefacts here (unless you disable the clear flags). For some reason I still get artefacts in my application. Maybe Nehon has more “luck” with reproducing the artefacts, but I think he’s got plenty of other things to do. I will report if I’m still struggling with it, for now I just have to wait for frame #2.
If anybody is interested in the test case, here it is:
import com.jme3.app.*;
import com.jme3.material.*;
import com.jme3.math.*;
import com.jme3.renderer.*;
import com.jme3.scene.*;
import com.jme3.scene.shape.*;
import com.jme3.texture.*;
// =============================================================================
public class ArtefactTestCase extends SimpleApplication
// =============================================================================
{
private FrameBuffer sunFB;
private Camera sunCam;
private ViewPort sunVP;
// Material of the fullscreen quad
private Material qMat;
// =============================================================================
public static void main(String[] args)
// =============================================================================
{ ArtefactTestCase app=new ArtefactTestCase();
app.start();
} // ===========================================================================
// =============================================================================
public void paint()
// =============================================================================
{
// Generate a blue sphere (the cloud)
// --------------------------------------------------------------------------
float radius=1.0f;
Material sMat=new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md");
sMat.setColor("Color", ColorRGBA.Blue);
Sphere sMesh=new Sphere(18, 18, radius);
Geometry sGeom=new Geometry();
sGeom.setMesh(sMesh);
sGeom.setMaterial(sMat);
// Setup renderer as seen from the sun
// --------------------------------------------------------------------------
int sunCamWidth=256;
int sunCamHeight=256;
// Create framebuffer
Texture2D sunTex=new Texture2D(sunCamWidth, sunCamHeight,
Image.Format.RGBA8);
Texture2D sunDepthTex=new Texture2D(sunCamWidth, sunCamHeight,
Image.Format.Depth);
sunFB=new FrameBuffer(sunCamWidth, sunCamHeight, 1);
sunFB.setColorTexture(sunTex);
sunFB.setDepthTexture(sunDepthTex);
// Create camera
sunCam=new Camera(sunCamWidth, sunCamHeight);
sunCam.setFrustum(1.0f, 1.0f+2.0f*radius,-radius,radius,radius,-radius);
sunCam.setParallelProjection(true);
sunCam.setLocation(Vector3f.UNIT_X.mult(-1.0f-radius));
sunCam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Z);
sunCam.update();
// Create view port
sunVP=new ViewPort("CLOUDPAINTER_SUN_VIEWPORT", sunCam);
sunVP.setOutputFrameBuffer(sunFB);
sunVP.setBackgroundColor(ColorRGBA.BlackNoAlpha);
sunVP.setClearFlags(true, true, true);
// Render cloud as seen from the sun
// --------------------------------------------------------------------------
sunVP.attachScene(sGeom);
sGeom.updateGeometricState();
renderManager.renderViewPort(sunVP, 0.0f);
} // paint =====================================================================
// =============================================================================
@Override
public void simpleInitApp()
// =============================================================================
{
paint();
qMat=new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md");
qMat.setTexture("ColorMap", sunFB.getColorBuffer().getTexture());
Geometry qGeom=new Geometry();
qGeom.setMesh(new Quad(settings.getWidth(), settings.getHeight()));
qGeom.setMaterial(qMat);
guiNode.attachChild(qGeom);
} // simpleInitApp =============================================================
// =============================================================================
@Override
public void simpleUpdate(float tpf)
// =============================================================================
{
// paint();
// qMat.setTexture("ColorMap", sunFB.getColorBuffer().getTexture());
} // simpleUpdate ==============================================================
}
When the framebuffer isn’t cleared, the data isn’t initialized to anything so you see those artifacts. I can also reproduce the issue when I disable clearing.
Try running your app with graphics debug and see if there’s anything in the log:
AppSettings settings = new AppSettings(true);
settings.putBoolean("GraphicsDebug", true);
app.setSettings(settings);
I had this issue too for my gui application, and i found that if you do an update in the simpleinitapp the problem disappear. From that i went into the code and copied everything in the update directly into the simpleinitapp, then remove things to keep only the core of the solution.
I don’t have my code here right now (but i can have it tomorrow) but
1 - you can find the solution with the process i described.
2 - i think that the solution was with stateManager.postRender(); (and maybe even inside that).
I thought i did something wrong and it’s why i didn’t communicate about this, sorry.
also sorry for not being able to give you the code right now but i just don’t have it with me and i don’t have a jme environment here.
When the framebuffer isn’t cleared, the data isn’t initialized to anything so you see those artifacts.
That makes sense now. I thought that there would be 0.0 everywhere but that assumption was wrong. Also, I don’t do any update in simpleinitapp like @bubuche, it actually doesn’t matter if you do the update or not (at least not for me).
And it’s a real bug, as color was wrong (rgb turned into bgr, pure green everywhere … ), so wrong that i actually got a perfect gradient green-to-black with a background color like (0,0.001, 0). I will maybe create a test case tomorrow.