5
\$\begingroup\$

I want to texture the surface of my terrain.

I have created the ground mesh and surface mesh separately and everything is okay for ground mesh. But I couldn't texture the surface mesh correctly.

As below, the first one is what I want exactly and the second one is my output:

Landscapes

And my surface texture image looks like this:

Surface Texture

My fragment shader:

#ifdef GL_ES
#define LOWP lowp
precision mediump float;
#else
#define LOWP
#endif

varying vec2 v_texCoords;
uniform sampler2D u_texture;

void main() {
  gl_FragColor = texture2D(u_texture, v_texCoords);
}

My vertex shader:

attribute vec4 a_position;
attribute vec2 a_texCoord0;
uniform mat4 u_projTrans;
varying vec2 v_texCoords;

void main() {         
 v_texCoords = a_texCoord0;
 gl_Position =  u_projTrans * a_position; 
}    

Here is how I create my textures and draw my meshes:

   private void initializeTextures() {
        groundTexture = new Texture(Gdx.files.internal(Constants.SIMPLE_GROUND_FN));
        groundTexture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);

        surfaceTexture = new Texture(Gdx.files.internal(Constants.SIMPLE_GROUND_SURFACE_FN));
        surfaceTexture.setWrap(Texture.TextureWrap.ClampToEdge, Texture.TextureWrap.Repeat);
        surfaceTexture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
    }

    public void draw(SpriteBatch batch){

        batch.setShader(shader);
        shapeRenderer.setProjectionMatrix(GameScreen.getCamera().combined);
        shader.begin();
        shader.setUniformMatrix("u_projTrans", GameScreen.getCamera().combined);
        groundTexture.bind(0);
        shader.setUniformi("u_texture", 0);
        groundMesh.render(shader, GL20.GL_TRIANGLES);
        surfaceTexture.bind(0);
        shader.setUniformi("u_texture", 0);
        shader.setUniformMatrix("u_projTrans", GameScreen.getCamera().combined);
        surfaceMesh.render(shader, GL20.GL_TRIANGLES);
        shader.end();

    }

And here is the method that generates mesh data:

public void createMeshes(int res) {
    Random r = new Random();
    int LENGTH = 15;
    //res (resolution) is the number of height-points
    //minimum is 2, which will result in a box (under each height-point there is another vertex)
    if (res < 2)
        res = 2;

    groundMesh = new Mesh(Mesh.VertexDataType.VertexArray, true, 2 * res, (2*res-1)*6,
            new VertexAttribute(VertexAttributes.Usage.Position, 2, "a_position"),
            new VertexAttribute(VertexAttributes.Usage.TextureCoordinates, 2, "a_texCoord0"));


    surfaceMesh = new Mesh(Mesh.VertexDataType.VertexArray, true, 2 * res, (2*res-1)*6,
            new VertexAttribute(VertexAttributes.Usage.Position, 2, "a_position"),
            new VertexAttribute(VertexAttributes.Usage.TextureCoordinates, 2, "a_texCoord0"));

    float x = 0f;     //current position to put vertices
    float med = 0.3f; //starting y
    float y = med;

    float slopeWidth = (float) (LENGTH / ((float) (res - 1)))/25; //horizontal distance between 2 heightpoints
    slopeWidth=0.1f;

    // VERTICES
    float[] tempVer = new float[2*2*2*res]; //hold vertices before setting them to the mesh
    float[] tempVerSurface = new float[2*2*2*res]; //hold vertices before setting them to the mesh
    int offset = 0; //offset to put it in tempVer
    int offset2 = 0;
    float[] tempVer2 = new float[2*res];
    int flahUp = 0;
    for (int i = 0; i<res; i++) {

        tempVer[offset+0] = x;      tempVer[offset+1] = 0; // below height
        tempVer[offset+2] = x;      tempVer[offset+3] = 0; // below height

        tempVer[offset+4] = x;      tempVer[offset+5] = y;  // height
        tempVer[offset+6] = x;      tempVer[offset+7] = y;  // height

        tempVerSurface[offset+0] = x;      tempVerSurface[offset+1] = y- .02f; // below height
        tempVerSurface[offset+2] = x;      tempVerSurface[offset+3] = y-0.02f; // below height

        tempVerSurface[offset+4] = x;      tempVerSurface[offset+5] = y+0.015f;  // height
        tempVerSurface[offset+6] = x;      tempVerSurface[offset+7] = y+0.015f;  // height

        //tempVer2[offset2+0] = x;      tempVer2[offset2+1] = 0f; // below height
        tempVer2[offset2+0] = x;      tempVer2[offset2+1] = y; // below height
        //next position:
        x += slopeWidth;
        if(flahUp < 20) {
            y += (r.nextFloat()*10)/200;
        }else {
            y -= (r.nextFloat()*6)/200;
        }
        flahUp++;
        if(flahUp > 35) flahUp = 0;

        offset +=8;
        offset2 +=2;
    }

    groundShape.createChain(tempVer2);
    groundMesh.setVertices(tempVer);
    surfaceMesh.setVertices(tempVerSurface);

    // INDICES
    short[] tempIn = new short[(2*res-1)*6];
    offset = 0;
    for (int i = 0; i<2*res-2; i+=2) {

        tempIn[offset + 0] = (short) (i);       // below height
        tempIn[offset + 1] = (short) (i + 2);   // below next height
        tempIn[offset + 2] = (short) (i + 1);   // height

        tempIn[offset + 3] = (short) (i + 1);   // height
        tempIn[offset + 4] = (short) (i + 2);   // below next height
        tempIn[offset + 5] = (short) (i + 3);   // next height

        offset+=6;
    }

    groundMesh.setIndices(tempIn);
    surfaceMesh.setIndices(tempIn);

    return;
}

So, maybe there is a very different way; this is actually my first game project and I don't know how to achieve this. What should I do to make my surface like the first one?

Thanks.

\$\endgroup\$
  • \$\begingroup\$ Check for OpenGL errors. I´d recommend debugging your program in gDEBugger or CodeXL. \$\endgroup\$ – Andreas May 21 '16 at 12:56
  • \$\begingroup\$ Thanks I will, but in my opinion it is texture positioning/alignment problem rather than OpenGL error and maybe surface mesh rendering needs different vertex/fragment shaders which follows ground curves ( of course i am not sure from that and it is exactly my approximation) \$\endgroup\$ – Jman May 21 '16 at 17:39
  • \$\begingroup\$ It's a bit tough to say for sure, but it sorta looks like a problem w/ the texture coords. Try a multiple gradient texture like this & then screen shot it & check the color values at various places w/ an image editor - that would indicate which edges are getting which texture coords. \$\endgroup\$ – Pikalek May 21 '16 at 20:57
  • \$\begingroup\$ @Pikalek thank you. You are right, with your help and a little investigation about texture wraping, i found solution \$\endgroup\$ – Jman May 22 '16 at 17:38
  • \$\begingroup\$ @Jman glad it helped! \$\endgroup\$ – Pikalek May 23 '16 at 1:07
2
\$\begingroup\$

At least i have found the solution. It includes 2 step :

1- My surface texture wraping was wrong. X axis must be repeated and Y axis must be clamped to edges. The correct one is:

surfaceTexture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.ClampToEdge);

2- When we use "ClampToEdge" wrapping, texture's Y coordinates must be between 0 and 1. So i have changed texture coordinates that i put as parameter to surface mesh. The correct one is:

        tempVerSurface[offset+0] = x;      tempVerSurface[offset+1] = y- .02f; 
        tempVerSurface[offset+2] = x;      tempVerSurface[offset+3] = 1f; // where i have changed

        tempVerSurface[offset+4] = x;      tempVerSurface[offset+5] = y+0.015f;  
        tempVerSurface[offset+6] = x;      tempVerSurface[offset+7] = 0;  // where i have changed.

So at now, my surface texture is exactly as I want.

Thanks.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.