Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 1 of 1

Thread: Loading and Rendering Terrain

  1. #1
    Junior Member Newbie
    Join Date
    Aug 2013
    Posts
    12

    Loading and Rendering Terrain

    I'm currently trying to render a terrain by loading one stored in a heightmap. I'm creating a class for loading and displaying it, but I'm having trouble displaying it (I assume that it's being loaded correctly, but can't be 100% sure until I get it displayed properly). I'm trying to find a way to display it using a VBO and triangle strips but can't seem to get it working just right. The terrain looks awful. Images of the terrain along with the heightmap can be found at: http://www.mediafire.com/?svmipbmw75lelra .

    My code for loading and displaying the terrain looks like this:
    Code :
    void Terrain::Load(wchar_t* Image)
    {
        WritetoLog("Loading terrain from heightmap...");
     
        Texture HeightMap;
        HeightMap.LoadTexture(Image);
     
        Width = HeightMap.Get_ImgWidth();
        Depth = HeightMap.Get_ImgHeight();
     
        Heights = new float*[Width];
        for ( int i = 0; i < Width; i++ )
            Heights[i] = new float[Depth];
     
        for ( int x = 0; x < Width; x++ )
            for ( int z = 0; z < Depth; z++ )
            {
                GLubyte Color = HeightMap.GetPixel(x, z)[0];
                Heights[x][z] = (Color/255.f - .5f) * TERRAIN_MAX_HEIGHT * 2;
            }
     
        vec3 Normals[Width][Depth], SmoothNormals[Width][Depth];
        for ( int x = 0; x < Width; x++ )
            for ( int z = 0; z < Depth; z++ )
            {
                Normals[x][z] = vec3(0);
     
                vec3 Front, Behind, Right, Left;
                if ( z > 0 )
                    Front = vec3( 0, Heights[x][z] - Heights[x][z+1], -1 );
                if ( z < Depth - 1 )
                    Behind = vec3( 0, Heights[x][z] - Heights[x][z-1], 1 );
                if ( x > 0 )
                    Left = vec3( 1, Heights[x][z] - Heights[x-1][z], 0 );
                if ( x < Width - 1 )
                    Right = vec3( -1, Heights[x][z] - Heights[x+1][z], 0 );
     
                if ( x > 0 and z > 0 )
                    Normals[x][z] += normalize( cross(Front, Left) );
                if ( x > 0 and z < Depth - 1 )
                    Normals[x][z] += normalize( cross(Behind, Left) );
                if ( x < Width - 1 and z > 0 )
                    Normals[x][z] += normalize( cross(Front, Right) );
                if ( x < Width - 1 and z < Depth - 1 )
                    Normals[x][z] += normalize( cross(Behind, Right) );
                Normals[x][z] = Normals[x][z];
            }
        const float NeighborWeight = .75;
        for ( int x = 0; x < Width; x++ )
            for ( int z = 0; z < Depth; z++ )
            {
                SmoothNormals[x][z] = Normals[x][z];
                if ( x > 0 )
                    SmoothNormals[x][z] += Normals[x-1][z] * NeighborWeight;
                if ( z > 0 )
                    SmoothNormals[x][z] += Normals[x][z-1] * NeighborWeight;
                if ( z < Depth - 1 )
                    SmoothNormals[x][z] += Normals[x][z+1] * NeighborWeight;
                if ( x < Width - 1 )
                    SmoothNormals[x][z] += Normals[x+1][z] * NeighborWeight;
                SmoothNormals[x][z] = normalize(SmoothNormals[x][z]);
            }
     
        vector<vec3> Verts;
        vector<vec3> Norms;
        vector<vec4> Cols;
        vector<unsigned short> Indicies;
     
        for ( int x = 0; x < Width; x++ )
            for ( int z = 0; z < Depth; z++ )
            {
                Verts.push_back( vec3( x - Width/2.f, Heights[x][z] - TERRAIN_MAX_HEIGHT/2.f, -z + Depth/2.f ) ); ///Automatically translate terrain to be centered at (0,0,0)
                Norms.push_back( SmoothNormals[x][z] );
                if ( Verts.back().y >= TERRAIN_MAX_HEIGHT/2.f * .75 )
                    Cols.push_back( vec4( 242/255.f, 242/255.f, 242/255.f, 1 ) ); /// Simple snow capped mountain effect
                else
                    Cols.push_back( vec4( 49/255.f, 150/255.f, 36/255.f, 1 ) );
            }
        for ( int x = 0; x < Width - 1; x++ )
            for ( int z = 0; z < Depth; z++ )
            {
                Indicies.push_back( z + x*Depth );
                Indicies.push_back( z + (x+1)*Depth );
            }
     
        glGenBuffers( 4, IDs );
     
        glBindBuffer( GL_ARRAY_BUFFER, IDs[0] );
        glBufferData( GL_ARRAY_BUFFER, Verts.size() * sizeof(vec3), &Verts[0], GL_STATIC_DRAW );
     
        glBindBuffer( GL_ARRAY_BUFFER, IDs[1] );
        glBufferData( GL_ARRAY_BUFFER, Cols.size() * sizeof(vec4), &Cols[0], GL_STATIC_DRAW );
     
        glBindBuffer( GL_ARRAY_BUFFER, IDs[2] );
        glBufferData( GL_ARRAY_BUFFER, Norms.size() * sizeof(vec3), &Norms[0], GL_STATIC_DRAW );
     
        glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, IDs[3] );
        glBufferData( GL_ELEMENT_ARRAY_BUFFER, Indicies.size() * sizeof(unsigned short), &Indicies[0], GL_STATIC_DRAW );
     
        NumIndicies = Indicies.size();
     
        WritetoLog("Terrain Loaded Successfully");
    }
     
    void Terrain::Draw(int Attributes[4])
    {
        int InitialFlags = BasicProgram.Get_Flags();
        BasicProgram.SetFlags( USING_POINT_LIGHT | USING_SPOT_LIGHT | USING_VERTEX_COLOR | USING_NORMALIZED_NORMALS );
        BasicProgram.UpdateFlags();
     
        glEnableVertexAttribArray( Attributes[0] );
        glBindBuffer(GL_ARRAY_BUFFER, IDs[0]);
        glVertexAttribPointer(Attributes[0], 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
     
        glEnableVertexAttribArray( Attributes[1] );
        glBindBuffer(GL_ARRAY_BUFFER, IDs[1]);
        glVertexAttribPointer( Attributes[1], 4, GL_FLOAT, GL_FALSE, 0, (void*)0 );
     
        glEnableVertexAttribArray( Attributes[3] );
        glBindBuffer(GL_ARRAY_BUFFER, IDs[2]);
        glVertexAttribPointer( Attributes[3], 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
     
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IDs[3]);
        glDrawElements(GL_TRIANGLE_STRIP, NumIndicies, GL_UNSIGNED_SHORT, (void*)0 );
     
        for ( int i = 0; i < 4; i++ )
            glDisableVertexAttribArray( Attributes[i] );
     
        BasicProgram.SetFlags(InitialFlags);
    }

    Do I just need to average my normals or is there more I need to do?

    Edit:
    I fixed everything myself
    Last edited by Niven07; 09-29-2013 at 06:15 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •