Jump to content
  • Advertisement

Project: The Berg

Into The Berg

Greedy Goblin


So here we are.  I'm not a seasoned blogger, or skilled game dev or any such thing.  Social media is, in my opinion, a bit of a pain, so don't be expecting regular daily updates or anything like that.  They'll happen when they happen.

This project (The Berg) is just my idea of fun in my spare time.  I didn't want to use any fancy game engines or integrate a full-blown physics engine.  The idea is to keep it retro, as simple as possible while still creating something that a) looks fairly decent and b) is fun(ish) to play.

I have no idea how this is going to turn out, or if it will ever get completed but we'll all have a good old laugh at my incompetance along the way I'm sure.  😜

Anyway, so I already got part way in to building this thing and thought 'Hey, here's a really dumb idea, why not blog about it for a laugh and waste more of my precious spare time!'.  Awesome!

So what I have so far is a simple Node/ExpressJS/ThreeJS set up in VS Code and I've created the island geometry from a 2D texture passed into a custom vertex shader which takes a flat subdivided plane and applies a displacement to each vertex based on the appropriate UV co-ords.  I want to keep a retro look and feel so this isn't some smooth terrain; it's full of lovely flat shaded triangle-y goodness.

So I created a terrain height map in Gimp (with the help of an online island generator tool for the contour -> http://exupero.org/hazard/post/islands/).


The real size is 2048 x 2048.  I want to create something on the larger scale here!

Once my Node/ThreeJS setup was up and running, I built a Terrain class (this is all in Javascript by the way) and set about loading the texture using the ThreeJS loaders and passing it through to my terrain vertex displacement shader.

P.S.  The terrain shader took me a while to figure out.  Initially it didn't work quite as expected but eventually I got there.  Essentially I pass the player position to the shader and only sample a smaller portion of the heighmap depending on what view distance I want.  So I'm only ever rendering a small sub-section of the heightmap which changes as the player moves.  This was easier said than done... in my head at least.

In the end it looks something like this...

	float step = viewSize / subdivisions;
	vec2 pp = vec2(playerPos.x, -playerPos.z);
	vec2 adjPlayerPos = floor(pp / step) * step;
	vec2 remainderPP = pp - adjPlayerPos;

	float uvScale = viewSize / mapSize;
	vec2 uvOffset = vec2(adjPlayerPos + (mapSize / 2.) - (viewSize / 2.)) / mapSize;
	vec2 newUV = uvOffset + uv * uvScale;

	vec4 dm = texture2D(heightMap, newUV);
	vec3 newPos = vec3( position.x - remainderPP.x, position.y - remainderPP.y, dm.r * heightScale );
	vec3 transformed = newPos;

Sheesh!  That looks... err... complicated, but it gives a great result....





Recommended Comments

I'm very interested in what you've done and how you managed to do it.  In the project I'm working on I'm creating a spherical world.  But I was thinking that perhaps I could do something similar to what you've done.  However instead of using a height map I could use RGB values to represent x,y,z coordinates for vertices for the shader code.  Do you think that is doable?

Another question, how would you go about layering different geometries that use different shaders?  I guess you did just that in your water blog post.

Can I have your code? :D 

Share this comment

Link to comment

Hey Awoken and thanks for the interest in 'The Berg'!

I've never tried this technique with a spherical world but I guess it's pretty much the same principle except you would need a curved plane or sphere rather than a flat plane.  Mapping UVs to that becomes a little more complicated I would guess.

I'm not sure how you could use a texture to represent the x,y,z coordinates for vertices to be honest as I would imagine you would need to sample every pixel of the texture on every pass.  Shaders don't like big for-loops!  (In fact if memory serves me correctly there used to be an explicit limit to the number of loops you could do on a single pass.  I wouldn't know if that's still the case).

For my water I simply use another plane mesh with a different shader.  Nothing complicated.

And lastly... can you have my code?  Sure!  Once I'm a bit further in and got something half-playable it will be on the internet for all to see... code and all!  (I can't guarantee it will be nice clean code but hey, you get what you pay for)  :D

Edited by Greedy Goblin

Share this comment

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!