2
\$\begingroup\$

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: enter image description here

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.

\$\endgroup\$
1
  • 3
    \$\begingroup\$ Not sure about the corruption, but 90% time in SwapBuffers likely just means you're GPU-limited (SwapBuffers waits for the GPU to be done with previous frames, among other things). You can use timer queries to profile individual rendering passes on the GPU. \$\endgroup\$ Commented Nov 16, 2013 at 2:58

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.