Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Game Development
  4. Best way to create multi-textured terrain
Forum Updated to NodeBB v4.3 + New Features

Best way to create multi-textured terrain

Scheduled Pinned Locked Moved Game Development
8 Posts 1 Posters 5.0k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • E Offline
    E Offline
    eggsmatter
    wrote on last edited by
    #1

    Hi,

    I have a heightmap that I've generated and have implemented to render a terrain. So far, I can only apply one texture to it. My question is, what is the best way to assign varying textures and render them? I will want to blend textures as well but that can come later. I just need to learn how to render more than one. Searching online certainly has a lot of examples but many are either outdated or conflicting. Most render in immediate mode without shaders. GLSL is something I'm trying to comprehend as well.

    The following code has been adapted from the "Qt OpenGL tutorial.":http://qt-project.org/wiki/Developer-Guides#28810c65dd0f273a567b83a48839d275

    In glwidget.cpp::initializeGL()
    @
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);

    const float bgColor[4] = {.7, .8, 1.0, 1.0};
    glClearColor(bgColor[0], bgColor[1], bgColor[2], bgColor[3]);
    
    camera = world->initCamera();
    
    shaderProgram.addShaderFromSourceFile(QGLShader::Vertex, ":/vertexShader.vsh");
    shaderProgram.addShaderFromSourceFile(QGLShader::Fragment, ":/fragmentShader.fsh");
    
    shaderProgram.link();
    
    texture0 = bindTexture(QPixmap(":/textures/grassb512.bmp"));
    

    @

    And the rendering occurs in glwidget.cpp::paintGL()
    @
    vMatrix.rotate(180.0f, 0.0f, 0.0f, 1.0f);
    vMatrix.rotate(yRot, 0.0f, 1.0f, 0.0f);
    vMatrix.translate(camera);

    shaderProgram.bind();
    
    shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix);
    shaderProgram.setUniformValue("texture", 0);
    
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture0);
    glActiveTexture(0);
    
    shaderProgram.setAttributeArray("vertex", world->vertices.constData());
    shaderProgram.enableAttributeArray("vertex");
    
    shaderProgram.setAttributeArray("textureCoordinate", world->textures.constData());
    shaderProgram.enableAttributeArray("textureCoordinate");
    
    QString log = shaderProgram.log();
    if (!log.isEmpty()) {
        qDebug("%s", qPrintable(log));
    }
    
    glDrawArrays(GL_TRIANGLES, 0, world->vertices.size());
    
    shaderProgram.disableAttributeArray("vertex");
    shaderProgram.disableAttributeArray("textureCoordinate");
    shaderProgram.release();
    

    @

    As you may be able to tell, I have a class "world" which exposes an array of vertices as well as an array of textures to the rendering method (I also have an array of normals etc.)
    It would be nice to bind the textures in the world class but I don't see how they'd be exposed to the rendering method. The only solution that comes to mind is to have the world class generate vertex and texture arrays per texture and then process them in the paintGL method but, what happens when I start adding objects: trees structures people? What happens when I need to blend two textures across mutliple polygons?

    Is there logic I can perform in the shaders?

    A link to a perinent and up-to-date reference would be great or just some lucid step in the right direction. Thanks!

    I am developing in:
    Qt Creator 2.5.0
    Based on Qt 4.8.2 (64 bit)

    Built on Aug 7 2012 at 11:47:27
    running on Linux Debian Wheezy/experimental.

    The OpenGL specs are mesa which is a little bit behind the current openGL standards.

    1 Reply Last reply
    0
    • E Offline
      E Offline
      eggsmatter
      wrote on last edited by
      #2

      Bump on this . . . anyone?

      1 Reply Last reply
      0
      • E Offline
        E Offline
        eggsmatter
        wrote on last edited by
        #3

        eggsmatter,

        Hey that's a great question! The tutorials provide a solid basis to get you up and running and, of course, they aren't necessarily provided to explain all development details for your specific project.

        So, it looks like you are rendering all (or some) of your scene in you "world" class. I would suggest that in that class, you set flags for the textures you want to render. So foreach world->vertices & world->textures collection, You would want to implement an algorithm in your world class that can break this one-off array into numerous arrays per texture.

        It sounds like you already have the data on hand. It's just a matter of parting it out into seperate collections by texture to render.

        A great object to help you store this data would be the QMap STL Object. Initialize it (in your world class) thusly:

        @
        QMap<QString, QVector<QVector3D> > vertexMap;
        //wherever you created your "vertices" array, instead do:
        . . .
        //sort by your texture flags:
        vertexMap["textureFlag1"] = vertexElement //which you would have just inserted into your vertices array
        @

        Use the QMap iterator to map your vertex arrays in the paintGL method, binding textures and calling the glDrawArrays method accordingly as you have done.

        Make sure you share with the rest of the group your end results so other people with this problem can be spared from your frustrations.

        Good Luck!

        1 Reply Last reply
        0
        • E Offline
          E Offline
          eggsmatter
          wrote on last edited by
          #4

          Thanks eggsmatter!

          I should have thought of that. A dictionary hash is a great way to store the data I need. This will help me conceptualize the data I'm working with and then later I can work through and optimize it. I can even set custom texture flags to map to multiple texture files for blending and multiple textures etc. This fits like a glove. Thanks once again!

          1 Reply Last reply
          0
          • E Offline
            E Offline
            eggsmatter
            wrote on last edited by
            #5

            don't mention it. Glad I could help.

            1 Reply Last reply
            0
            • E Offline
              E Offline
              eggsmatter
              wrote on last edited by
              #6

              Curious what's going on?

              When I attempt the following, my code just hangs - no errors or warnings - and my entire system slows to a complete crawl:

              @
              QString textureKey = worldMap[x][y]->planes[j]->texture;
              if (vertexMap.contains(textureKey)) {
              QMap<QString, QVector<QVector3D> >::const_iterator i = vertexMap.find(textureKey);
              while (i != vertexMap.end() && i.key() == textureKey) {
              //append a value in the vertexMap and then re-insert it:
              QVector<QVector3D> temp = QVector<QVector3D>(i.value());
              temp << worldMap[x][y]->planes[j]->getPlane()[0]
              << worldMap[x][y]->planes[j]->getPlane()[1]
              << worldMap[x][y]->planes[j]->getPlane()[2];
              vertexMap.insert(textureKey, temp);
              }
              }
              @

              1 Reply Last reply
              0
              • E Offline
                E Offline
                eggsmatter
                wrote on last edited by
                #7

                Well, based on your prior programming experience, you should know that you must never insert an object into a collection while you're iterating through it. Look at what's happening. You're inserting a value into the map. The next iteration, you test if you've reached the end of the collection (which you haven't as you've just inserted something into it) and inserting another object into the collection. Your computer is bogging down because it is running out of memory.

                1 Reply Last reply
                0
                • E Offline
                  E Offline
                  eggsmatter
                  wrote on last edited by
                  #8

                  Right, I was under the mistaken assumption that QMultiMap () would insert over the same key. The opposite is true. The documentation was staring me in the face.

                  1 Reply Last reply
                  0

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved