🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

How do I create a terrain editor with OpenGL?

Started by
12 comments, last by Valakor 1 year, 11 months ago

Hello,

I am trying to create a terrain editor for my RTS game I am making with OpenGL 3+.

To generate the terrain, I am using a function called genLandscape() that is called once in the initialization of the application.

EngineModel TerrainEngine::genLandscape(Loader loader, std::string heightMap)

{

GLuint textureID = 0;

int texture_width = 0, texture_height = 0, channels = 0;

here /\ I loaded an image. Is insignificant information…

//allocate texture

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_width, texture_height, 0, GL_RGB, GL_UNSIGNED_BYTE, pData);

int VERTEX_COUNT = texture_height;

//free SOIL image data

int count = VERTEX_COUNT * VERTEX_COUNT;

std::vector<float> vertices(count * 3);

std::vector<float> normals(count * 3);

std::vector<float> textureCoords(count * 2);

std::vector<int> indices(6 * (VERTEX_COUNT - 1)*(VERTEX_COUNT - 1));

int vertexPointer = 0;

heightsLength = VERTEX_COUNT;

heights = new GLfloat*[VERTEX_COUNT];

for (int i = 0; i < VERTEX_COUNT; i++) {

heights[i] = new GLfloat[VERTEX_COUNT];

}

for (int i = 0; i < VERTEX_COUNT; i++) {

for (int j = 0; j < VERTEX_COUNT; j++) {

vertices[vertexPointer * 3] = (float)j / ((float)VERTEX_COUNT - 1) * SIZE;

GLfloat height = getHeight(j, i, pData, texture_height, texture_width, channels);

heights[j][i] = height;

vertices[vertexPointer * 3 + 1] = height;

vertices[vertexPointer * 3 + 2] = (float)i / ((float)VERTEX_COUNT - 1) * SIZE;

normals[vertexPointer * 3] = 0;

normals[vertexPointer * 3 + 1] = 1;

normals[vertexPointer * 3 + 2] = 0;

textureCoords[vertexPointer * 2] = (float)j / ((float)VERTEX_COUNT - 1);

textureCoords[vertexPointer * 2 + 1] = (float)i / ((float)VERTEX_COUNT - 1);

vertexPointer++;

}

}

int pointer = 0;

for (int gz = 0; gz < VERTEX_COUNT - 1; gz++) {

for (int gx = 0; gx < VERTEX_COUNT - 1; gx++) {

int topLeft = (gz*VERTEX_COUNT) + gx;

int topRight = topLeft + 1;

int bottomLeft = ((gz + 1)*VERTEX_COUNT) + gx;

int bottomRight = bottomLeft + 1;

indices[pointer++] = topLeft;

indices[pointer++] = bottomLeft;

indices[pointer++] = topRight;

indices[pointer++] = topRight;

indices[pointer++] = bottomLeft;

indices[pointer++] = bottomRight;

}

}

free(pData);

return loader.postToVAO(vertices, textureCoords, normals, indices);

}

This setup, however, is creating issues for me, as when I want to edit the terrain, the testing process is slowed down because when I try to generate the landscape every frame, it, of course, slows the frame rate because of all the calculations that are being carried out. The same thing happens if I create another heights vector to extract the height data. So my question is how could I make the terrain one that could be changed in, say, a heightmap editor? (that is what I am going for here) What would be the most efficient way of going about such calculations?

Thanks in advance!

-yaboiryan

Advertisement

yaboiryan said:
What would be the most efficient way of going about such calculations?

You could do all on GPU, including the painting.
But i don't think that's needed to have interactive editing. Mostly depends on the resolution of the height map.
Notice you do not need to update triangle indices every frame as they remain constant from height changes.

However, painting realistic landscapes is not artist friendly, and results are usually bad. To improve it, we can use simulation to deal with various erosion effects.
There is a number of tools, e.g. Gaea, which iirc is free to use for sizes up to 1024^2. I'd look at those first, before you invest a lot of time in making one yourself.
A project which helped me on the latter is this, which also demonstrates interactive painting using WebGL.

@JoeJ hahaha I already have seen these applications before. I want to make a terrain editor for my Real Time Strategy game. I am trying to create one so that the player can have as much scenario freedom as they had in, say, Empire Earth.

JoeJ said:
Notice you do not need to update triangle indices every frame as they remain constant from height changes.

Right, so I could just update the vertices every frame? But that would still slow down the framerate.

JoeJ said:
I'd look at those first, before you invest a lot of time in making one yourself.

I have definitely looked into making one myself. Those are, in fact, my inspiration for creating such a tool!

JoeJ said:
But i don't think that's needed to have interactive editing.

What do you mean by that? How wouldn't I need to update it and redraw in every frame? If I didnt change what was being redrawn, then I would run into the same issue I am currently running into! XD

yaboiryan said:
I am trying to create one so that the player can have as much scenario freedom as they had in, say, Empire Earth.

Idk this game. Do you need dynamic terrain, which the players can affect during gameplay? Like Magic Carpet had for example? I guess not?

yaboiryan said:
Right, so I could just update the vertices every frame? But that would still slow down the framerate.

I have ported the WebGL project to single threaded CPU to learn, and it's fast enough:

40 fps for simulating 256^2. With multi threading it would be 8-10 times faster on my 8-core.
Painting is less expensive than simulation, so adding this would be no problem either. Surely good enough for editor needs at sizes like 1024.
Even if GPU implementation is needed, i would develop on CPU first, and only after i'm happy i'd port to GPU. Because developing stuff on GPU just sucks. :D

yaboiryan said:
What do you mean by that? How wouldn't I need to update it and redraw in every frame? If I didnt change what was being redrawn, then I would run into the same issue I am currently running into! XD

Personally i do indeed upload all triangles every frame. There are not even shared vertices. I use a simple debug renderer for my visualizations, which is very slow, yes.
But fast enough for editing tools.

yaboiryan said:
I have definitely looked into making one myself. Those are, in fact, my inspiration for creating such a tool!

I tell you the secret on how to get natural and high quality results from simulations:
If you look at the image above, all those erosion tendrils have about the same width. Looks pretty artificial, because i simulated only one frequency.

To improve this, we need to simulate at multiple frequencies.
Let's say we have some input at 1024. Input can be some noise function, or a manual painting of a hightmap.
The next step is to calculate a mip map pyramid. So we downscale the image to resolutions 512, 256, 128, and 64.
We also store a difference texture between those mip levels. For size 128, that is (image at 128) - (image at 64 but upscaled to 128).
Then start with the smallest image (64) and do erosion simulation, e.g. as shown from the github project.
After some steps of simulation, we upscale the result to 128. And we add the difference texture from before, so we reintroduce the high frequency details we have lost from the downscaling.
Now we simulate at 128, and repeat all the steps until we get back to initial 1024.

This way we have combined simulation results at 5 frequency levels, and results look much better (i just use 3 levels here):

It's also much faster.

Using some better input, i get natural results like this:

That's pretty nice already, and not far off from commercial tools.
Not so much work either. I think it took me 2 weeks maybe.

But that's just the time to have a working proof of concept. To get the results you want, you'll spend a lot of time on tweaking parameters. You'll experiment with new features. You need to work on generating texture as well.
It will be a lot of time, which subtracts from the time you have to work on the actual game.
So it remains a hard decision to decide between using existing tools and making your own.

the testing process is slowed down because when I try to generate the landscape every frame, it, of course, slows the frame rate

Then don't re-generate the terrain every frame. The key is to generate (or load) the base data once, then edit sub-sections. For example, provide various “brushes” to the user that move the heightmap verts around. Track the regions that have changed each frame, then re-upload the new height values for only those regions to the GPU. In some cases this is actually easier to implement on the GPU because there's no need for a separate CPU copy and upload step (though debugging and initial setup is probably harder).

So, in VAO terms, I would need to, @Valakor , get the address where all the verticx data is passed? This terrain is created and set equal to a model file, which manages all the VAO data, and then the glDrawElements function is called.

And both of you had valuable information, but the thing that is stumping me now is being able to find the data location. Do either of you know of how I could get this vertex data? I have the data that is posted to the VAO, but I do not know how to access it so that I can modify it and then resend it.

@JoeJ I dont need the terrain stuff to be able to make my own terrains… I wanted to make an in-game terrain editor. There is no way that I could use commercial software because I would literally have to program commercial software into my game. Because not only am I trying to do a terrain editor, but on top of this, I was going to do a scenario editor as well, where the player could create their own scenarios from a script file type I have created. XD

That sounds ambitious, even for large established teams.

There is nothing inherently wrong with that, but as was pointed out, you are spending a lot of time building editors and player friendly tools rather than spending time on the actual fun game.

It is less of a concern for larger teams where a group of tools developers spend a couple years polishing everything first for in-house use and then later for the game's enthusiasts who want to make maps or mods and can tolerate less polish. But for an individual or small team it is usually a distraction from the real goal.

@frob ah… hm… well then. I guess I will just be trying to make an editor…

@valakor @joej I successfully got one point to rise. I cant control it with the mouse, but I control it with the U and J keys. And it also does not save the height… but I have an idea.

This topic is closed to new replies.

Advertisement