Sunland Villagers (was: Learning OpenGL/LWJGL)

The real start of the thread is a bit below. Since it was moved to the WIP section (thanks!), I thought I should add some info and a recent screenshot to the first post.

The idea is a to create a village building and managing game, which loosely resembles the old “Settlers II” game. I don’t want to implement the combat part, but have a more peaceful settlement simulation.

At the moment it’s little more though than a LWJGL based landscape rendering engine, and some basic actions to place buildings and create paths.

It’s open source, and the project site is hosted on Sourceforge:

I try to keep things as simple as possible.

---- original start of the thread ----

This is my third attempt to learn OpenGL. Long ago I had been trying OpenGL and C, but the drivers were so buggy then, that it wasn’t fun. Microsoft supllied drivers had different bugs from vendor supplied drivers, and it just was not nice to work with. Maybe that try to too early …

Year later I tried JOGL, and the reuslt were quite pleasing. I didn’t pursue that further though …

Inspired by this thread http://www.java-gaming.org/topics/jogl-vs-lwjgl-and-the-best-way-to-start-learning/27543/msg/249455/view.html#msg249455 I now make my third attempt, this time with LWJGL. LWGL specific documentation seems to be a bit strange, overly complicated at times, buggy at other times, seldom exactly what I would need. But there is enough OpenGL documentation around to make up for that, at least in regard to the OpenGL functions themselves.

Results of half a day of trial-and-error: A little landscape renderer, using triangles.

Maybe this can become the base for few more modern toy projects, OpenGL is now available on many platforms and the drivers seem to be much better than 10 years ago. At least I can move on from purely 2D development now, and OpenGL seems to be good for 2D graphics, too.

Next to learn: Calculate smoothed vertex normals and enable lighting. Or at fake lighting, I don’t know yet what will be the better approach.

me + math = </3

Calculating the normals turned out to be quite horrible. Actually not because of the vector math, but the way the map is stored in memory and it’s not straight-forward to tell 3D coordinated from the map (2D array) indices. Took a lot of trial and error again, but now I think I have the basics in place:

Now, how can I make the display brighter? I’m not quite sure how to control the light yet.

Using this at the moment:


        glEnable(GL_DEPTH_TEST);
        glEnable(GL_LIGHTING);
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_LIGHT0);
        
        FloatBuffer lightPos = BufferUtils.createFloatBuffer(4);
        lightPos.put(-100.0f).put(50.0f).put(100f).put(0f).position(0);
        glLight(GL_LIGHT0, GL_POSITION, lightPos);
        
        FloatBuffer ambient = BufferUtils.createFloatBuffer(4);
        ambient.put(0f).put(0f).put(0f).put(1.0f).position(0);
        glLight(GL_LIGHT0, GL_AMBIENT, ambient);

        FloatBuffer diffuse = BufferUtils.createFloatBuffer(4);
        diffuse.put(1.0f).put(1.0f).put(1.0f).put(1.0f).position(0);
        glLight(GL_LIGHT0, GL_DIFFUSE, diffuse);

        FloatBuffer specular = BufferUtils.createFloatBuffer(4);
        specular.put(1.0f).put(1.0f).put(1.0f).put(1.0f).position(0);
        glLight(GL_LIGHT0, GL_SPECULAR, specular);

Also, how to control the contrast, the difference between the darkest and lightest texture display?

Edit: its seems I can do this:


        FloatBuffer diffuse = BufferUtils.createFloatBuffer(4);
        diffuse.put(2.0f).put(2.0f).put(2.0f).put(2.0f).position(0);
        glLight(GL_LIGHT0, GL_DIFFUSE, diffuse);

but is this right, to put numbers > 1.0 in there?

[quote=“Varkas,post:1,topic:40136”]
Could you elaborate?

GL_DIFFUSE determines how much of the incoming light is scattered (multiples light color).
GL_AMBIENT adds an omni-directional light source (increases the pixel values)

[quote=“Riven,post:3,topic:40136”]

It’s a bit difficult, since I have surely checked 30 or so differnet tutorials and documentation sites since I started working on this.

Overly complicated - this one I can remember fairly clearly. I wanted to know how to put a texture onto a triangle. This tuturial (The Quad Textured)

http://lwjgl.org/wiki/index.php?title=The_Quad_textured

includes that, but it also comes with a lot of openGL calls that are not needed or aren’t specific to just creating textures, and make it very difficult to extract the part that one needs for textuzres and stripü off the rest. Actually I missed one line in stripping (something about Mipmaps) and it caused my textures not to show, while I was searching the mistake in different places till I found another tutorial and while copmparing I noticed the mipmap setting line, removed it, and it worked … a more focused tutorial would have been easier.

The buggy one I forgot the source. But I Tried the perlin noise code from your blog, and found it (a) doesn’t compile, and when I fixed that, (b) smooth_noise() produces 0.0. for each coordinate that I’ve tried.

Maybe I misunderstood the class. I have ported my old Perlin noise code from C++ to Java, and it worked, so I could continue, but I had expected that the published code was tested before being published (-> would compile at least). Well A comment tells that, but I didn’t check all comments when getting the code.

The rest blurred away in my memory from reading too many openGL documentation recently. Ah right, LWJGL API documentation leaves many parameters undocumented which is uncomfortable - even that I can google the functions, in my IDE it doesn’t show much, although there was a Java Doc supplied with LWJGL, just it’s quite void for many (?) methods.

Edit:

Also took me a while to fi9nd out about this:

FloatBuffer buf = BufferUtils.createFloatBuffer(4);

I used this initially, and it complained about “not direct” which was quite meaningless to me as a pointer what is wrong:

FloatBuffer buf = FloatBuffer.allocate(4);

This is what a Java coder uses if he doesn’t know that LWJGL has it’s own, special buffers implementaion. Again, I lost time and had to do research why LWJGL wouldn’t like my buffer.

I guess this means it’s safe to use values larger than 1.0. The functions I’ve understood, I just don’t know which value ranges are good/sane/allowed/common. I’m almost completely new to OpenGL, and have no experienc with it.

Edit:

Next step: add billboard trees. I remember there were tricks to circumvent blurry texture borders for partly transparent textures, but it seems I’ve lost the code from my lat OpenGL test with JOGL, and besides a faint memory that there existed a trick, I have nothing anymore … I’ll see how long it takes to add the trees.

It doesn’t use its own special buffers implementation; there is simply a library-wide requirement that all buffers passed to native methods are direct bytebuffers as opposed to array-backed ones. Blame “Java the platform” for even having the distinction…

Normally you would use


FloatBuffer buf = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();

but that LWJGL util method just does it for you.

Cas :slight_smile:

Will do. I’d too lazy/busy to research this buffer thing any further :stuck_out_tongue:

Icanhastreesnow!

Now I have everything in place to make a new Settlers II clone ;D

Widelands is there, but it’s C++, and I don’t want to cde C++ anymore. But I have too many projects started already …

At least I now have a OpenGL landscape renderer that does everything that I need :smiley:

And it’s still quite fast, despite my horrid coding, and it surely can be optimized, so this has potential. Thanks for pointing me to LWJGL, it’s been a good start :slight_smile:

Edit: Just noticed that I forgot to rotate the tree sprites towards the viewer. But it’s not much of a problem.

  1. Switched to orthographic projection like the old settler games used.
  2. Got panning and zooming in place now (map dragged by mouse - I think it was done this way in Settler II as well)

Display is fast enough for sure, even for large maps with a lot of objects. OpenGL really pays off here :slight_smile:

Edit: I found out how to use LWGL to render to a canvas in a AWT Frame. Using other AWT components as part of the canvas worked well.

Can I overwrite the canvas paint method to draw something over the OpenGl output?

I assume I can use Swing components in an AWT panel, but I haven’t tested that and it’s been too long ago that I used AWT, I just remember that mixing causes problems. But it seems I can build some game UI around the OpenGL display area.

No, once LWJGL takes control of the Canvas, you can’t draw to it using the Graphics object.

I also noticed you’re using old fixed function OpenGL. I suggest you learn about the programmable pipeline.
The Arcsynthesis tutorial is an excellent resource, and here are the LWJGL ports.

I don’t want to stop you while you’re having your fun making this game, though ;D

The drawing isn’t a big problem, I can either port a UI system that I have from C++ to Java and make it use the openGL primitives, or just write something new. Also it might be sufficient to have the controls below/aside of the world view, that might be good enough. But thanks for the explanation, no I don’t need to try it by myself.

When I started to learn openGL for the first time, OpenGL 1.1 was the only standard that was commonly available in drivers. So I didn’t look at the extensions and newer version, even at that time.

When coming back, I mad the essumption that OpenGL 1.1 will be available on all devices, and since I knew it will be good enough for my needs, I didn’t look beyond that standard. I didn’t even look into display lists yet, becuase performance of the immediate mode was good enough and I had enough CPU left on the one used core, so I didn’t bother about learning anything more.

But in the book I saw this:

[quote]The only exception to this deals with OpenGL 3.0 and above, relative to previous versions. v3.0 deprecated a number of older functions, and v3.1 removed most of those functions from the API
[/quote]
This actually worries me. I don’t know yet which of the old API functions were dropped, but it means that OpenGL 1.1 might not be so universally available as I had thought, and that I need to learn how to do things with OpenGL 3.1 instead. This will take time again. Particulalry it seems to make use of concepts which I considered voodoo (vertex shaders and everything newer - I’m a late adopter and very hesitant with new concepts), and which I wanted to avoid. But it seems that what I considered “voodoo” is now the standard way to do things and I must learn it :confused:

Well, thanks for the link, it will help to avoid mistakes. The book is easy to read and a good source of information. I don’t know if/when I actually will have time and the guts to dive into learning again, but at least I now have a good source of information.

Thanks for the link again, ra4king :slight_smile:

Meh, don’t listen to ra4king about all that 3.0+ stuff. The old-style APIs are here to stay for a number of years at the very least. Most Macs are still stuck on 2.1. Even with drivers that support 3.1 and above LWJGL can use the “compatibility context” path which gives you the old-style APIs anyway. So: use the fixed function pipeline.

Cas :slight_smile:

My Mac can’t do anything over 2.1, besides, the old stuff can do everything the new stuff can, so uh, here’s the deal, why change? I will keep this opinion until I can get a better Mac somehow.

Cheers! :smiley:

I assume that I’ll learn more about OpenGL while working on this project. But it’s good to know that for the moment I can stick with OpenGl 1.1/1.3. Thanks for the feedback!

Levelling ground was a feature and restriction in the settlers games, because bigger buildings required more level space. So I wrote some testing code to see if levelling is as easy as expected and it seems to be. Just setting the height values for the vertices and recalculating the normals does it.

I’ve added a few small houses as example, which need a level triangle as ground to be built.

The houses don’t blend in perfectly yet. Also I think the ground perspective and the sprite perspective don’t match 100% yet, but the code basically works.

What’s up with those grassy and sandy triangles? Are you going to change this? :X

They somehow look… bad… I think this would be something very important to “fix” before going on with game features…

What are you trying to accomplish with them?

Other than that: Very good :slight_smile:

Hehe, actually I didn’t think much when made the map structure. I just wanted to have two textures to see if the map display works. I also found them useful for tracking the triangle positions and later the tree positions. That’s a bit hard without a pattern on the landscape.

Later I’ll have some real landscape textures, but I haven’t made up up my mind yet how exactly they will have to look. I assume most of the land will be grassy, with some rocky places and water areas in between. I’ll need to experiment a bit with layered textures/polygons to make it look interesting.

Thanks :slight_smile:

Well at least 2.1 be minimum for good ol’ shaders! ;D

Why would you limit yourself to the old-style API?

Having the understanding of GLSL will give you a much richer toolset to play with. Personally I did not find myself advancing very quickly with OpenGL until I sat down and forced myself to learn the programmable pipeline. It was only after wrapping my head around shaders did the fixed-function pipeline all come together and make sense to me.

I’m on a Mac with GL 2.1 and I have no trouble playing with fragment and geometry shaders, float textures, texture arrays, etc.

I would be very interested if you supplied some source code. :smiley:

GL2.1 is still the old-style API. It’s only 3.1 (?) and beyond that totally do away with all the old style API commands and you have to ask for a compatibility context instead.
I’m targeting 2.1 these days, but still using all my old code; I’ve just added a couple of shaders.

Cas :slight_smile: