It is currently Sat Aug 22, 2020 2:04 pm


All times are UTC




Post new topic Reply to topic  [ 37 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Thu Jun 30, 2011 7:13 pm 

Joined: Sat Sep 18, 2010 9:45 pm
Posts: 189
Are you manually updating the manual object or are you modifying the volume then extract? I'm doing the latter and changing to use vertex buffer for this case shouldn't be that complicated because you just have to write the vertex buffer code once and reuse.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Fri Jul 01, 2011 9:31 pm 

Joined: Sun Oct 03, 2010 10:13 pm
Posts: 73
Sorry for the late reply. I've been busy with university again.
AuraofMana wrote:
I am failing somewhere and am just drawing the entire texture atlas as the image.

From looking at the shader code I can't say where the error is, however your atlas-handling code looks quite a bit different from mine. As I already mentioned I'm not remembering what I actually did in my code but I'm sure the stuff is in there for a reason ;)


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Sat Jul 02, 2011 8:45 pm 

Joined: Sat Jun 18, 2011 3:29 am
Posts: 17
beyzend wrote:
Are you manually updating the manual object or are you modifying the volume then extract? I'm doing the latter and changing to use vertex buffer for this case shouldn't be that complicated because you just have to write the vertex buffer code once and reuse.


I am modifying the volume and then extracting it again. I skimmed your link but haven't delve into it. I've been working on something else in the project. I'll just have to sit down for two hours and figure out how Ogre is storing the vertexBuffer at some point.

Wouldn't I have to convert the manual object to a mesh?


Last edited by AuraofMana on Sat Jul 02, 2011 10:54 pm, edited 2 times in total.

Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Sat Jul 02, 2011 9:43 pm 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
AuraofMana wrote:
Wouldn't I have to convert the manual object to a mesh?


Nope, you can get direct access to vertex and index buffers in Ogre through the Ogre::HardwareBuffer class. But you also need to learn about the rendering architecture of Ogre, as I think you need to crate your own Renderable objects. Actually I am a bit hazy here. At any rate it's a lot more complex than just using the ManualObjects, but also potentially faster because you can just to a memcpy() of the vertex and index data.

But is it really the ManualObject which is your bottleneck? What takes longer out of building the ManualObject or using PolyVox to extract the mesh in the first place? If you don't actually know where the bottleneck is you might do a lot of work for little gain. Are you using the CubicSurfaceExtractor without normals?


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Sat Jul 02, 2011 10:59 pm 

Joined: Sat Jun 18, 2011 3:29 am
Posts: 17
David Williams wrote:
Nope, you can get direct access to vertex and index buffers in Ogre through the Ogre::HardwareBuffer class. But you also need to learn about the rendering architecture of Ogre, as I think you need to crate your own Renderable objects. Actually I am a bit hazy here. At any rate it's a lot more complex than just using the ManualObjects, but also potentially faster because you can just to a memcpy() of the vertex and index data.

But is it really the ManualObject which is your bottleneck? What takes longer out of building the ManualObject or using PolyVox to extract the mesh in the first place? If you don't actually know where the bottleneck is you might do a lot of work for little gain. Are you using the CubicSurfaceExtractor without normals?


Yea I am using CubicSurfaceExtractor without normals. I haven't really checked on what the bottleneck is but as of right now, it's running at 1000 FPS on release and it drops to 700~ when removing an object. There is no stutter and I can pretty much spam. This sounds nice but I am pretty sure as the program gets more complicated it'll slow down. I am just not sure if it'll slow down enough to the point where removing an object produces noticeable delay. I am not too worried about it right now though since I am using 32^3 as a chunk. Even when removing a block on the edge of a chunk (worst case scenario) where I have to update 3 bordering chunks in addition to the current chunk it's not that bad. This isn't a necessity right now so I am just wondering about this in case I do need to do it.

As for texture atlas, how does inputting worldPosition result in [0,1] uv coordinates? For example when you have something like:
Code:
#define VOXELCENTEROFFSET 0.5
#define WORLDSCALE 1.0
   //Left
   if(worldNormal.x < -0.5)
    {
        pos.x = inWorldPosition.z / WORLDSCALE + VOXELCENTEROFFSET;
      pos.y = 1 - inWorldPosition.y / WORLDSCALE + VOXELCENTEROFFSET;
    }
   outColor = tex2D(texture, pos);
}


How does this work? I originally thought that it would just use the decimal value (i.e., 17.5 is 0.5 in uv coordinates) which would mean that in order to do texture atlas I would have to convert to [startX, endX] and [startY, endY] instead of the traditional [0, 1]. However this hasn't been working and I am not really sure how to do texture atlas from this point. I've tried AndiNo's code and it doesn't work.

For example, if I have a texture atlas with just 2 images, to get the image on the right all I really need to do is divide u by 2. But then the blocks would alternate the different textures like this:

Image

I tried looking up how using world position as uv coordinates work but I can't seem to find anything that explains it on Google. Can anyone enlighten me?


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Sun Jul 03, 2011 6:22 pm 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
AuraofMana wrote:
How does this work? I originally thought that it would just use the decimal value (i.e., 17.5 is 0.5 in uv coordinates) which would mean that in order to do texture atlas I would have to convert to [startX, endX] and [startY, endY] instead of the traditional [0, 1]. However this hasn't been working and I am not really sure how to do texture atlas from this point. I've tried AndiNo's code and it doesn't work.


For a normal texture (not a texture atlas) it works because your tex_address_mode mode is set 'wrap', which is the default. When texture coordinates go out of the 0-1 range they simply wrap around, meaning 17.5 ends up sampling 0.5.

With texture atlases you can't quite do this because, for a texture in the middle of the atlas, you don't ever want to touch the edge. So instead of doing the wrapping you should manually take the fractional part with something like frac()

So, to access only the first texture in your two-texture atlas you should use frac() and thenmultiply by 0.5. To access only the second texture you should then add 0.5.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Mon Jul 04, 2011 11:17 am 

Joined: Sat Jun 18, 2011 3:29 am
Posts: 17
Okay, I got texture atlas working. There are some imperfections however.

1. There were random streaks of lines along the border. This is seemingly fixed by using linear filtering (linear point point point in Ogre material to be more specific).
2. There are color bleeding, which is expected. Now I am wondering what texture atlas program are there that can handle this for me (if there are any). I remember seeing it referenced on the forums here a while back but I wanted to see if anyone has any updates on it.

Here is what I am talking about:
Image

It's a lot more clearer with grass:
Image

Here is my Ogre.material:
Code:
vertex_program VoxelTexture_VP cg
{
   source VoxelTexture.cg
   entry_point voxeltexture_vp
   profiles vs_1_1

   default_params
    {
      param_named_auto world world_matrix
      param_named_auto viewProj viewproj_matrix
    }
}

fragment_program VoxelTexture_FP cg
{
   source VoxelTexture.cg
   entry_point voxeltexture_fp
   profiles ps3_0 ps_2_x ps_2_0
}

material VoxelTexture
{
   receive_shadows on
   technique
   {
      pass
      {
         vertex_program_ref VoxelTexture_VP
         {
         }
         
         fragment_program_ref VoxelTexture_FP
         {
         }
         
         texture_unit
         {
            texture TextureAtlas.png 2d
            filtering point point point
            tex_address_mode clamp
         }
      }
   }
}


Here is my CG Shader code:
Code:
#define VOXELCENTEROFFSET 0.5
#define WORLDSCALE 1.0
#define NUM_TEX_PER_ROW 4
#define TEX_WIDTH_NORMALIZED (1.0 / NUM_TEX_PER_ROW)

void voxeltexture_vp(
   float4 inPosition         : POSITION,
   float4 inColor            : COLOR,

   out float4 outPosition     : POSITION,
   out float4 outWorldPosition   : TEXCOORD0,
   out float4 outColor         : TEXCOORD1,

   uniform float4x4 world,
   uniform float4x4 viewProj)
{
   outWorldPosition = mul(world, inPosition);
   
   outPosition = mul(viewProj, outWorldPosition);
   
   outColor = inColor;
}

void voxeltexture_fp(
   float4 inWorldPosition       : TEXCOORD0,
   float4 inColor            : TEXCOORD1,

   out float4 outColor         : COLOR,

   uniform sampler2D texture)
{
   float3 worldNormal = cross(ddy(inWorldPosition.xyz / WORLDSCALE), ddx(inWorldPosition.xyz / WORLDSCALE));
   worldNormal = normalize(worldNormal);
   
   float2 pos;
   //Right
    if(worldNormal.x > 0.5)
    {
      pos = frac(inWorldPosition.zy + VOXELCENTEROFFSET); //Only divide by WORLDSCALE if it isn't a whole number
        pos.x = 1 - pos.x;
      pos.y = 1 - pos.y;
    }
   //Left
   if(worldNormal.x < -0.5)
    {
      pos = frac(inWorldPosition.zy + VOXELCENTEROFFSET);
      pos.y = 1 - pos.y;
    }
   //Top
    if(worldNormal.y > 0.5)
    {
      pos = frac(inWorldPosition.xz + VOXELCENTEROFFSET);
    }
   //Bottom
    if(worldNormal.y < -0.5)
    {
      pos = frac(inWorldPosition.xz + VOXELCENTEROFFSET);
      pos.y = 1 - pos.y;
    }
   //Front
    if(worldNormal.z > 0.5)
    {
      pos = frac(inWorldPosition.xy + VOXELCENTEROFFSET);
      pos.y = 1 - pos.y;
    }
   //Back
    if(worldNormal.z < -0.5)
    {
      pos = frac(inWorldPosition.xy + VOXELCENTEROFFSET);
        pos.x = 1 - pos.x;
      pos.y = 1 - pos.y;
    }
   
   //Texture atlas handling
   pos *= TEX_WIDTH_NORMALIZED;
   if(inColor.x != 0)
   {
      pos.x += inColor.x;
   }
   if(inColor.y != 0)
   {
      pos.y += inColor.y;
   }
   
   outColor = tex2D(texture, pos);
}


Here is my C++ code that is pertinent to this (this is inside the Vertices loop):
Code:
               Ogre::ColourValue val;
               VoxelMat vMat = vecItr->getMaterial();
               uint16_t mat = vMat.getMaterial() - NUM_NONTEX_MATERIALS;
               /*
               r = u coords where the texture starts
               g = v coords where the texture starts
               b = direction of the block with 0.0, 0.25, 0.5, 0.75 as North, East, South, West
               a = maybe used to flag that one of the faces uses a different texture?
               */
               val.r = mat % NUM_TEX_PER_ROW * TEX_WIDTH_NORMALIZED;
               val.g = mat / NUM_TEX_PER_ROW * TEX_WIDTH_NORMALIZED;
               val.b = 0.0f;
               val.a = 1.0f;
               obj->colour(val);


In addition I have some questions:

1. When you use a frac, doesn't this mean that there is nothing on the entire [1, 1]? Could this be the thing I am seeing instead of color bleeding?
2. I would need to handle blocks with directions and this would mean using a different texture to show this. In addition, some blocks may have different textures on top and on bottom. For this, wouldn't handling this in the shader code be extremely slow? I think I read somewhere that shader codes aren't meant to do a bunch of conditionals.
3. Related to 2, is there a way to transport all of these calculation (normal and tex coords) to the vertex (which would mean I cannot use ddy and ddx to determine the normals as that is a pixel shader only thing). This is because the pixel shader is a lot more expensive than the vertex shader.
4. Is there a way to actually do this in the C++ code itself?
5. Would you suggest doing lighting in the vertex shader or the pixel shader?

Edit on 4:
So if I print the indices out in triplets I would end up getting these coordinates as vertices (first 2 triangles):
(31.5,15.5,0.5)
(29.5,15.5,0.5)
(0.5,17.5,-0.5)

(31.5,15.5,0.5)
(0.5,17.5,-0.5)
(-0.5,17.5,-0.5)

As you can tell the third point doesn't match up to the expectation of a triangle of a face of a cube. I assume this is because CubicSurfaceExtractor has the built in decimation thus producing this. Is this correct? If so you can't set texture coordinates on the vertex like this.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Mon Jul 04, 2011 9:59 pm 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
AuraofMana wrote:
2. There are color bleeding, which is expected. Now I am wondering what texture atlas program are there that can handle this for me (if there are any). I remember seeing it referenced on the forums here a while back but I wanted to see if anyone has any updates on it.


I think you're looking for this: http://www.ogre3d.org/forums/viewtopic.php?f=4&t=61602 ?

AuraofMana wrote:
In addition I have some questions:

1. When you use a frac, doesn't this mean that there is nothing on the entire [1, 1]? Could this be the thing I am seeing instead of color bleeding?


The range will go from 0 to 0.999... I think this is the behaviour you want and does not lead to colour bleeeding, but I'm not certain here.

AuraofMana wrote:
2. I would need to handle blocks with directions and this would mean using a different texture to show this. In addition, some blocks may have different textures on top and on bottom. For this, wouldn't handling this in the shader code be extremely slow? I think I read somewhere that shader codes aren't meant to do a bunch of conditionals.


The GPU processes a number of pixels in parallel. If all these pixels take the same path then conditionals are fast, they become slow if different pixels in the group take different paths. If I were you I'd try it and see.

If it was me I would make a texture atlas which was indexed by material ID along one axis and face ID (0,1,2,3,4,5) along the other. You could then create this face ID using conditionals (based on the normal). If you want to get clever you could create a 1x1x1 cubemap where each face stores the index. Then a cubemap lookup would convert a normal to a face index. No idea is this is actually faster, I just thought it sounded like a nice trick...


AuraofMana wrote:
3. Related to 2, is there a way to transport all of these calculation (normal and tex coords) to the vertex (which would mean I cannot use ddy and ddx to determine the normals as that is a pixel shader only thing). This is because the pixel shader is a lot more expensive than the vertex shader.


In general I think you need to do most of the work in the pixel shader due to lack of normal in the vertex shader. And also the decimation, as you noted later.

AuraofMana wrote:
4. Is there a way to actually do this in the C++ code itself?


If you ignore the decimation issue, you could choose to pass normals from C++. PolyVox doesn't give them to you but you can compute them your self easily enough. You could also compute the texture coordinates in C++ and pass them in a seperate stream (probably multiple streams) though this seems wasteful of space as they are just a multiple of the world position.

You could also split the mesh up if you wanted, based on what direction the quads are facing. I'm not saying any of these things are a good idea, just that you have a lot of options and no one right solution.

AuraofMana wrote:
5. Would you suggest doing lighting in the vertex shader or the pixel shader?


Again, if you ignore the decimation, and if you pass your own normals from C++ (or use the CubicSurfaceExtractorWithNormals) the you can do per-vertex lighting. At that point I guess it depends on the artistic style you prefer.

AuraofMana wrote:
I assume this is because CubicSurfaceExtractor has the built in decimation thus producing this. Is this correct?


Yes, but you can turn it off via the last parameter to the CubicSurfaceExtractor constructor


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Sat Jul 09, 2011 4:39 am 

Joined: Sat Jun 18, 2011 3:29 am
Posts: 17
Took a rest from texture atlas to work on chunk paging instead. My goal is to have 4 direction of movement when paging, and so the chunks you no longer see will get saved on file while all the SimpleVolume information will be memmoved to the right place (for example, if I am moving west, every chunk except the last on the west will move over by chunksize. New chunk information are then stored in the new empty place). New chunk information are gathered from save files, or if none are present, generated.

I took a look in SimpleVolume and see that the nested loop goes ZYX, assuming that 0,0,0 is on the top left bottom, and so voxels will fill from west to east starting with the bottom most layer. Once one "slice" is filled, it moves on to 0,0,1 and repeat until everything is filled.

I coded my SimpleVolume shifting (using memmove) around this idea. So moving west would be something like:
Code:
   int horizontalChunk = centerChunk * 2 - 1; //Total chunk through x and z-axis, they are always the same and are always odd
   int horizontalSize = horizontalChunk * chunkSize; //Number of voxels in x or z-axis
   int horizontalSlice = horizontalSize * verticalMax; //Number of voxels in x or z-axis * y-axis
   int size = horizontalSize - chunkSize; //Since every chunk except the last is moving one chunksize right, this is size of the move
   int verticalChunk = verticalMax / chunkSize; //How many chunks is in the y-axis
   int lastChunk = horizontalChunk - 1; //The very last chunk

   //Move the voxels
   for(int i = 0; i < horizontalSize; ++i)
   {
      for(int j = 0; j < verticalMax; ++j)
      {
         memmove(polyVolume + (horizontalSlice * i + horizontalSize * j + chunkSize), polyVolume + (horizontalSlice * i + horizontalSize * j), size);
      }
   }


So if chunkSize is 32 and centerChunk is 2, meaning there is a 3x3 square representing the current world, the first loop would make start = 0, end = 32, and size as 64. What this means is that 64 voxels from 0 are moved over positive 32 elements. This is then performed for every single 96 voxels starting from y = 0 to y = 256 (my verticalMax). After verticalMax is hit, it would start over again with y = 0 while z += 1, causing the horizontalSlice one element south to be working in the same fashion.

The program would crash due to access violation. I checked the prints are they are right, although even though I am moving in the same fashion every time, it would crash in different places in the loop (different start and end). Upon checking the PolyVolume data, I find that the m_uWidthInBlocks, m_uHeightInblocks, and m_uDepthInBlocks to be different every time, as well as m_uNoOfBlocksInVolume. I do not understand why this is the case and was hoping someone can enlighten me on this.

In addition, is there anyway of doing this? Could Regions be utilized? If anyone knows another way I would be glad to hear it. Thanks!


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Sat Jul 09, 2011 2:10 pm 

Joined: Sat Sep 18, 2010 9:45 pm
Posts: 189
correct me if I'm wrong, but doing it that way is pretty inefficient. It's not going to scale. If you want paging use LargeVolume which already supports paging. I'm working on another paging volume right now (I'm calling it TorusVolume) which pages into a constant size volume.

The volume I'm implementing uses http://en.wikipedia.org/wiki/Modulo_operation to page.

If you want to wait a little bit, maybe another week, I should have the TorusVolume ready. It may be want you want or it may not.


Top
Offline Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 37 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Theme created StylerBB.net