tag:blogger.com,1999:blog-39281125905631229492024-02-19T18:07:39.756+02:00Draco's DragoonWillemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.comBlogger23125tag:blogger.com,1999:blog-3928112590563122949.post-19134397862264628732013-07-29T21:01:00.000+02:002013-07-30T18:39:55.975+02:00Faster Terrain Render<div style="text-align: left" dir="ltr" trbidi="on">In the previous post <a href="http://dracocepheus.blogspot.com/2013/07/the-basics-of-terrain-rendering.html" target="_blank">about the basics of terrain rendering</a> you saw a simple way to render a <a href="http://en.wikipedia.org/wiki/Terrain" target="_blank">terrain</a> in <a href="http://www.opengl.org/" target="_blank">OpenGL</a>.   In this post you’ll see how to improve the performance of the <a href="https://en.wikipedia.org/wiki/Rendering_(computer_graphics)" target="_blank">render</a> procedure.   On my computer, the original procedure measured 590 frames per second; and with the improvements shown here it measured a whopping 1017 frames per second.   That is nearly a 100% improvement. </div> <div style="text-align: left" dir="ltr" trbidi="on"> <br />Let me start by reviewing the original plan: it is shown in Listing 1.  This procedure traverses through all elements, calculates and sends each vertex to OpenGL.  The <a href="http://en.wikipedia.org/wiki/Central_processing_unit" target="_blank">CPU</a> does all the calculation work – and it does this every time the scene is rendered.  To be fair, the procedure is not all bad: it uses very little memory.  </div> <div style="text-align: left" dir="ltr" trbidi="on"> <br />But what exactly is our memory overhead?  A <a href="http://en.wikipedia.org/wiki/Single-precision_floating-point_format" target="_blank">float</a> is 4 bytes.  As shown in the previous post, a <em>50x50</em> <a href="http://en.wikipedia.org/wiki/Heightmap" target="_blank">heightmap</a> produces <em>5 000</em> vertices (during the triangular traverse).  So, if we store each <a href="http://en.wikipedia.org/wiki/Vertex_(computer_graphics)" target="_blank">vertex</a>, we would need less than 6<em>0 </em><a href="https://en.wikipedia.org/wiki/Kilobyte" target="_blank"><em>kb</em></a> (5 000 * 3 * 4) of memory on the <a href="https://en.wikipedia.org/wiki/Graphics_processing_unit" target="_blank">GPU</a>.   As a side effect: once we have the vertices on the GPU memory, we do not have to make the <em>5 000 </em>calls o OpenGL.  And voila, we gain a lot of speed! </div> <div style="text-align: left" dir="ltr" trbidi="on"> <br /><strong>Listing 1:</strong> <br /></div> <div style="text-align: left" dir="ltr" trbidi="on"> <hr /><script src="https://gist.github.com/codespear/1b00d3f768bf6f228cc0.js"></script> <hr /> <div style="text-align: left" dir="ltr" trbidi="on">The first task is to calculate the vertices.  This is done once: before this first render.  The idea is simple: store the calculations to a <a href="http://www.cplusplus.com/reference/vector/vector/" target="_blank">std::vector</a>.  The code is shown in Listing 2.  Note that the space for the vector is allocated on its constructor – because we know how many elements we need.  <br /> <strong>Listing 2:</strong> <div style="text-align: left" dir="ltr" trbidi="on"> <hr /><script src="https://gist.github.com/codespear/d7e16e2a942719571d00.js"></script> <hr /> <div style="text-align: left" dir="ltr" trbidi="on">Now that you have the values in main memory, you need to copy the data to the GPU.  This is done in three steps (see Listing 3).  First use <a href="http://www.opengl.org/wiki/GLAPI/glGenBuffers" target="_blank">glGenBuffers</a> to create a handle to a new buffer.  Then, <a href="http://www.opengl.org/wiki/GLAPI/glBindBuffer" target="_blank">glBindBuffer</a> tells the OpenGL state machine that you want to use this buffer.  And then <a href="http://www.opengl.org/wiki/GLAPI/glBufferData" target="_blank">glBufferData</a> does the real work: it copies the data from the main to the GPU memory.  The last line tells OpenGL that we are not using the buffer anymore.    <br /><strong>Listing 3:</strong> <br /></div> <div style="text-align: left" dir="ltr" trbidi="on"> <hr /></div> <div style="text-align: left" dir="ltr" trbidi="on"><script src="https://gist.github.com/codespear/c3e36558f4fcf315408b.js"></script> <br /></div> <div style="text-align: left" dir="ltr" trbidi="on"> <hr /></div> <div style="text-align: left" dir="ltr" trbidi="on">All that remains for you is to render the scene using the buffer.  This is done in Listing 4.  This procedure must be called inside the game loop for every render.  As before you tell OpenGL you want to use the buffer identified by the previously allocated handle. The calls to <a href="http://www.opengl.org/wiki/GLAPI/glEnableVertexAttribArray" target="_blank">glEnableVertexAttribArray</a> and <a href="http://www.opengl.org/wiki/GLAPI/glVertexAttribPointer" target="_blank">glVertexAttribPointer</a> tells OpenGL what the format is of the data in the buffer:  essentially we store 3 float values per vertex.  Then the call to <a href="http://gldrawarrays/">glDrawArrays</a> uses the data definition and the data in the buffer to render the terrain.  It is called for each column.  You use the heightmap dimensions to calculate <em>prims</em>, the number of vertices per column.  This value is then used to find the offset in the data for the given column. <br /><strong>Listing 4:</strong> <br /></div> <div style="text-align: left" dir="ltr" trbidi="on"> <hr /></div> <div style="text-align: left" dir="ltr" trbidi="on"><script src="https://gist.github.com/codespear/2f2884d7a576edd9d898.js"></script> <br /></div> <div style="text-align: left" dir="ltr" trbidi="on"> <hr /></div> <div style="text-align: left" dir="ltr" trbidi="on">You now know a little bit more about OpenGL buffers.  You get the same picture as before – its just faster.  </div> </div> </div> </div> Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com1tag:blogger.com,1999:blog-3928112590563122949.post-79568705959097436072013-07-13T09:52:00.000+02:002013-07-29T21:06:08.473+02:00The basics of terrain rendering<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXzQYTWmuTcdONZ811UW77oil16nrEG-hGz0pSsF9oShFRSHoVxvfB7dk6BtGRWT79_YxySLTYi-19zOxZuF7TqYyNL1I7lqDonl0RKCXdatISJXH8gLknuv1B7GY7p_IyuQ9ni6nfkyaB/s1600-h/screen%25255B2%25255D.png"><img title="screen" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: right; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="screen" align="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1ZRN_oBOm5GHLBPI3QttXAS2p1gyfWZyu34F-kePT7B1w-GM-xcZv_sfMiI9St5kiXlpNCi-buFf1-x0xQJz1revo3rtA7Ec9QsVlo177dBwnKKthDqzB3ABvUDqGYWk14eIbAhRdBGQy/?imgmax=800" width="244" height="184" /></a>In the previous post called <a href="http://dracocepheus.blogspot.com/2013/07/the-heightmap-from-concept-to-template.html" target="_blank">The heightmap: from concept to template</a>  you saw how to create a C++ <a href="http://www.cplusplus.com/doc/tutorial/templates/" target="_blank">class template</a> for a <a href="http://en.wikipedia.org/wiki/Heightmap" target="_blank">heightmap</a>.  This post is the next step: you’ll gain an understanding of how to use <a href="http://www.opengl.org/" target="_blank">OpenGL</a> to render a <a href="http://en.wikipedia.org/wiki/Terrain" target="_blank">terrain</a> that uses that heightmap.  The screenshot on the right shows what you’ll have if you follow this post carefully.  The screenshot is produced from the heightmap concept and the <a href="http://en.wikipedia.org/wiki/BMP_file_format" target="_blank">BMP file</a> introduced in the previous post.   </p> <p>Broadly speaking, the terrain is rendered in two steps: 1) create the geometry 2) send the geometry to OpenGL.   The first step in technology agnostic and and could be of use even if you do not like OpenGL.    </p> <p>Let’s start with step one. Terrain geometry needs vertices, so you need to use each element in the heightmap <a href="http://en.wikipedia.org/wiki/Matrix_(mathematics)" target="_blank">matrix</a> to create a three-dimensional <a href="http://en.wikipedia.org/wiki/Vertex_(computer_graphics)" target="_blank">vertex</a>.  This is not difficult because a matrix element can be represented as the triple: <strong>{c,r,h}</strong> where <strong>c</strong> is the column, <strong>r</strong> is the row and <strong>h</strong> is the value of the element.  Imagine <strong>h </strong>is zero for all matrix elements, then the terrain is a flat rectangular grid, composed of equality sized squares. If there are <strong>m </strong>columns and <strong>n</strong> rows in the heightmap there are <strong>m * n</strong> vertices, and consequently you’ll have <strong>(m-1) * (n-1)</strong> squares in your terrain.  You can easily see how it works if the heights are not zero imagining that the corners of the squares are ‘pulled up’ based on the value of <strong>h</strong>.  Clearly your imagination with not be sufficient in itself: you need a <a href="http://en.wikipedia.org/wiki/Function_(mathematics)" target="_blank">function</a> that maps each triple <strong>{c,r,h}</strong> to a vertex <strong>{x,y,z}</strong>. I call this function the <em>transformer</em>.  </p> <p>Before you can define the transformer, you need to commit to a meaning for the components of the vertex <strong>{x,y,z}</strong>.  When talking about terrains, I find it useful to think in terms of the <a href="http://en.wikipedia.org/wiki/Cardinal_direction" target="_blank">cardinal directions</a>.   Orientate your terrain so that the top row of squares lies north and the left column of squares is on the west side.  OpenGL does not know the meaning of the cardinal directions, so we need to decide on a <a href="http://en.wikipedia.org/wiki/Cartesian_coordinate_system" target="_blank">Cartesian coordinate system</a> that maps nicely to these directions.  Let <strong>x </strong>increase from east to west, <strong>y </strong>increase from south to north and <strong>z</strong> increase upwards.  Take a moment to consider what this means. You should also decide on an origin for the vertex on the north-west corner: let that be <strong>{0,0,h’}</strong> where <strong>h’</strong> is a mapping from the <strong>h </strong>value of the matrix element at <strong>{0,0}</strong>.</p> <p>The <em>transformer</em> needs to know the size of your terrain.  OpenGL does not define units, but it is a good idea for you to tie meaning to the floating point numbers sent to the rendering engine.  For convenience I always use the rule: <em>one meter = 1.0f</em>.  Let <strong>square_length</strong> be the length of the side of a square.  So, if your terrain stretches 10km west to east and you have 20 squares in a row, then your <strong>square_length</strong><em> </em>is<em> 500.0f</em>.   Using this value, the transformer can calculate two components: <strong>x = r * square_length </strong>and <strong>y = c * square_length * (-1)</strong>.  Notice that the sign for <strong>y</strong> is changed because <strong>r</strong> increases towards the south while the coordinate system’s <strong>y</strong> increases towards the north. </p> <p>The mapping from <strong>h</strong> to <strong>z</strong> should also be uncomplicated.  If you use a <a href="http://en.wikipedia.org/wiki/Byte" target="_blank">byte</a> for <strong>h </strong>the value of <strong>h</strong> ranges from 0 to 255.  One way to use this range is to decide on the maximum and minimum height you want for your terrain. Let’s call those <strong>max_h</strong> and <strong>min_h</strong>. Keep in mind that <strong>min_h</strong> could be negative and that a negative value for <strong>h</strong> could mean <em>below water level</em>.  From these bounds you calculate <strong>height_scale = (max_h – min_h) / 255</strong>,<strong> </strong>and you get the function <strong>z = h * height_scale</strong> which calculates the final component of the vertex.      </p> <p>Listing 1 shows the <a href="http://www.cprogramming.com/tutorial/functors-function-objects-in-c++.html" target="_blank">functor</a> template called <em>terrain::Transformer.  </em>This class implements the component calculations in C++.  The <a href="http://en.wikipedia.org/wiki/Subclass_(computer_science)#Subclasses_and_superclasses" target="_blank">subclass</a> called <em>terrain::TransformerByte </em>can be used for a heightmap with byte elements. It simply provides a convenient constructor that takes the bounds of <strong>h</strong> as arguments.  The basic<em> Byte, Scalar</em> and <em>Vector</em> types used in the listing are defined in GameEx. </p> <p><strong>Listing 1:</strong></p> <hr /><script src="https://gist.github.com/codespear/72791eb56fe602d1beda.js"></script> <hr /> <p>That wraps up step one: you have geometry.  Now we decide how render the geometry.  Let’s create a <a href="http://en.wikipedia.org/wiki/Triangle_strip" target="_blank">triangle strip</a> for each column of squares.  Consider the squares in the west-most column. The vertices on left (west) side of those squares have <strong>c</strong> = 0, and those on the right hand side <strong>c</strong> = 1.  For this column you create the triangle strip by walking the following  <strong>{c,r}</strong> sequence: <strong>{1,0}, {0,0}, {1,1}, {0,1}, {1,2}, {0.2}, {1,3} …. {1,m},{0.m}</strong>.  This traversal through the elements in a heightmap, can be implemented on the <em>terrain::Heightmap</em> class template.  Listing 2 shows the new <em>traverse_triangles</em> method.  This method takes a function as argument.  It calls this function for each triple <strong>{c,r,h}</strong> it visits while walking in the desired sequence column by column.  It emits a sentinel triple <strong>{-1,-1,0}</strong> to indicate the end of a column has been reached.</p> <p><strong>Listing 2:</strong></p> <hr /><script src="https://gist.github.com/codespear/b8ad2214995cb2a7b8db.js"></script> <hr /> <p>Listing 3 combines the geometry and rendering approach in a class template called <em>TerrainObject</em>.  Take a close look at the <em>draw </em>method: it first draws solid triangles and then red lines ‘over’ those triangles.  Notice how <em>traverse_triangles</em> is called in line 19: it uses a <a href="http://www.cprogramming.com/c++11/c++11-lambda-closures.html" target="_blank">C++ lambda function</a>.   </p> <p><strong>Listing 3:</strong></p> <p><script src="https://gist.github.com/codespear/8f976bda229a1d40f229.js"></script></p> <hr /> <p>Listing 4 shows how these concepts are brought together in the GameEx framework.  If you use another game library this part would obviously be vastly different.  The lines in the listing is all that is needed to show the terrain and have a crude camera to explore your creation a bit.</p> <p><strong>Listing 4: </strong></p> <hr /><script src="https://gist.github.com/codespear/09099ffff62d631ba3c3.js"></script> <hr /> <p>This concludes the post. Using the BMP file as as input,  you created a three-dimensional image that has 4900 triangles.  And maybe you leant a bit more of the new C++ language features.</p> <p><u><strong>After thoughts:</strong></u></p> <p>The post called <a href="http://dracocepheus.blogspot.com/2013/07/faster-terrain-render.html" target="_blank">Faster Terrain Render</a> show you how to use buffers to draw this terrain.</p> Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-23912703882261550122013-07-02T19:32:00.000+02:002013-07-14T11:46:27.601+02:00The heightmap: from concept to template<div style="text-align: left" dir="ltr" trbidi="on">If you want to render a terrain, a <a href="http://en.wikipedia.org/wiki/Heightmap" target="_blank">heightmap</a> is a handy tool to have at your disposal.  This post explores one way to create an abstraction of this concept using the <a href="https://en.wikipedia.org/wiki/C%2B%2B11" target="_blank">new C++ standard</a>.     <br /><img style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: right; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" src="http://upload.wikimedia.org/wikipedia/commons/5/57/Heightmap.png" />In its essence, a heightmap is simply a <a href="http://en.wikipedia.org/wiki/Matrix_(mathematics)" target="_blank">matrix</a> of numbers where an element at <strong>{c,r}</strong> indicates the height of the terrain at some location.  It is a handy data structure and is also a compact way to store the details of a terrain.   The image on the right hand side is an example of a heightmap shown as a 2D image (taken from Wikipedia). The height is determined by the value of the white colour: a whiter pixel indicates a higher level for the terrain at that point.  You should be able to imagine where the hills and valleys are by looking at this image long enough. <br />As you can expect, compact storage comes with a cost: less data equals less detail.  The granularity of the terrain is determined by the size of the matrix, and also by the size of the data type used for its elements.  For instance if the elements are stored as a <a href="http://en.wikipedia.org/wiki/Byte" target="_blank">bytes</a> the terrain height ranges from 0 to 255.  The height cannot be 23.5 … there is only 256 levels to choose from.  <br />Getting back to the abstraction: It seems reasonable that a heightmap needs at least three parameters.  These are: (a) the number of columns <strong>m</strong>, (b) the number of rows <strong>n</strong> and (c) the data type of the elements, <strong>elemT</strong>.   We should now be able to implement this abstract concept as a  C++ <a href="http://www.cplusplus.com/doc/tutorial/templates/" target="_blank">class template</a>.  <br />First, we need is to choose a data structure for the matrix data.  We want a structure that is fixed in memory and stores consecutive elements in sequence.  This constraint will make the heightmap very useful for rendering in <a href="http://www.opengl.org/" target="_blank">OpenGL</a>.   The <a href="http://www.cplusplus.com/reference/array/array/" target="_blank">std::array</a> container is well suited for this purpose.  <br />Often we want to address the elements in the array using the <strong>{c,r}</strong> pair as index.  For this reason, I provided an overloaded <em>()</em> <em>operator</em> that can throw <a href="http://www.cplusplus.com/reference/stdexcept/out_of_range/" target="_blank">std::out_of_range</a>. The code for our class template <em>Heightmap, </em>is shown in Listing 1.  <br /><strong>Listing 1:</strong> <br /> <hr /><script src="https://gist.github.com/codespear/5894305.js"></script> <br /> <hr />Fine and well you say, the meaning is clear, but what is the use of it all?  Ok, let’s develop a more concrete concept that actually does do something.  How about loading the heightmap from an image file, and writing it back?  <br />Consider the image shown above.  Using my favourite image editor <a href="http://www.getpaint.net/" target="_blank">paint.net</a>, I converted this image to an 24-bit <a href="http://en.wikipedia.org/wiki/BMP_file_format" target="_blank">BMP file</a> and resized it to be 50 x 50 pixels.  I want a BMP file because this is a file format <a title="Simple Direct Media library" href="http://www.libsdl.org/" target="_blank">SDL</a> handles very nicely; the size is an arbitrary choice.  <br />The fact is, the handy SDL library provides all the heavy lifting we need.  The <a href="http://www.libsdl.org/docs/html/sdlloadbmp.html" target="_blank">SDL_LoadBMP</a> function creates an <a href="http://wiki.libsdl.org/moin.fcg/SDL_Surface" target="_blank">SDL_Surface</a> which contains the pixel data in row order.  The pixel data depends on the pixel format declared in the BMP file.  The 24 bits means the data contains 3 bytes per pixel.  Note that the 3 bytes represents an RGB value where R = G = B. Here 0 is black and 255 is white. Clearly, the R, G and B values are not all needed in the matrix: one byte is enough.  <br />Let’s call our new abstraction <em>HeightmapWithByte</em>: it is a <em>Heightmap</em> with <strong>elemT =</strong> <strong>unsigned char</strong>.   The code for this abstraction is shown in Listing 2.   The read and write members of this new class template allows us to  swap heightmap data from and to a BMP file.  <br /><strong>Listing 2:</strong> <br /> <hr /><script src="https://gist.github.com/codespear/8bead713d96e52ed2adc.js"></script> <br /> <hr />The code for the functions invoked on line 5 and line 11 are shown below in Listing 3.   Both functions assume the the 24-bit per pixel format.  Line 2 refers to a simple wrapper class in <a href="https://github.com/codespear/GameEx" target="_blank">GameEx</a> (a Github repo of mine)  that manages the SDL_Surface.  The <em>pitch</em> of an SDL surface is a notable concept.  It is the number of bytes in a render line. It is the next number after the image width that is divisible by 4.   For example if you have 50 pixels per row, the SDL surface has a <em>pitch</em> is 52.  The consequence is that each row has 2 padding bytes appended in the pixel data of the surface.  So, be extra careful if your fingers itch to unroll that for-loop ;-).         <br /><strong>Listing 3:</strong> <br /> <hr /><script src="https://gist.github.com/codespear/2981cef60434c9eb8b59.js"></script> <br /> <hr /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMAGJSsGshBoeKPqjhQA92yzHLH_FJg29pZoMkdnxYz4Ks9SH_5ITRt7rdhLFd2hAetj9bk0Rq-xY3IC_Wt5ShhRM24L0Xx3Svbx9eY_q2UfUwLw-BsByguCjoQBcbIct1OBal542mLGSw/s1600-h/my_hm%25255B12%25255D.png"><img title="my_hm" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: right; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="my_hm" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiizwmNHuWthNQkmq7nd5AyT5Pzm8yNf3WezQqBWoKnUdWmNK0fQ1DcOvnw4YIfin2hKfyIp0q_8VylzxlKiFajyDJCHEnNnY6_alBaEWNaOknZnycKsUtFxZYfWS_-u_Re9ET5bFsntnfH/?imgmax=800" width="244" height="244" /></a> <br />Let's put it all together is a small example program. The snippet in Listing 4 reads the input bitmap, inverts the heights so that the highs are low and lows are high. Then it writes the heightmap to an output BMP file. The image on the right hand side is an enlargement of the output produced by this snippet.  If you compare with the original you’d notice the pixilation effect brought about by the radical transformation of the original input (described above). <br /><strong>Listing 4:</strong> <br /> <hr /><script src="https://gist.github.com/codespear/d93be260eb49281d928b.js"></script> <br /> <hr />By the way, that <em>for_each</em> call in the snippet is a very handy macro defined in GameEx.  It works very well with all standard containers, including the new <em>std::array</em>.  <br />There you have it: a few lines of C++ to chew on.  Have fun! </div> <div style="text-align: left" dir="ltr" trbidi="on"> </div> <div style="text-align: left" dir="ltr" trbidi="on"><u>After thoughts:</u> </div> <div style="text-align: left" dir="ltr" trbidi="on">There is follow-on post about <a href="http://dracocepheus.blogspot.com/2013/07/the-basics-of-terrain-rendering.html" target="_blank">terrain rendering</a> you can read.</div> Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-23175316372723662432013-06-25T18:23:00.001+02:002013-07-14T12:21:08.081+02:00Screenshot in SDL/OpenGL<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
I am using <a href="http://www.opengl.org/">OpenGL</a> and <a href="http://www.libsdl.org/">SDL</a>, mostly to learn more of OpenGL. At some time it would be nice to take a screenshot. Pleasant was my surprise that this is not difficult to do. The code shown below is all you need. The <code>_width</code> and <code>_height</code> is your screen size in pixels. <br />
<br />
<b>Listing 1:</b> </div>
<div dir="ltr" style="text-align: left;" trbidi="on">
<hr />
<script src="https://gist.github.com/codespear/724344ddba746c593b97.js"></script> <br />
<hr />
There is a small caveat. The 'y' axis is swapped when you move from SDL to OpenGL. So you have to flip the SDL image vertically. The function in the code below does exactly that. <br />
<br />
<b>Listing 2:</b> </div>
<hr />
<script src="https://gist.github.com/codespear/5859474.js"></script> <br />
<hr />
</div>
Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-10292322937246891292012-02-04T13:56:00.000+02:002012-02-04T13:56:43.874+02:00Coding for funIn many news groups and game development forums there are always general questions from newbies that would like to create games. The <i>oldies</i> that frequent these sites give good advice, but the utility of this advice depends the assumption the oldie makes about the experience of the newbie. A newbie may be disheartened by an answer that goes into too much depth, or feel that the advice is too superficial.<br />
<br />
I think the question we newbies should ask ourselves is: Why do I want to create a game? There are many possible reasons. For example, you may want to pursue a career in the gaming industry; impress someone with your technical aptitude; explore your own creative genius; learn a new language; or you may simply want to create games for your own personal enjoyment (a.k.a. fun). <br />
<br />
Whatever it is, be sure <i>you know</i> the particular motivation that drove <i>you</i> to the task of creating a game. And then stay true to yourself in that regard. For example. if you want to join the gaming industry, my advice is to make sure you explore all areas that is of interest to you, then choose a speciality. Focus all your efforts on learning the current state-of-the-art tools and techniques in that speciality. If you don't like it, switch to another area - and so on. I would also argue that you would do well to ignore me and ask advice from someone that has actually tried to make it in the industry. <br />
<br />
For a person like myself that create games only for the fun of it; any advice that does not directly pertain to fun should be taken with a good dose of salt. Now, if we talk about fun - that is a different story. About that we can talk for hours. Soon we might conclude that <i>fun</i> is not objective and it is a very personal thing. But, all is not lost, there is one absolute truth about fun: <i>you are the only judge of your fun</i>. If you say 'that was fun', no one can disagree; and if you say 'that was not fun' no one can disagree that you did not have fun. <br />
<br />
So, if fun is your motivator, I propose that you are the only judge of your game. If the game was fun to create, it was a successful, otherwise it was an utter waste of your time. This proposal presupposes that you have in fact <i>completed</i> a game. Clearly, on the road to <i>completion</i> you may have to spend some time (hopefully not too much) that may not be fun. But take heart; this process is like any other worthwhile human endeavour. The acquiring of fun is usually preceded by the attainment of a reasonable level of skill. The pursuit of the latter is filled with toils and troubles that are overcome only by an adequate level of personal commitment.<br />
<br />
Of course, when your aim is to have fun, your level of commitment is relatively low. You quickly recognise problems that are far beyond your current skill and promptly avoid solving them. This is a fine approach, but it may be problematic. This is mostly because creating a game for fun is not a competitive sport, like tennis for example. You may enjoy playing tennis without ever thinking about becoming a tennis pro. You like to play tennis with other people that are more or less on your skill level; and as they get better, your game may also improve. If your competitors always beat the living crap out of you, tennis won't be much fun..<br />
<br />
Likewise, when you create a game, and you evaluate your product with the product of a professional game studio, creating games won't be much fun. You need a good competitor. Realise that the only competitor you have - and the one you must always strive to beat - is no one else but the previous version of yourself. So it is very advisable to start with Tic-Tac-Toe or some other simple game. This way you create a worthy opponent; an opponent that has drawn a line in the sand, and dares you to cross that line. For your next game, you must focus on giving that opponent a real beating - and then draw a new line in the sand.<br />
<br />
Before asking on a forum which is the best language, the best platform, the best graphics engine for creating games, or the best game idea, first ask yourself what is more fun for you. For me, it is currently more fun to program in C++ than in Java or in C#. It is more fun to use OpenGL than it is to use Direct X. It is more fun for me to use SDL than it is to Orge3D. These are assertions I make because I have explored these (and many other) choices. And I had fun doing it.<br />
<br />
Go ahead, start working towards that vision of a game you always wanted to write. But start by creating a lesser game - a game you know you can write. Take that first step; who knows where to it might lead. It could even be fun!Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-33240545846630987712011-02-16T20:50:00.000+02:002011-02-16T21:19:55.179+02:00BoogalooIt has been some time since I did a bit of game development. Recently, a local game competition inspired me to do another little game. After puddling around a bit, I decided to stop development and to call the game finished [a.k.a. version 1.0].<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqJP-WqNcR2okDmbQ1JTLIfXYYL92XrUWgpt1z2Q6Q8XjbgpxCfKW1p2WMmgb4rKG9_U7LcdGd4Iz4-JmRzP7ludCp_R_QbazYr1OofgvXHbpKCiPqlFGwA4dI-E5oVVVpsNsOQCl1kF-1/s1600/boogaloo_01_00.png"><img style="MARGIN: 0px 0px 10px 10px; WIDTH: 200px; FLOAT: right; HEIGHT: 150px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5574362009241132210" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqJP-WqNcR2okDmbQ1JTLIfXYYL92XrUWgpt1z2Q6Q8XjbgpxCfKW1p2WMmgb4rKG9_U7LcdGd4Iz4-JmRzP7ludCp_R_QbazYr1OofgvXHbpKCiPqlFGwA4dI-E5oVVVpsNsOQCl1kF-1/s200/boogaloo_01_00.png" /></a><br />The game itself is the simple snake-eats-apple game with an interesting twist: you have to control two snakes at the same time. Surprisingly, this small variation to the original idea adds a little bit of puzzle and a lot of fun.<br /><br />I built the game using Scala, Swing and Java2D. I also made use of an indie game library (<a href="http://goldenstudios.or.id/products/GTGE/">GTGE</a>). The game is very simple, so the services I used from the library were minimal. However, I must say I liked the simplicity of the library API and I would gladly use GTGE again.<br /><br />It is the first time I tried the JAVA VM to develop a game. As an experience, it was not as bad as I expected. The deployment package is a single JAR file that you should be able to start playing with a double-click on the jar file (on most modern PC platforms).<br /><br />Why not give it a try -- download the executable jar file <a href="http://www.box.net/shared/j58f0ajxdk">from box.net</a>.<br /><br />If you get more than 600 points, you should really consider quiting that day job ;-).Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-9198419923865709292009-04-18T21:07:00.009+02:002013-06-25T19:42:42.863+02:00BreakOut clone updatedAlthough I am working on one or two other ideas, I figured I should not let my first (and only) completed <span class="blsp-spelling-error" id="SPELLING_ERROR_0">XNA</span> game rust away. So, I picked up ye old shovel and upgraded some code to VS2008 and <span class="blsp-spelling-error" id="SPELLING_ERROR_1">XNA</span> 3.0. The upgrade process was quite painless - apart from an issue I picked up with <span class="blsp-spelling-error" id="SPELLING_ERROR_2">XACT</span>.<br /><br />In fact <span class="blsp-spelling-error" id="SPELLING_ERROR_3">XACT</span> does not seem to be working on my machine at all. Even the <span class="blsp-spelling-error" id="SPELLING_ERROR_4">XACT</span> tool fails to play any media. I googled a bit for an answer, but could not find any good reasons for this behaviour. Luck was on my side: <span class="blsp-spelling-error" id="SPELLING_ERROR_5">XNA</span> 3.0 offers an alternative to <span class="blsp-spelling-error" id="SPELLING_ERROR_6">XACT</span> for audio processing. The game is quite simple, so it was easy to remove <span class="blsp-spelling-error" id="SPELLING_ERROR_7">XACT</span> from the code, and plug in the new pieces.<br /><br />I do not know what advantage <span class="blsp-spelling-error" id="SPELLING_ERROR_8">XACT</span> has for a simple game like this one. <span class="blsp-spelling-error" id="SPELLING_ERROR_9">XACT</span> took a bit of figuring out; while the new method is very straight forward. My crystal ball says most new developers will sidestep <span class="blsp-spelling-error" id="SPELLING_ERROR_10">XACT</span> while they can.<br /><br />Anyways if you are interested in trying out this very basic clone, get the zip from <a href="http://breakit.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=26293">the release on <span class="blsp-spelling-error" id="SPELLING_ERROR_11">codeplex</span></a>. But calm down those high expectations -- I suspect reading the code is more interesting than playing the game :).Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-21598372254824490722009-02-01T08:04:00.015+02:002013-06-25T19:43:48.467+02:00Teaming UpIt is clear that collaboration does not come free. Compared to the work of a solo developer, there is definitely additional effort required to start and maintain a successful collaborative project. Collaboration is driven by the need to be part of something great, something cool, or even something profitable. Even though total satisfaction is not guaranteed, one thing cannot be denied: the team <em>is</em> stronger than the individual.<br />A few days ago, I posed a <a href="http://forums.sagamedev.com/topic.aspx?topicid=553">question at SA game dev</a> to get some thoughts on the team issue. The feedback was very interesting. Here are some of the key points that were highlighted.<br /><strong></strong><br /><strong>A "main dude" is needed for success. </strong><br />* This is the guy with the full picture in his mind. He defines the project, sets it up and invites other to join. He is possibly the key contributor, and he directs and controls the work done by other (possibly part-time) contributors.<br />* If you want to be this dude, your attitude is important. Setup you collaborative site, but assume that you will do all the work yourself. The success of the project hinges not on the contributions of others, but on your ability to see it through.<br /><br /><strong>Your idea must be pragmatic.</strong><br />* The game idea must be clear. You must know how to implement the idea. Think about breaking down the idea into small milestones so that each can be reached relatively quickly.<br />* An alternative is to start with a small idea and finish it with some collaboration. Then come up with a more complex idea that will take the willing participants to the next level. Finish that as well. Gradually gaining collaborative momentum.<br /><br /><strong>Consider the team issues before you start.</strong><br />* Make sure you ideas and plans are communicated clearly. The team will function properly only if they work from the same knowledge base.<br />* Think about how team members will participate. Perhaps a person can choose which discipline he wants to be involved with. Maybe the idea lends itself to episodes or mini-games - giving your team members more autonomy.<br />* Choose tools that promotes collaboration amongst developers and also amongst artists.<br />* Keep in mind that some potential team members are less technical, and they may need custom written tools before they will help you. For instance, an artist might become more interested when he can view his creation in a setting that resembles the game in some way.Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-37614924166170516852009-01-03T11:04:00.036+02:002009-04-18T21:49:11.477+02:00Those jagged edges<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOmfNuhyt3rr_GggeWr76nBHo5g6u6q4BWfMrmJJao9yoZO-F-lDdmha_e9YyciLTPyV4TSY0UOk4x6DYqoCjOENcJ1GNlk7FoZHAUnDH1Gk10c-vmtMdYDmoDDERAyaRm_uZqc1ejiAkV/s1600-h/jaggededges.jpg"><img id="BLOGGER_PHOTO_ID_5287872458708403170" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; WIDTH: 200px; CURSOR: hand; HEIGHT: 200px" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOmfNuhyt3rr_GggeWr76nBHo5g6u6q4BWfMrmJJao9yoZO-F-lDdmha_e9YyciLTPyV4TSY0UOk4x6DYqoCjOENcJ1GNlk7FoZHAUnDH1Gk10c-vmtMdYDmoDDERAyaRm_uZqc1ejiAkV/s320/jaggededges.jpg" border="0" /></a>After patching together the crater (described <a href="http://dracocepheus.blogspot.com/2008/12/geomorphic-landforms.html">previously</a>), I noticed a deformation at the edges of the crater's upturn. Initially, I gave it little thought and blamed it on a side-effect associated with terrains with sharp edges.<br /><br />However, <a href="http://www.sciencedaily.com/releases/2008/12/081224215542.htm">the subconscious mind is apparently very persistent</a>, and a possible fix dawned on me. The four vertexes used to create the two triangles for the terrain do not (in all likelihood) line up to form a plane. The <a href="http://en.wikipedia.org/wiki/Quadrilateral">quadrilateral</a> create by the points <em>A,B,C </em>and <em>D</em> is divided into two triangles using either the diagonal <em>AC</em> or the diagonal <em><span class="blsp-spelling-error" id="SPELLING_ERROR_0">BD</span></em>. In the terrain construction, the same diagonal is always chosen. The picture above illustrates the consequence -- the edges of the crater is very jagged.<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyJfZiBKgwz4LCtRqSphVVUBc4xuUC_2wLDYGd0kpr6BvQbbOd1wOF37botM5XByMo8dOB6pKMMWJfyb7JE5HU_SyAdOXFMGGJPo0YTgMEdXIfreXdLNBF9FZfi5C7e4enfgq535vEuPyn/s1600-h/fixededges.jpg"><img id="BLOGGER_PHOTO_ID_5287887149714178194" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 200px; CURSOR: hand; HEIGHT: 200px" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyJfZiBKgwz4LCtRqSphVVUBc4xuUC_2wLDYGd0kpr6BvQbbOd1wOF37botM5XByMo8dOB6pKMMWJfyb7JE5HU_SyAdOXFMGGJPo0YTgMEdXIfreXdLNBF9FZfi5C7e4enfgq535vEuPyn/s320/fixededges.jpg" border="0" /></a>Instead of a fixed choice, a better result is obtained when the diagonal is chosen with more care. Here is the rule I applied: take the diagonal that is the highest. This means that the quadrilateral will be always be convex (as seen from the outside) -- and some concave aspects of the generated terrain will disappear. In other words the terrain will have less jagged edges. To compute the <em>highest </em>diagonal I take the diagonal that has the largest sum of the <em>Y</em> component of its vertexes. Other methods also seem reasonable: for instance take the diagonal with the highest <em>Y. </em><br /><br />The second picture shows the same view as the first using the <em>largest sum</em> method. Definitely a <span class="blsp-spelling-corrected" id="SPELLING_ERROR_1">noticeable</span> improvement.Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-84916489337533523702009-01-01T08:38:00.017+02:002009-06-13T16:36:00.760+02:00Riemers Components 1.1.0A little bit of functionality has been added since the <a href="http://dracocepheus.blogspot.com/2008/12/xna-terrain-rendering-lesson-5.html">last time I published the code</a>, and time for a version update has arrived.<br /><br />The new stuff in Version 1.1.0 is briefly described in related blog entries:<br /><ol><li>The terrain weights are adjusted not only based on height, <a href="http://dracocepheus.blogspot.com/2008/12/slippery-slopes.html">based also on the normal</a>.</li><li>A new class was added to <a href="http://dracocepheus.blogspot.com/2008/12/terrain-generation.html">generate heightmaps</a> using Perlin Noise.</li><li>The ability to create a <a href="http://dracocepheus.blogspot.com/2008/12/fairly-odd-stitching.html">larger heightmap</a> from a small one through tiling was added.</li><li>Placing <a href="http://dracocepheus.blogspot.com/2008/12/geomorphic-landforms.html">volcanoes and craters</a> on the heightmap is also possible.</li></ol><br />If you would like to use these components in your own game, I suspect the best way is to copy code from my project to your project, and make changes to the classes as you see fit. The components were not created to be generic or to be a reusable library of sorts. It simply presents you with an approach to combine the various aspects of creating a terrain into a reasonable set of classes.<br /><br />The interesting thing about class design is that it is a little bit of an artform. Like other art, not everybody like what they see, but the artist is likely to stay true to himself. Sometimes, the artist might even <a href="http://www.answerbag.com/q_view/20527">cut off his ear</a>.<br /><br />However, class design can also be a little bit of a science form. There is a lot to learn, and I need my ear for that, thank you very much. You may have better ideas on the class composition I did here and I invite you to share your ideas and feedback with me if you get some time.<br /><br />I published the code in a zip file that can be downloaded <a href="http://www.codeplex.com/RoboBattle/Release/ProjectReleases.aspx?ReleaseId=21264">here</a>.Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-48371004512629457482008-12-27T09:10:00.003+02:002009-01-01T10:40:57.629+02:00Geomorphic landformsThe <a href="http://dracocepheus.blogspot.com/2008/12/black-water-debunked-on-better-beaches.html">previous blog entry</a> was about cosmetic changes. This one is about adding landforms to the terrain. The <a href="http://dracocepheus.blogspot.com/2008/12/terrain-generation.html">Perlin terrain </a>works well for generating your basic (perhaps flattish) terrain, but I want to be able to place specific obstacles at specific locations. Not obstacles that are placed on the terrain: but rather obstacles that are part of the terrain.<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLuWTjux5sk88K-jpgx2NS0GSvtQWgUPQtkU50r9nXZCIcUe3DJXLWberTCFqYvY4uD4uwuHMaqkQSjWeZLdLZgxe7iscsIDf78XWNNK3R3aV9JONaWdKIVnApuxlz58LxPYLOd2hCDaQ3/s1600-h/screenshot.jpg"><img id="BLOGGER_PHOTO_ID_5284363558201971090" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 200px; CURSOR: hand; HEIGHT: 200px" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLuWTjux5sk88K-jpgx2NS0GSvtQWgUPQtkU50r9nXZCIcUe3DJXLWberTCFqYvY4uD4uwuHMaqkQSjWeZLdLZgxe7iscsIDf78XWNNK3R3aV9JONaWdKIVnApuxlz58LxPYLOd2hCDaQ3/s320/screenshot.jpg" border="0" /></a>I am thinking about volcanoes and craters. A volcano is a cone shaped mountain with a hole in the middle. The cone surface is made less smooth with randomised adjustments. Although a crater is simply a large hole with an elevated rim at its edge; it gets slightly complicated when you consider that the rim must fit nicely with the original landscape.<br /><br />The implementation starts with a definition for the <code>ILandform</code> interface. Instances of this interface is added to an object that inherits from <code>HeightMap</code> via the <code>Landformations</code> member on this class. Right after the heightmap itself is established each of the landforms in this collection are initialised. The lanform has full access to the heightmap data. The classes <code>LandformVolcano</code> and <code>LandformCrater</code> embodies the volcano and crater functionality. Not really much code there; but some experimentation was needed to get things just right.<br /><br />I must admit, gross shortcuts were taken. There must be more <a href="http://en.wikipedia.org/wiki/Geomorphological">geomorphologically</a> correct ways to build these landforms (and I cannot help but feel my volcano can do with some smoke). Alas, these artifacts are good enough for my current expectation. The image above shows a crater next to a volcano. I am sure you can spot the difference between the crater pool and the Perlin pool.Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-48388699453998614702008-12-26T11:41:00.004+02:002008-12-26T13:20:26.560+02:00Black water debunked on better beachesWhen moving away from the terrain, I noticed that the water turned black. You can see what I mean if you look at the image in the <a href="http://dracocepheus.blogspot.com/2008/12/fairly-odd-stitching.html">previous post</a>. This is a side effect of <a href="http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series4/Skydome.php">Riemers Skydome</a>. In order to minimise the problem a bit, I did two things. The first was to change the background colour to something other than black (made it a blend between white smoke and sky blue). This small change made the problem much less apparent.<br /><br />But, I was not yet convinced, so I took a closer look at the <code>RiemersSkyDome</code> class. In order to determine the place of the dome in the world, a matrix is calculated as follows:<br /><code>wMatrix = Matrix.CreateTranslation(0, -0.30f, 0)<br />* Matrix.CreateScale(100)<br />* Matrix.CreateTranslation(camera.Position);<br /></code><br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRbiceES2DRSsMce8i7FkOV0ilwiuoatwLKJ7XGb8u1py_VlDc2xGqIj0pnkNqZaKJSZrYVw0nh_ABJ_YgrDVJLS0riTXPwf2W41fKCu22z41D3bHBu0RAlqtowEUuGnDMVVcKYyUCBKmn/s1600-h/screenshot.jpg"><img id="BLOGGER_PHOTO_ID_5284026934217532418" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; WIDTH: 250px; CURSOR: hand; HEIGHT: 250px" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRbiceES2DRSsMce8i7FkOV0ilwiuoatwLKJ7XGb8u1py_VlDc2xGqIj0pnkNqZaKJSZrYVw0nh_ABJ_YgrDVJLS0riTXPwf2W41fKCu22z41D3bHBu0RAlqtowEUuGnDMVVcKYyUCBKmn/s320/screenshot.jpg" border="0" /></a>Our needs can be addressed by adjusting the value of the first translation's Y component (-0.30) and the scale value. A higher value of Y component lifts up the dome making the <a href="http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series4/Gradient_skybox.php">gradient effect</a> more visible from the terrain surface. The scale adjusts the distance to the horizon of the dome. A scale factor of 300 produced the desired effect.<br /><br />On a different note, I also refined the island terrain trimmer (the <code>HeightMapIslandTrim</code> class) produced more pleasing terrains. I added two options: the one is a shape and the other is a trim method. The shape is either a <em>circle</em> or a <em>square</em>.<br /><br />The trim method is more interesting: it has two options: a <em>fill</em> option and a <em>merge</em> option. The <em>fill</em> option is the one described in the previous post. It simply fills in ground until the beach is perfect according to specification. The problem with this is that it creates an unnatural edge for the beach; except if that's what you were going for, you may not like it.<br /><br />The <em>merge </em>option is much smarter. It takes the beach line (this is where the water hits the sand) and applies the fill method there. As it moves away from this line, the original form of the heightmap is gradually adopted with more vigor. Again this uses our old friend the <em>lerp</em> function.<br /><br />The image shown here is a terrain built from a mirror of Riemer's original heightmap with the island modifier applied to it. Notice how the merge option created puddles on the beach.Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-19479201475635746882008-12-24T08:00:00.003+02:002008-12-26T06:18:12.194+02:00Fairly odd stitchingIn my <a href="http://dracocepheus.blogspot.com/2008/12/terrain-generation.html">previous blog</a> I explained the need for a fair playground. Developing a fair heightmap from an unfair one is quite easy. The key is to tile the original on a 2 x 2 grid such that the edges are mirrors of one another. This way the resulting playground is not only fair, but the edges where the tiles meet are seamless.<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZMzmGsiGxLvYRbz9yI_DPxHsuJWUocGv9zu0WSmb1YkgVx27rP4U6CiYhcTiPy82MY3AHrEMTBblNC2Adu0Og2G6oxb9EMwLVgM46vCUW4wASLX9f3lG2hPOkZ2gLVH3kH_FeZ6K4JrTj/s1600-h/screenshot.jpg"></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZLw2QOOof_reiysoOiRRXO7QxdTWlW9sUgHfpkTFP66e1DV9kA-n62P6HvwXX4h6rgclLc1SbzHFQg5ZmRryw5RmMbryNAi8SqEylakyJf81raYworru9E-SWS5jOlIgfX_6RyOfMve5H/s1600-h/screenshot.jpg"><img id="BLOGGER_PHOTO_ID_5283050533517029810" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 250px; CURSOR: hand; HEIGHT: 250px" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZLw2QOOof_reiysoOiRRXO7QxdTWlW9sUgHfpkTFP66e1DV9kA-n62P6HvwXX4h6rgclLc1SbzHFQg5ZmRryw5RmMbryNAi8SqEylakyJf81raYworru9E-SWS5jOlIgfX_6RyOfMve5H/s320/screenshot.jpg" border="0" /></a>This idea was implemented in a class called <code>HeightMapMirror</code> that takes an <code>IHeightMap</code> as argument. This class also implements the <span style="font-family:Courier New;">IHeightMap</span><br />interface. This means a mirror can now be created from any other height map on the fly - whether that map is generated or whether it is loaded from an image file.<br /><br />Obviously you can feed the constructor of the new class another instance of a <span style="font-family:Courier New;">HeightMapMirror</span> effectively creating a 4 x 4 tile (who wouldn't give that a try?)<code>. </code>Surprisingly, from an almost featureless patch of a <code>HeightMapPerlin</code> terrain an interesting and attractive fair playground is produced using this plan . The image shown above is produced that way. Notice the repeating pattern of water and hills.<br /><br />The other thing I did today was to create a <code>HeightMapIslandTrim</code> class. Its function is simply to put a coastline on the edge of the heightmap. Like <span style="font-family:Courier New;">HeightMapMirror</span> (the other <em>modifier</em> of heightmaps) this class constructor also takes another map as source.<br /><br />First I tried a circle island and did not like the loss of real estate. I then tried creating a square island and did not like the look of it too much. I'll experiment more with this when creating a terrain in the context of a game.<br /><br />The basic idea of adding a coastline is simple: the height is calculated using a <a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.mathhelper.lerp.aspx">linear interpolation</a> that is based on the distance from the edge of the island. This class can also be (ab)used to create a wall around the terrain by specifying impossible values for <code>waterlevel</code> or <code>shoreheight</code>.<br /><br />This concludes today's blog. Not much added, but at least some progress has been made.Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-24041800089166119002008-12-23T08:00:00.006+02:002008-12-23T22:59:11.806+02:00Perlin's magic on terrain generationAfter building the terrain from a fixed heightmap and <a href="http://dracocepheus.blogspot.com/2008/12/slippery-slopes.html">fixing the slopes</a>, terrain generation seems to be a good next step. There seems to be quite a number of ways to do generate terrain. I think the selection of a method depends primarily on the look you are going for.<br /><br />I decided on three initial characteristics: a) The landscape must be a <em>fair playground, </em>b) it must be <em>reproducible</em>, and c) it must be relatively smooth.<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6eXpk4_TsU30t2OSPLus5tVZgzSvYKM-CtEhMeAuSkSaCLNwKcnEoX9gPCQxampO7Qo_awlTt_t5qPqGOV6uPlqvq4qdTaLrfiGqhJxMuJuFIJ_lQ6Ffm_AtFaEXvkY3hg3WaF8S9mFdk/s1600-h/screenshot.jpg"><img id="BLOGGER_PHOTO_ID_5282858163210848898" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 250px; CURSOR: hand; HEIGHT: 250px" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6eXpk4_TsU30t2OSPLus5tVZgzSvYKM-CtEhMeAuSkSaCLNwKcnEoX9gPCQxampO7Qo_awlTt_t5qPqGOV6uPlqvq4qdTaLrfiGqhJxMuJuFIJ_lQ6Ffm_AtFaEXvkY3hg3WaF8S9mFdk/s320/screenshot.jpg" border="0" /></a>The idea behind a <em>fair playground</em> is to have a two player arena such that the terrain gives no advantage to either player. This means the terrain must be a mirror of sorts. A player in the north looking toward the center will see the same <em>effective terrain</em> as a player looking from the south.<br /><br />The term 'effective terrain' refers to those aspects of the terrain that are not cosmetic. For example: having different vegetation in the north and the south may influence the look dramatically. If it is not used in the game logic the choice of vegetation is not part of the effective terrain. This separation of <em>effective</em> and <em>cosmetic</em> concerns on your drawable objects could be an import design consideration that would simplify many aspects of the game design and implementation.<br /><br />A terrain is <em>reproducible</em> when its form can be recreated from its input. In other words, although I might need a lot of terrains for my game, I would like to be sure that the same terrain is presented for the same scenario. This reproducibility also give me a handle on the generated terrains, and allows me to handpick scenarios by tweaking the input parameters. The idea here is to use <em>predictable random numbers</em>.<br /><br />After some googling I decided to start with Perlin Noise based generator (Perlin was already <a href="http://dracocepheus.blogspot.com/2008/12/xna-terrain-rendering-lesson-5.html">used before</a> to create the animating clouds). It seems that I can get a smooth terrain using this method. For the implementation I used an article on the <a href="http://learn.nerdy-inverse.com/?p=63">Nerdy Inverse Network</a> as a starting point.<br /><br />During my previous blog, I created a class called <code>Terrain</code>, originally copied from <code>RiemersTexturedTerrain</code>. Now, we need to separate the height map from the terrain, and <code>IHeightMap</code> together with the reference implementation <code>HeightMapLoaded</code> emerged.<br /><br />The new class, called <code>HeightMapPerlin</code> addresses expectation (b) and (c) described above. Here is its constructor: <code>public HeightMapPerlin(Game g, int width, int length, float minHeight, float xHeight, int seed, float persistence, int octaves)</code><br /><br />The <code>seed</code> produces the same terrain for any given seed value. The value of <code>persistence</code> influence how <i>pointy</i> the hills are. Low values produce a less pointry terrain. The number of hills are influenced by the value of <code>octaves</code>. More octaves, more hills. The slope is influenced by the value of <code>minHeight</code> and <code>maxHeight</code>. Some experimentation with these values is nessasary to get the right kind of terrain to suit a particular need. The published image shows a rendering with <code>persistence = 2.9f</code> and <code>octaves = 4</code>.<br /><br />I can now generate a terrain with given properties, but the issue of fairness has not been addressed yet.Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-2288604622756400122008-12-18T21:37:00.002+02:002008-12-23T08:15:20.340+02:00Slippery slopesI could not help but see an opportunity to fix the degradation that occurs at the <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiENSo1qCU95wGh2s7pPjLT9sXyefGTnY7vnO7WvtOOw9CM5Vy1JgUK7gK_3mQsTAloFUf9V9zZrqsYCd9jMkkW6-WAGqgQyjuSPbQOCkQovHWii8Z-EsenxT2MTK0rips6yMzAIFFM3E7H/s1600-h/sn_old.jpg"></a>steep slopes in the terrain created in the <a href="http://dracocepheus.blogspot.com/2008/12/xna-terrain-rendering-lesson-5.html">previous blog</a>. <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimI6R6R5jlNERkHx-1zOb33cFYqSo1AGDInRZRi_BZ317K6yTDTC3e-cSpQrLHAqZF5SJuYXA3FxfdbZ-X0XNi193WoA2cfxAgbaCXvDN3_9zcDZ65l-nsNK6Q5EXldHANIW1f-Rhrjkms/s1600-h/sn_old.jpg"><img id="BLOGGER_PHOTO_ID_5281527850838361506" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; WIDTH: 250px; CURSOR: hand; HEIGHT: 250px" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimI6R6R5jlNERkHx-1zOb33cFYqSo1AGDInRZRi_BZ317K6yTDTC3e-cSpQrLHAqZF5SJuYXA3FxfdbZ-X0XNi193WoA2cfxAgbaCXvDN3_9zcDZ65l-nsNK6Q5EXldHANIW1f-Rhrjkms/s320/sn_old.jpg" border="0" /></a>This degradation occurs because the <code>UV</code> coordinates specify a small piece of texture (as seen from the top) must fit on a large piece of real estate (as seen from the side). Aha, I thought, the solution is simple - just fix the coordinates and all should be fine. After doing the work, the flat areas of the terrain become seriously damaged. This is because all the adjustments adds up and the sum causes a distortion of the textures on the flat areas in the terrain. I'm sure there is a simple mathematical explanation for this, but you'd have to ask someone else for it ;-).<br /><br />Little did I know this was a know issue. See <a href="http://www.gamedev.net/community/forums/topic.asp?topic_id=468418">this forum topic</a> for a small discussion and a better description of the problem. So I reverted back to the original <code>UV</code> coordinates. However, I decided to change the multi-texture decision so that the rock texture is preferred when the gradient reaches some threshold. The gradient is easy to measure -- the smaller the Y component of the normal, the steeper is the slope. <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnxxGlWB2K83HPO8lugygzwjXGHzVXLdfCnveSfo6qmTTQjxj2GYHVs49awVVdFtQ1hhfGblYmVZzno4yKXNmNQwY4jFmxbH-UqXqfbJaoaLEzByZvddKK5cQMpu4DbZyir5eFyduN18t6/s1600-h/screenshot.jpg"><img id="BLOGGER_PHOTO_ID_5281528181797900978" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 250px; CURSOR: hand; HEIGHT: 250px" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnxxGlWB2K83HPO8lugygzwjXGHzVXLdfCnveSfo6qmTTQjxj2GYHVs49awVVdFtQ1hhfGblYmVZzno4yKXNmNQwY4jFmxbH-UqXqfbJaoaLEzByZvddKK5cQMpu4DbZyir5eFyduN18t6/s320/screenshot.jpg" border="0" /></a><br /><br />Choosing the rock texture as the one for steep slopes gives you this code: <code><span class="blsp-spelling-error" id="SPELLING_ERROR_0"><span class="blsp-spelling-error" id="SPELLING_ERROR_0">TexWeights</span></span>.Z = 1.0f - _<span class="blsp-spelling-error" id="SPELLING_ERROR_1"><span class="blsp-spelling-error" id="SPELLING_ERROR_1">vertices</span></span>[x + y * _width].Normal.Y;</code>. As you can see from the image on the right, the slopes look a bit more realistic.<br /><br /><p>On another topic -- the download of the code I published from my previous blog did not work well. I republished the code <a href="http://www.codeplex.com/RoboBattle/Release/ProjectReleases.aspx?ReleaseId=20706">here</a>. The available code does not contain the changes mentioned here. Maybe I'll publish again later.</p>Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-17965350806995962932008-12-16T09:04:00.001+02:002009-06-13T16:40:22.426+02:00XNA Terrain Rendering - lesson 5<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWmjKpYkmVmGCqZNNxAsf0fWVLnT2XuT2mJIsziTt-qH1WMZTLO8Zw1Z-eXqjpcBsm5MH1OkvvZOUfqRKVKaxiNJeey2dKZxjTRQAkYkdosNmEZc0SCu23mnzW1TP15DPhBxCItAYa9TDT/s1600-h/screenshot.jpg"><img style="MARGIN: 0px 10px 10px 0px; WIDTH: 320px; FLOAT: left; HEIGHT: 320px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5280357865954382690" border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWmjKpYkmVmGCqZNNxAsf0fWVLnT2XuT2mJIsziTt-qH1WMZTLO8Zw1Z-eXqjpcBsm5MH1OkvvZOUfqRKVKaxiNJeey2dKZxjTRQAkYkdosNmEZc0SCu23mnzW1TP15DPhBxCItAYa9TDT/s320/screenshot.jpg" /></a><br /><div>I am now at <a href="http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series4/Ripples.php">step 10 of Riemers advanced terrain tutorial</a>. Instead of using complex wave mathematics, Riemer uses a bump map. A bump map contains normal vectors in the <code>RGB</code> of each pixel. Using new inputs to the HLSL effect, <code>waveLength</code> and <code>waveHeight</code>, the pixels in the mirror is perturbed with the pixels in the bump map.<br /><br />Step 11 works in the refraction map created earlier into the scene. Based on the angle of camera and the normal, the amount of reflection and refraction is adjusted. This is called a <em>Fresnel</em> term, and is calculated using the dot product of the two vectors. In addition, this step adds a bit of dullness to the output to make the water surface less shiny.<br /><br />The next step makes the water move. Again lots of vector and HLSL tricks. Here a new <code>xTime</code> parameter is added to the parameters. Together with a parameters that shows the wind direction, the chosen coordinates in the bump map changes. I created a component called <code>Environment</code> to keep these aspects. This component updates the parameters in the effect when it draws.<br /><br />In step 12, a specular effect is added to the water. As the light shines on the water the water sparkles when the sun is reflected on the surface. This is done by adding to the intensity of the <code>RGB</code> components on the pixel shader.<br /><br />Trees are added in step 13 using a billboard technique. I created a component called <code>BilboardTrees</code> to make this work. I had to make the vertexes of the terrain a public property for the billboard trees to be placed on the terrain.<br /><br />The next step cleans out some problems with the billboards by drawing non-transparent pixels only. Riemer explains a trick that avoids ordering the trees before drawing them. A downside of billboards becomes clear when the world is viewed from the top.<br /><br />The second last step is about creating perlin noise. Almost the work is done in HLSL. I placed this into a new component called <code>PerlinNoise</code>. This component generates a texture that contains perlin noise. The noise gradually shifts as time passes -- making clouds that change over time. Very cool!<br /><br />The final step is subtle but adds a lot to the realism. Here this sky gradient is changed in HLSL so that the sky on the bottom of the horizon is lighter than the sky on the top.<br /><br />Now, its done, the terrain tutorials are great. I now have a collection of components to use in my own terrain. I published this work on <a href="http://www.gameprojects.com/project/?id=25fec21007">Game Projects</a>.</div><div> </div><div>(<u>Edit:</u> Please note that there has been additional improvements on the published code that might be of interest to you. Read all about it on <a href="http://dracocepheus.blogspot.com/2009/01/riemers-components-110.html">this blog</a> entry).</div>Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-33861841491541697472008-12-14T07:09:00.001+02:002008-12-23T08:10:06.398+02:00XNA Terrain rendering - lesson 4The lesson starts with <a href="http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series4/Multitexturing.php">step 3 of Riemer's advanced terrain tutorial</a>. Here multiple textures are introduced (we now have grass,rock,snow and sand). In order to get a smooth texture transition, each vertex carries a weight for each the four textures. The weight are calculates using fuzzy logic (rockiness, snowiness and so on). The values are normalised to have a total of one. The weights are stored in a <code>Vector4</code> using <code>TEXCOORD3</code> HLSL semantics. Each vector component (X,Y,Z and W) is used to stored the weight of the respective textures. In the pixel shader the output colour is determined by adding up the weighted values from the four texture samplers.<br /><br />Step 4 is about the level of detail (or LOD) problem. Essentially the size of the texture must be bigger (i.e. more detailed) when viewed up close -- and smaller when viewed from a distance. The solution is to get the distance from the camera (i.e. the depth of a pixel). The solution is to get a blend factor (float from zero to one) determined by the depth. When this factor is zero, near texture coordinates are used, when its far, the normal tex coords are used. The near texture coordinates is a magnification of the normal coordinates. Linear interpolation (lerp) chooses the actual magnification level. All this is done in the shader code. Very neat.<br /><br />The next step is about setting up a sky dome. This code was simple to implement as a new component called <code>RiemersSkyDome</code>. The sky dome must be drawn before the terrain, and it also needs access to the <code>RiemersCamera</code> instance. The sky dome itself is a model (.X file), and the effects in the model is imply replaced with a clone of Riemers customer effect. The clone is important because this effect has its own values for the effect parameters.<br /><br />In step 6, Riemer explains the overview of creating water. Essentially, the reflection (from above) is combined with the refraction from below to determine the pixel colour. Then a ripple is added using a <i>Fresnel</i> method. As a final modification, some "dirtiness" is added to get a realistic effect.<br /><br /><a href="http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series4/Refraction_map.php">Step 7</a> starts off with the refraction map. Here again, I created a component called a <code>RefractionMap</code> The basic idea is that the part of the scene that is below the surface of the water is drawn to a <code>Texture2D</code> This is done by setting a clip plane -- only pixels above the clip plane is drawn. The tricky part is to create the place based on the current camera orientation. For the component I created a collection property called <code>RenderedComponents</code>. The user of the component adds all the elements to this collection he wants refracted. For now I only added the terrain to this collection.<br /><br />In step 8, the same technique as above is used to create a reflection map. After creating a base class for <code>RefractionMap</code>, I created another control of the same kind called <code>ReflectionMap</code>. The problem here is to "extract" the reflected image to a texture.<br /><br />In the next step a mirror effect is created. Much of the code comes from the HLSL tutorials. Form a component viewpoint, the normal XNA draw method is not enough for the <code>ReflectionMap</code> to use. For reflection, the draw must be done via from a reflection matrix view; so the interface of components must be extended to contain a <code>void Draw(Matrix viewMatrix)</code>.<br /><br />This concludes the lesson. We have a terrain with perfect mirrored surfaces for water. And some interesting new components.Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-43025304615955552692008-12-13T19:49:00.002+02:002008-12-23T08:11:25.877+02:00XNA Terrain rendering - lesson 3<a href="http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series1/Lighting_basics.php">Riemers tutorial, step 9</a> is all about the basics of lighting. It starts by adding a normal to each surface. Given a normal, a light source and view point, the amount of light reflected by the surface is computed. A new vertex structure called <code>VertexPositionNormalColored</code> is created to keep the normal. The light source is send to Riemers effect. Riemers next step applies these changes to the terrain.<br /><br />In my code, the <code>RiemerTerrain</code> component keeps and calculates the light information is kept on the <code>RiemerCamera</code> component.<br /><br />The final step on Riemer's series is very interesting. It is an optimization. Essentially memory is allocated on the GPU and values are copied to the GPU only once. The call to the graphics primitive is updated to use that memory instead. This means during draw, there is not a lot of communication to the graphics card. A great technique for optimising the rendering of static geometry.<br /><br />Although <a href="http://www.riemers.net/eng/Tutorials/XNA/Csharp/series4.php">Riemers advanced terrain series</a> assumes knowledge of the HLSL series; I will start with it without walking through the HLSL series (I did that one quite a while ago -- and I am now sorry I did not create a blog for it). This means I have to prepare my current code to be aligned with Riemers. This was actually quite easy -- there is a new height map and a new effects file.<br /><br />The <a href="http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series4/Mouse_camera.php">first advanced tutorial step</a> is all about creating a better camera. This was relatively easy -- I created a new component called <code>RiemersFirstPersonCamera</code> by inheriting from the <code>RiemersCamera</code> class created a few days ago. Had to refactor a bit -- and moved the <code>angle</code> relates functionality to a another derivative of <code>RiemersCamera</code> called <code>RiemersRotatingCamera</code>. Quite easily done. Now we have a camera that allows us explore the terrain nicely. The good old WASD with mouse control.<br /><br />The second step uses a texture to draw the terrain. I copied <code>RiemersTerrain</code> to <code>RiemersTexturedTerrain</code> and found a number of small differences. One notable difference was the removal of the indices and vertexes from the private member list of the class. There is no need to keep a copy of this data since it is generated right into the graphics card memory.<br /><br />The idea of the texture is relatively simple. When seen from above, each dot on the map maps to some XY coordinate on the texture.<br /><br />There was one more change that is important from the component perspective. Previously, the camera decided on the current technique of the effect. But now, the current technique is chosen by the terrain component. The primary reason for this change is that the terrain owns the texture, and the texture is a parameter for the technique (albeit implicitly). I am not convinced that this is in fact the best place for technique selection -- maybe I'll change it back later.<br /><br />Again, the end of another lesson; and we have a nice look and feel. That is a little green patch to look at, and an intuitive camera that creates the feel.Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-49390957816893182662008-12-12T19:06:00.001+02:002008-12-23T08:11:50.756+02:00XNA Terrain rendering - lesson 2So far, so good. New we move to <a href="http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series1/World_space.php">step 4 of Riemer's excellent tutorials</a>. During this step, the triangle coordinates are adjusted and the camera is introduced.<br /><br />So, what I did is create a <code>RiemersCamera</code> component that implements the camera. This is a drawable component, and when it draws, it sets up the view and projection of the effect. The important lesson here is that the order in which the components are created is significant. Create the camera first -- it sets up the effect. Components that follow the camera uses this effect. This way there is no reason for the other components to be aware of the camera. Neat!<br /><br />A disadvantage of these two components is that they share an effect. The effect has only one instance, and changes to the effect is propagated from one control to another.<br /><br />To mitigate this situation, I created a base control <code>RiemersEffectComponent</code> that encapsulates the loading of the effect. At least the process coupling is a bit more explicit.<br /><br />Step 5 of Riemer's series is about rotating and translating the world matrix. Easily done on the <code>RiemersCamera</code>. And step 6 is all about introducing <code>DrawUserIndexedPrimitives</code>. For this I created a new component called <code>RiemersIndices</code>, starting with a copy of <code>ReimersTriangle</code>.<br /><br />At last in step 6 we get a glimpse of terrain. Although the final drawing is not much. The idea is the following: the terrain is a number of dots, organised in a equally spaced matrix. Each dot has <code>Y-value</code> that indicates its height. The dots are then connected to draw the terrain. You guessed it -- all this is done in the <code>RiemersTerrain</code> component.<br /><br />Step 7 shows how the simple code in the previous steps becomes much more interesting. The only change is to load the height data from a heightmap. Step 8 gives a bit more interactivity and allows you to control the view via the keyboard.<br /><br />The last two steps raised an issue for my components. The camera controls the view, but the terrain knows its size. So I added a <code>TranslationMatrix</code> as a public property to the <code>RiemerCamera</code>. Then passed the camera to the constructor of <code>RiemersTerrain</code>. After the terrain loads the heightmap, it adjusts the view by specifying the tranlation matrix value.<br /><br />Step 8 adds colour. To determine the water levels, the height of the heightmap is determined and releative water levels are set. There is also a need to clear the Z-Buffer (However, on my machine I did not notice the anomaly that is mentioned in the tutorial).<br /><br />This is a good place to end the lesson. We have moved from triangles to heightmappped wire frame to a basic coloured terrain. Some simple game components are taking form, thanks to Riemer!Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-69532812991741009562008-12-11T21:17:00.002+02:002008-12-23T23:16:46.115+02:00XNA Terrain rendering - lesson 1I am no XNA expert - but I thought it is time to figure out how to render a terrain. I could find no better place to start than <a href="http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series1/Starting_a_project.php">Remiers Tutorials</a>. If your looking for a tut, follow Riemer. This is a blog :-). I am using XNA version 3.0.<br /><br />In the first step, the graphics device is initialised to a 500 x 500 view.<br /><br />In the second step, the effects file is loaded and incorporated into <code>Draw</code>. In the draw method, Riemer uses <code>device.Clear(Color.DarkSlateBlue)</code>. But there is a property on <code>Game</code> called <a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.game.graphicsdevice.aspx"><code>GraphicsDevice</code> </a>that I am using instead. A technique in the effect file called <code>Pretransformed</code> is used -- but nothing is in fact drawn using this technique.<br /><br />In the third step, a triangle is drawn. Now the meaning of <code>Pretransformed</code> becomes clear - it is used as a simple rendering method of the triangle. The technique avoids the need for a camera. The triangle is specified as a set of three vertices and rendered on the draw method.<br /><br />At this point I deviated from Riemer a bit and I created a <code><a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.drawablegamecomponent.aspx">DrawableGameComponent</a></code> called <code>RiemersTriangle</code>. Moving away from the single class approach followed in the tutorial. For the component, the <code>VertextDeclaration</code> cannot be done on <code>Initialise</code>, and I had to add an override for <code>LoadContent</code> and put it there. The <code>GraphicsDevice</code> is not available during <code>Initialise</code> Add the component to the <code>Game.Components</code> on <code>Initialise</code> before <code>base.Initialise</code> is called.<br /><br />Anyhow, that concludes lesson 1 -- we have a pre-transformed triangle to show for our effortWillemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-202401408096031362007-06-30T09:08:00.001+02:002008-12-23T08:12:21.929+02:00Even if it's not broken, try break it anywayMy second project, <span style="FONT-WEIGHT: bold">Beak-it</span> has been complete for some time now, but I decided to publish it only a few days ago. You can find it on <a href="http://www.gameprojects.com/project/?id=9a1a9735c4">Game Projects</a>, a very nice independent project release site.<br /><br />Break-it is a breakout clone with all the basic elements: a bouncing ball, bricks and a paddle that has a few tricks. I kept the features to the bare minimum, but the sound effects and graphics provides a good playing experience.<br /><br />This game was coded in C#, using <a href="http://creators.xna.com/">XNA</a>. A big downside of XNA is that you need the .NET framework 2.0 and the Microsoft XNA runtime on your machine. The upside is that XNA provides a well designed game framework for developers to work in; especially for 2D game development (I have not delved into the 3D aspects). I recommend XNA for anyone that wants to learn how to write games.<br /><br />I also used <a href="https://opensvn.csie.org/">OpenSVN</a> as a code repository. It allows you to manage your code without committing to specific licensing constraints.<br /><br />After some amount of introspection I decided to do my next project in C++ and Ogre. The reasons revolve around my unwillingness to drop the C++ language, the possibility of having XNA runtime distribution issues and the availability of (yet unexplored) game libraries and utilities for C++ developers.Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-62652570664736697102006-12-18T20:05:00.003+02:002008-12-23T08:13:00.805+02:00Whatever you do, don't drop it!<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgb6i2uYG9gIeNsrOZYNUUgpE-tQ42vIGOgoj3IcF6rLo8346icR8AZNgL6W4HCQYeIj4IH4N2GLFVlcEgohNQVduSISZ4WVtOhE8kvVbNvMrVL5XOQCQoDqye6iQFSfDd9-Z6roTXQ6G3k/s1600-h/screen.png"><img id="BLOGGER_PHOTO_ID_5009951576936277298" style="FLOAT: right; MARGIN: 0pt 0pt 10px 10px; CURSOR: pointer" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgb6i2uYG9gIeNsrOZYNUUgpE-tQ42vIGOgoj3IcF6rLo8346icR8AZNgL6W4HCQYeIj4IH4N2GLFVlcEgohNQVduSISZ4WVtOhE8kvVbNvMrVL5XOQCQoDqye6iQFSfDd9-Z6roTXQ6G3k/s320/screen.png" border="0" /></a><br />My creation is done. As you can see it looks just like Tetris. What did you expect? Legally, I could not use the term "tris" in the name, and I choose to call this version <span style="COLOR: rgb(102,0,204)">DropIt</span>. This name is also a clue -- you get serious bonus points for dropping the tetromino. If you have not played Tetris for a while, <a href="http://www.t-3s.net/wiki/DracoCepheus">here is your chance</a>.<br /><br />Quite a large download for such an insignificant, but yet surprisingly brilliant ;-) game. That's what you get when you develop a light weight game to learn more about heavy weight libraries.<br /><br />Sadly, if you do not have Visual Studio installed on your PC, you will also need to download <a href="http://www.microsoft.com/downloads/details.aspx?familyid=32BC1BEE-A3F9-4C13-9C99-220B62A191EE&displaylang=en">vc_redist.exe</a>. Not having this Microsoft distributable installed on your system causes a very ugly error indeed. I tried to include this as part of the installation, but because this exe is an installation program itself, it could not run from within another install. Anyway, it really blew up the size of an already hefty download.<br /><br />The third source of distress is the Ogre configuration window that you see when starting up. Don't panic! It has been left for a reason. Firstly it is a tribute to the Ogre library, and secondly it is really helpful to change the settings to get the system to work. I even got the game running on an old PC with a very basic graphics card. The game has strange behaviour and even crashed on this machine when the settings were ill chosen. I'd be really interested if you cannot get this game to work on your system.<br /><br />So much for the boos.<br /><br />On the up side, I have learnt a lot about <a href="http://www.ogre3d.org/">Ogre</a>. I still have quite a bit of ground to cover though. I love the idea that I can define overlays and materials in scripts. Not having to compile the application every time is such a pleasure. Also, it is quite easy to pull in any true-type font into your game.<br /><br /><a href="http://www.openal.org/">OpenAL</a> is really impressive as well. It has the ability to move objects around in a 3 dimensional sound universe. If you combine that with a moving listener, sound effects can become quite amazing. I have not used any of these great effects in DropIt, but I can't wait to use them in some future endeavor.<br /><br />All and all it was a good experience to put this game together. You can judge for yourself by downloading the game <a href="http://www.t-3s.net/wiki/DracoCepheus/files?get=dropitsetup1.msi">from here</a>. Let me know what you think!Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0tag:blogger.com,1999:blog-3928112590563122949.post-16427209259358203792006-12-07T20:00:00.001+02:002008-12-23T08:13:16.116+02:00Wherefore art thou going, Draco?Imagine you want to write a game -- you know quite a bit about programming and you have a few hours a week. Naturally, within minutes your imagination go ballistic, boundless ideas spring into being, wonderful concepts are conceived. However, reality dawns, and you conclude that you're ideas are not that original -- in fact they are best vague reflections on games you have already played. Of course, you could be a highly gifted individual, and come up with something that is new, at least in your experience. But a quick Google will burst your bubble, and you might conclude that even this idea is not that phat. Then you come across a cool new game, such as the <a href="http://binnenstad.hku.nl/">The Blob</a>, and you marvel at the innovation shown by a bunch of noobs (or so it appears), while also wondering <span style="FONT-STYLE: italic">why can I not think of something like that?<br /></span><br />The conclusion I came to is that I need to bring down my expectations of myself. Way down. Not only do my ideas suck, but I am also simply not able to deliver even a radically boiled down version of these virtual concoctions. I then found <a href="http://www.gamedev.net/reference/design/features/makegames/default.asp">an interesting article</a> that not only made me feel better, but also provided a practical road-map to get to where I wanna be. It says : "Do Tetris first!", and that is exactly what I did, I started a Tetris project.<br /><br />I chose a few tools, and some libraries that looked good during my window shopping expedition here on the net. There is <a href="http://www.blender.org/">Blender</a> for 3-d artwork, <a href="http://www.gimp.org/">GIMP</a> for 2-d artwork, <a href="http://www.ogre3d.org/">Ogre</a> for 3-d graphics and<a href="http://www.openal.org/"> OpenAL</a> for sound. These tools might be an overkill for the task at hand, but I am doing this for fun, am I not?<br /><br />There are other libraries that are specifically geared for gaming, but I have decided to ignore these for a while. I might have a better appreciation for these after I try to build my own glue between the tools that I have chosen. Time will tell, even though it has no lips.<br /><br />Leave a comment, or at least <a href="http://poll.pollcode.com/UnnR">take my poll</a>.Willemhttp://www.blogger.com/profile/12795167342888706497noreply@blogger.com0