I am using a framebuffer to procedurally create heightmaps with perlin noise in GLSL shaders. There are two main problems that I am experiencing with this. I have a quadtree for the terrain and in the update loop of the program I update this tree. When a quad is split I have to create 4 new heightmaps. When I do this though the heightmaps are severely corrupted. I am not sure why. I even wait one frame before sending the heightmaps to the graphics card to be sampled for the quad. Here is an image displaying the corruption:
Notice how the green quad has a successfully rendered heightmap. The green quad is pQ4 as shown below. It's heightmap is rendered after all the other ones. Here is the code that I use for this:
for(int i = 0; i<QuadN.list.size(); i++){
QuadN q = QuadN.list.get(i);
Vector3f center = QuadN.getCenter(q);
float width = q.width;
float distance = center.distance(cam.getLocation());
float view = (1.5f * width);
if(view >= distance && !q.children && q.width > (8) && q.queuePosition == -1){ //this splits the quad, generating 4 new quads
q.queuePosition = i;
QuadN.split(q,q.index1,q.index2);
QuadN pQ1 = q.childs.get(0);
QuadN pQ2 = q.childs.get(1);
QuadN pQ3 = q.childs.get(2);
QuadN pQ4 = q.childs.get(3);
float scale = pQ1.width/size;
//these textures store the heightmaps
Texture2D hm1 = getHeightMap(itexSize, new Vector2f(pQ1.index1 * (scale * ftexSize), pQ1.index2 * (scale * ftexSize)), scale, pQ1);
Texture2D hm2 = getHeightMap(itexSize, new Vector2f(pQ2.index1 * (scale * ftexSize), pQ2.index2 * (scale * ftexSize)), scale, pQ2);
Texture2D hm3 = getHeightMap(itexSize, new Vector2f(pQ3.index1 * (scale * ftexSize), pQ3.index2 * (scale * ftexSize)), scale, pQ3);
Texture2D hm4 = getHeightMap(itexSize, new Vector2f(pQ4.index1 * (scale * ftexSize), pQ4.index2 * (scale * ftexSize)), scale, pQ4);
//each quad object has a heightmap
pQ1.Heightmap = hm1;
pQ2.Heightmap = hm2;
pQ3.Heightmap = hm3;
pQ4.Heightmap = hm4;
}else if ( i == q.queuePosition){
//this forces the quad that was split above to be examined the next frame
//vp.clearScenes(); clear the viewport so that that heightmaps are not repeatedly re-rendered as this causes extreme performance problems
vp.clearScenes();
QuadN q1 = q.childs.get(0);
QuadN q2 = q.childs.get(1);
QuadN q3 = q.childs.get(2);
QuadN q4 = q.childs.get(3);
q1.mesh.setMaterial(makeMaterial(path));
q1.mesh.getMaterial().setVector3("Color", new Vector3f(1,1,1));
q1.mesh.getMaterial().setFloat("size", q1.width);
q1.mesh.getMaterial().setTexture("HeightMap", q1.Heightmap);
q1.mesh.getMaterial().setVector2("Offset", q1.heightmapOffset);
q2.mesh.setMaterial(makeMaterial(path));
q2.mesh.getMaterial().setVector3("Color", new Vector3f(1, 0,0));
q2.mesh.getMaterial().setFloat("size", q2.width);
q2.mesh.getMaterial().setTexture("HeightMap", q2.Heightmap);
q2.mesh.getMaterial().setVector2("Offset", q2.heightmapOffset);
q3.mesh.setMaterial(makeMaterial(path));
q3.mesh.getMaterial().setVector3("Color", new Vector3f(0f, 0,1f));
q3.mesh.getMaterial().setFloat("size", q3.width);
q3.mesh.getMaterial().setTexture("HeightMap", q3.Heightmap);
q3.mesh.getMaterial().setVector2("Offset", q3.heightmapOffset);
q4.mesh.setMaterial(makeMaterial(path));
q4.mesh.getMaterial().setVector3("Color", new Vector3f(0,1f,0));
q4.mesh.getMaterial().setFloat("size", q4.width);
q4.mesh.getMaterial().setTexture("HeightMap", q4.Heightmap);
q4.mesh.getMaterial().setVector2("Offset", q4.heightmapOffset);
rootNode.attachChild(q1.mesh);
rootNode.attachChild(q2.mesh);
rootNode.attachChild(q3.mesh);
rootNode.attachChild(q4.mesh);
rootNode.detachChild(q.mesh);
q.queuePosition = -1;
}
Here is also the method getHeightMap(); for reference's sake:
public Texture2D getHeightMap(float TEXTURE_SIZE, Vector2f index, float scale, QuadN currQuad){
float scaledTexSize = scale * TEXTURE_SIZE;
Vector2f offset = new Vector2f(currQuad.index1 * scaledTexSize , currQuad.index2 * scaledTexSize);
Texture2D hm = new Texture2D(itexSize,itexSize,Format.RGBA32F);
Quad q = new Quad(2,2);
mat = new Material(assetManager, "material.j3md");
mat.setVector2("Offset", offset);
mat.setFloat("Size", TEXTURE_SIZE);
mat.setFloat("Scale", scale);
mat.setFloat("H", H);
mat.setFloat("Amp", amp);
mat.setFloat("Off", Off);
mat.setFloat("Gain", gain);
mat.setFloat("lac", lacunarity);
ge = new Geometry("Mesh",q);
ge.setMaterial(mat);
mat.setTexture("permSampler2d", permutationTex);
mat.setTexture("permGradSampler", gradTex);
FrameBuffer fbo = new FrameBuffer(itexSize,itexSize,1);
fbo.setColorTexture(hm);
vp.setOutputFrameBuffer(fbo);
vp.attachScene(ge);
if(vp.isEnabled()){
ge.updateGeometricState();
}
currQuad.centerOff = 0;
return hm;
}
The second problem I am having pertains to performance. Clearing the viewport as seen above eliminates the single-digit framerate I was seeing before yet now when many quads are being split the framerates plummet. I profiled the program and found that the process "SwapBuffers" is taking over 90% of the time processing time. Is there anyway to alleviate this?
EDIT: I solved the aforementioned corruption problem by creating a separate viewport and framebuffer for each heightmap.
If any further explanation or code is needed please say so. Thank you for the time, I am completely stuck with this so any help at all is appreciated.