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\$
5
  • \$\begingroup\$ Check for OpenGL errors. I´d recommend debugging your program in gDEBugger or CodeXL. \$\endgroup\$
    – Andreas
    Commented May 21, 2016 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
    Commented May 21, 2016 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
    Commented May 21, 2016 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
    Commented May 22, 2016 at 17:38
  • \$\begingroup\$ @Jman glad it helped! \$\endgroup\$
    – Pikalek
    Commented May 23, 2016 at 1:07

1 Answer 1

3
\$\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\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .