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 23, 2011 8:54 pm 

Joined: Sat Jun 18, 2011 3:29 am
Posts: 17
beyzend wrote:
That looks like off by one error, I think you are over extending the boundary. You have to really think about boundary conditions so you don't have off-by-one errors.

Oh wait I see it. I didn't check my partner's code and he was indeed off by 1 in x, y, and z :D

As for density, my partner just set every voxel to maxDensity. Obviously you can't do this anymore as a Material so I SetMaterial(1) instead. I will probably change this later because I may need at least 3 different density so I may do something like MaterialDensityPair<unsigned int, 30, 2>.

Thanks for your help!


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Fri Jun 24, 2011 3:53 am 

Joined: Sun Jan 23, 2011 6:06 am
Posts: 92
Hello. In the images where you are using the number "10" with different colors on different faces, would you mind please posting your source image for the material? I am just interested to see how you did it.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Fri Jun 24, 2011 7:45 am 

Joined: Sat Jun 18, 2011 3:29 am
Posts: 17
DefiniteIntegral wrote:
Hello. In the images where you are using the number "10" with different colors on different faces, would you mind please posting your source image for the material? I am just interested to see how you did it.


Sure, no problem.

VoxelTexture.material <-- Name doesn't matter for the material. You can set the name of the material in the material [name] loop. That's what you call in your ManualObject or Entity or whatever you are using.
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 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 Dirt.png 2d
            filtering anisotropic
                max_anisotropy 16
         }
      }
   }
}


For the image, I just grabbed the image in the materials/textures folder in the OGRESDK. It's called 10points.png and I just changed the name. It's a nice texture to check out how each face is being drawn.

VoxelTexture.cg <--This name does matter.
Code:
#define VOXELCENTEROFFSET 0.5

void voxeltexture_vp(
   float4 inPosition         : POSITION,

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

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

void voxeltexture_fp(
   float4 inWorldPosition       : TEXCOORD0,

   out float4 color         : COLOR,

   uniform sampler2D texture)
{
   float3 worldNormal = cross(ddy(inWorldPosition.xyz), ddx(inWorldPosition.xyz));
   worldNormal = normalize(worldNormal);
   //Right
    if(worldNormal.x > 0.5)
    {
        color = tex2D(texture, float2((1 - inWorldPosition.z) + VOXELCENTEROFFSET, (1 - inWorldPosition.y) + VOXELCENTEROFFSET));
    }
   //Left
   if(worldNormal.x < -0.5)
    {
        color = tex2D(texture, float2(inWorldPosition.z + VOXELCENTEROFFSET, (1 - inWorldPosition.y) + VOXELCENTEROFFSET));
    }
   //Top
    if(worldNormal.y > 0.5)
    {
        color = tex2D(texture, inWorldPosition.xz + VOXELCENTEROFFSET);
    }
   //Bottom
    if(worldNormal.y < -0.5)
    {
        color = tex2D(texture, float2(inWorldPosition.x + VOXELCENTEROFFSET, (1 - inWorldPosition.z) + VOXELCENTEROFFSET));
    }
   //Front
    if(worldNormal.z > 0.5)
    {
        color = tex2D(texture, float2(inWorldPosition.x + VOXELCENTEROFFSET, (1 - inWorldPosition.y) + VOXELCENTEROFFSET));
    }
   //Back
    if(worldNormal.z < -0.5)
    {
        color = tex2D(texture, float2((1 - inWorldPosition.x) + VOXELCENTEROFFSET, (1 - inWorldPosition.y) + VOXELCENTEROFFSET));
    }
}


This does not color code the different faces however. I'll talk about that below.

A word of caution here. You can use:
Code:
if(worldNormal.x > 0.0)
if(worldNormal.x < 0.0)

as conditions for the x-axis (and same for y and z). This worked for me. I was running this in DX9 with an ATI card. OpenGL crashes Ogre for me (and not just in this project) so I have no way of knowing.

My partner has an nVidia card, and using 0.0 would cause the textures on the left/right and top/bottom images to look like static. Changing it to 0.5/-0.5 fixed it for him. He was also running in DX as OpenGL is causing problems. For his scenario with the OpenGL trouble it may be some other problem and not related to Ogre at all. But because of that I have no idea if this works for OpenGL. This is to let you and anyone who happens to find this know.

As for colors, inside one of the conditionals that test the normal, you can do something like this:

This is the original:
Code:
color = tex2D(texture, float2((1 - inWorldPosition.x) + VOXELCENTEROFFSET, (1 - inWorldPosition.y) + VOXELCENTEROFFSET));


Change it to:
Code:
float4 col; //More useful to define this outside of the conditional
col = tex2D(texture, float2((1 - inWorldPosition.x) + VOXELCENTEROFFSET, (1 - inWorldPosition.y) + VOXELCENTEROFFSET));
color = col + float4(0.0, 0.0, 0.0, 1.0);


Just replace the first 3 0.0's with your RGB color (last one is A). float4(1.0, 0.0, 0.0, 1.0) would give you red, float4(1.0, 1.0, 0.0, 1.0) would give you yellow and so on. I color coded the different faces when I was testing if I got their orientation right.

Lastly, you can also search through http://www.thermite3d.org/phpBB3/viewtopic.php?t=77 to find some additional things (like scaling, texture atlas). I based mine off of that with help. I'll end up doing things like those as well but right now I am messing with Libnoise to generate terrain so it will be a while.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Fri Jun 24, 2011 11:15 am 

Joined: Sun Jan 23, 2011 6:06 am
Posts: 92
Thanks.

To be honest I don't really know that much about materials since I have always just played around more with rendering systems and stuff. So I will probably copy some stuff from your material above to get started in working out materials if you don't mind.

Rather than a texture atlas, would it be possible to use multiple texture channels (1 for each face) and just choose which texture to sample from based on the face direction / normal? Graphics cards support 8 texture channels these days, right..... ?

I would have no idea how to do this though. I really should read up some noob tutorials on using .cg

Btw I have the same problem with Ogre and not being able to use OpenGL. Loading the OpenGL DLL crashes Ogre at startup.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Fri Jun 24, 2011 3:12 pm 

Joined: Sat Sep 18, 2010 9:45 pm
Posts: 189
The reason I'm using texture atlas is to reduce draw call since you can render an entire chunk in a single draw call. If you don't use texture atlas then you have to have N buffers ready each with it's own texture and write your mesh to these N buffers. I'm curious how this will performance so i'd appreciate it if someone posted their results here.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Sun Jun 26, 2011 8:19 am 

Joined: Sat Jun 18, 2011 3:29 am
Posts: 17
Hey Beyzend (or anyone that has this working) can you show me how you did your texture atlas? I PM'd AndiNo and he gave me his C++ code and shader code, but he doesn't really remember what he did in the shader.

The idea of his code is to:
1. Find the col and row a texture is on. For example, (2, 1) is the texture on the second column, row 1 (columns and rows start at 1). He then passes this information inside a Ogre::ColourValue (specifically the r and g) which is then applied to the manual object. Since he has a 256x256 image and each texture is 16x16, there are 16 rows and columns. He will then multiply the column and row by 16/256 which are then stored in the r and g of the ColourValue (because it is [0.0, 1.0]).

2. Pass the color in the VP and into the FP. Now reconvert that color value to back to the column and row by dividing 16/256. After this he adds the uv coords you obtain using the world position.

I am failing somewhere and am just drawing the entire texture atlas as the image.

This is my vertex loop:
Code:
#define NUM_TEXTURES 256
#define NUM_NONTEX_MATERIALS 1 //Air is 0 for me, so the first texture is actually material 1, so materialID - 1 to offset this
#define NUM_TEXTURES_PER_ROW 16
#define TEX_WIDTH_NORMALIZED (NUM_TEXTURES_PER_ROW / NUM_TEXTURES) //This is 16/256

            vector<PositionMaterial>::iterator vecItr;
            for(vecItr = vecVertices.begin(); vecItr != vecVertices.end(); vecItr++)
            {
               Vector3DFloat pos = vecItr->getPosition() * worldScale;
               pos += (Vector3DFloat(j * chunkSize, k * chunkSize, i * chunkSize) * worldScale);
               obj->position(pos.getX(), pos.getY(), pos.getZ());

               Ogre::ColourValue colVal;
               uint8_t matID = vecItr->getMaterial(); //+ 0.5;
               colVal.r = ((matID - NUM_NONTEX_MATERIALS) % NUM_TEXTURES_PER_ROW) * TEX_WIDTH_NORMALIZED; // - pixelOffset;
               unsigned int matY = (unsigned int) (matID / NUM_TEXTURES_PER_ROW);
               colVal.g = (float) (matY * TEX_WIDTH_NORMALIZED);
               colVal.b = 0.0f;
               colVal.a = 1.0f;
               obj->colour(colVal);
            }


This is my shader code:
Code:
#define VOXELCENTEROFFSET 0.5
#define WORLDSCALE 2.0
//Pixel size of the texture atlas
#define TEXATLASSIZE 256
//Pixel per single texture
#define TEXATLAS_TEXSIZE 16
//Number of textures per row
#define TEXATLAS_NUMTEX (TEXATLASSIZE / TEXATLAS_TEXSIZE)
//Size of a single texture in 0.0 - 1.0 values
#define TEXATLAS_TEXSIZE_NORMALIZED ((float)TEXATLAS_TEXSIZE / (float)TEXATLASSIZE)

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            : COLOR,

   out float4 color         : COLOR,

   uniform sampler2D texAtlas)
{
   float3 worldNormal = cross(ddy(inWorldPosition.xyz / WORLDSCALE), ddx(inWorldPosition.xyz / WORLDSCALE));
   worldNormal = normalize(worldNormal);
   
   float2 pos;
   
   //Handle texture atlas
   int2 posColor;
   // X coordinate
   inColor.x /= TEXATLAS_TEXSIZE_NORMALIZED;
   posColor.x = (int) inColor.x;
   pos.x = posColor.x;
   // Y coordinate
   inColor.y /= TEXATLAS_TEXSIZE_NORMALIZED;
   posColor.y = (int) inColor.y;
   pos.y = posColor.y;
   
   //Right
    if(worldNormal.x > 0.5)
    {
      pos += float2(1 - inWorldPosition.z / WORLDSCALE + VOXELCENTEROFFSET, 1 - inWorldPosition.y / WORLDSCALE + VOXELCENTEROFFSET);
    }
   //Left
   if(worldNormal.x < -0.5)
    {
        pos += float2(inWorldPosition.z / WORLDSCALE + VOXELCENTEROFFSET, 1 - inWorldPosition.y / WORLDSCALE + VOXELCENTEROFFSET);
    }
   //Top
    if(worldNormal.y > 0.5)
    {
        pos += float2(inWorldPosition.xz / WORLDSCALE + VOXELCENTEROFFSET);
    }
   //Bottom
    if(worldNormal.y < -0.5)
    {
        pos += float2(inWorldPosition.x / WORLDSCALE + VOXELCENTEROFFSET, 1 - inWorldPosition.z / WORLDSCALE + VOXELCENTEROFFSET);
    }
   //Front
    if(worldNormal.z > 0.5)
    {
        pos += float2(inWorldPosition.x / WORLDSCALE + VOXELCENTEROFFSET, 1 - inWorldPosition.y / WORLDSCALE + VOXELCENTEROFFSET);
    }
   //Back
    if(worldNormal.z < -0.5)
    {
        pos += float2(1 - inWorldPosition.x / WORLDSCALE + VOXELCENTEROFFSET, 1 - inWorldPosition.y / WORLDSCALE + VOXELCENTEROFFSET);
    }
   
   color = tex2D(texAtlas, pos);
}


Is the concept correct? Where am I failing? Do you have any other way to do this that may be better?


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Mon Jun 27, 2011 11:37 pm 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
I don't have any code for you as I'm not using a texture atlas myself, but you seem to have the concept correct. Maybe you can debug it by replacing some of the variables with hard-coded values which you know are correct? And maybe also try a one dimensional texture atlas with only two textures to start with?


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Wed Jun 29, 2011 11:55 pm 

Joined: Sat Jun 18, 2011 3:29 am
Posts: 17
I'll work on texture atlas later. Right now I am trying to implement block removal. I am having setDynamic(true) on all manual objects I am constructing right now, and rebuilding the chunk the block belongs to through .beginUpdate(0) (each of my chunk is its own manual object so there's only 1 section). This stutters on 32^3 but runs smoothly on 16^3.

However when I remove a block, the voxels nearby do not get their texture displayed. This is very weird. Got some pictures of what I am talking about.

I removed the block in front of me and the block below it. This looks fine.

Image

I remove some block here, and the voxel below it doesn't display its up face:

Image

I know there is a valid block there because as soon as I remove it and the block behind it (I am thinking this is because the chunk gets rebuilt again and it comes up right).

Image

Why does this happen?

In addition it seems terribly inefficient to rebuild an entire chunk. Should I think about getting in the vertexBuffer myself and set it?

Here's my removal code just in case. The raycast function sets the material for the voxel to 0, and finds the chunk the block belongs to so I only have to rebuild that chunk. Also don't mind the ijk being set up weirdly in the string. This is because PolyVox and Havok sets their xyz differently.
Code:
void GraphicsManager::UpdateManualObject(SimpleVolume<VoxelMat>& volData, WorldTerrain wTerra, Vector3DInt32 chunkNum)
{
   int i = chunkNum.getX();
   int j = chunkNum.getY();
   int k = chunkNum.getZ();

   char str[50];
   sprintf(str, "%d-%d-%d", k, i, j);

   Vector3DInt32 start(i * chunkSize, j * chunkSize, k * chunkSize);
   Vector3DInt32 end((i + 1) * chunkSize - 1, (j + 1) * chunkSize - 1, (k + 1) * chunkSize - 1);

   SurfaceMesh<PositionMaterial> mesh;
   CubicSurfaceExtractor<SimpleVolume, VoxelMat> surfaceExtractor(&volData, Region(start, end), &mesh);
   surfaceExtractor.execute();

   ManualObject *obj = manualObjects[str];

   obj->estimateVertexCount(mesh.getNoOfVertices());
   obj->estimateIndexCount(mesh.getNoOfIndices());

   vector<uint32_t> vecIndices = mesh.getIndices();
   vector<PositionMaterial> vecVertices = mesh.getVertices();

   obj->beginUpdate(0);

   vector<PositionMaterial>::iterator vecItr;
   for(vecItr = vecVertices.begin(); vecItr != vecVertices.end(); vecItr++)
   {
      Vector3DFloat pos = vecItr->getPosition() * worldScale;
      pos += (Vector3DFloat(i * chunkSize, j * chunkSize, k * chunkSize) * worldScale);
      obj->position(pos.getX(), pos.getY(), pos.getZ());
   }

   vector<uint32_t>::iterator indVec;
   for(indVec = vecIndices.begin(); indVec != vecIndices.end(); indVec++)
   {
      obj->index(*indVec);
   }

   obj->end();
}


Hmm I Googled and asked around a bit and it seems it would be beneficial to turn D3DUSAGE_DYNAMIC on. Does anyone have any idea how to do this in Ogre? Googling this doesn't give me the results I want.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Thu Jun 30, 2011 2:33 am 

Joined: Sat Sep 18, 2010 9:45 pm
Posts: 189
I don't think there is a public way to set hardware buffer usage with manual object (could be wrong). Instead, you may want to skip the middle man and just work with Ogre hardware buffers, you can then set the buffer usage. http://www.ogre3d.org/docs/manual/manual_51.html#SEC275

I'm not sure how much this will affect performance. I meant to switch from manual object to hardware buffers to see but have not found the time to do so yet.

As for you border issues, well, that's one of the border issues you have to either resolve or made irrelevant (somehow). In my setup, because the way extractor works by needing to examine element x -1 at x, therefore on chunk borders you need to reextract a neighbor so the extracted state match. For example, let's say you delete element 31 on a chunk H, but it's neighbor (H+1)'s 0th element needs x - 1, which is element 31 on the chunk H. If you don't reextract (H+1) then you may see visual artifacts because both chunk no longer match.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Thu Jun 30, 2011 6:35 am 

Joined: Sat Jun 18, 2011 3:29 am
Posts: 17
I see what you mean about the neighbors thing. So you are saying that I could perform a check to see if the voxel is a bordering voxel. If so then just update the chunk(s) it is bordering as well. I'll probably just use this and see how the speed works. If it is unacceptable I may need to use the vertexBuffer directly, which would be a pain.


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