It is currently Sat Aug 22, 2020 3:41 pm


All times are UTC




Post new topic Reply to topic  [ 37 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
 Post subject: PolyVox and a Minecraft-esque Game
PostPosted: Mon Jun 20, 2011 9:22 am 

Joined: Sat Jun 18, 2011 3:29 am
Posts: 17
So my partner and I are trying to code a Minecraft-esque game (I know) over summer for practice. Of course we'll be using PolyVox and I have several questions. If anyone can help us that would be great!

1. We are using CubicSurfaceExtractorWithNormals. There was a recent snapshot that improved CubicSurfaceExtractor. Does it improve CubicSurfaceExtractorWithNormals as well? I am kind of sure it does but wanted to ask just in case.

2. While looking at the source code for CubicSurfaceExtractorWithNormals to look at how the vertices are done (so that I can get the texture coordinates right), I am not sure how it does it. In the Ogre tutorial for ManualObjects, it goes counter-clockwise starting with bottom left. Looking at the code in CubicSurfaceExtractorWithNormals, it seems like PolyVox follows something like: v0 as bottom left, v1 as bottom right, v2 as top left, and v3 as top right (or some other variation where no clockwise or counter-clockwise pattern is being done) since v1 and v2 are the shared vertices. Can anyone tell me the order?

3. We are definitely going to end up using MaterialDensityPair (may just end up using Material since Density doesn't seem very useful to us). I was wondering about two things:

3a. To construct the object (MaterialDensityPair or just Material), you need to provide a type. Providing anything other than ints makes it unhappy. Is there anyway to input non-int's without rebuilding PolyVox (just out of curiosity)? In addition, does __int64 work? If __int64 works a pointer can be provided that would work for x64 architecture. If not then I was thinking to only store the Block ID as this (so really, 9 bits or so is probably enough) and handle everything else (health, state, direction, etc.) as a separate Block object. If there is a better way please let me know.

3b. This question has to do with the density threshold in MaterialDensityPair or Material. What does PolyVox consider solid? Is > Threshold solid or non-solid? What about at the Threshold?

4. What is the difference between LargeVolume and SimpleVolume? Is SimpleVolume simply where each Voxel is a block and this is why a class SimpleVolumeBlock is provided?

Sorry if I asked any obvious or stupid questions. The SRC has been pretty helpful!


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

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
AuraofMana wrote:
1. We are using CubicSurfaceExtractorWithNormals. There was a recent snapshot that improved CubicSurfaceExtractor. Does it improve CubicSurfaceExtractorWithNormals as well? I am kind of sure it does but wanted to ask just in case.


No, the CubicSurfaceExtractorWithNormals has not benefited from these improvements (it's actually more difficult to apply them here). The CubicSurfaceExtractorWithNormals is really just to get you started with PolyVox, because it saves you from having to worry about computing the normals yourself in a shader. It will still handle a reasonable size terrain, but ultimatly you'll probably want to use the CubicSurfaceExtractor.

AuraofMana wrote:
2. While looking at the source code for CubicSurfaceExtractorWithNormals to look at how the vertices are done (so that I can get the texture coordinates right), I am not sure how it does it. In the Ogre tutorial for ManualObjects, it goes counter-clockwise starting with bottom left. Looking at the code in CubicSurfaceExtractorWithNormals, it seems like PolyVox follows something like: v0 as bottom left, v1 as bottom right, v2 as top left, and v3 as top right (or some other variation where no clockwise or counter-clockwise pattern is being done) since v1 and v2 are the shared vertices. Can anyone tell me the order?


I'm not exactly sure - I think the winding matches the OpenGL default which I think is counter-clockwise. But actrally you don't need to know the winding of the vertiecs to generate the texture coordinates - you can just use the vertex position (possibly with some scaling). E.g. if your vertex position is (12, 13, 14) you could use (12, 13) for the texture coordinate. If you do this for all vertices you will project the texture onto the xy plane of the model.

Of course, here your basically sending the same data in two seperate channels (or more, because you'll want to texture several axes). Instead you could write a shader which doesn't even need texture coordinates as it just uses the positions directly

AuraofMana wrote:
3. We are definitely going to end up using MaterialDensityPair (may just end up using Material since Density doesn't seem very useful to us). I was wondering about two things:


For a minecraft clone you can just use Material8 - you don't need to worry about the density.

AuraofMana wrote:
3a. To construct the object (MaterialDensityPair or just Material), you need to provide a type. Providing anything other than ints makes it unhappy. Is there anyway to input non-int's without rebuilding PolyVox (just out of curiosity)? In addition, does __int64 work? If __int64 works a pointer can be provided that would work for x64 architecture. If not then I was thinking to only store the Block ID as this (so really, 9 bits or so is probably enough) and handle everything else (health, state, direction, etc.) as a separate Block object. If there is a better way please let me know.


I think you may be confusing PolyVox materials with Ogre Materials - the two are unrelated. The volume will store a material ID for each voxel, and so having 8 bits means you can have 256 unique materials. This number (0-255) is attached to each vertex of the resulting mesh, but it is up to you how you interpret this. You might decide that it represent a texture in a texture atlas, or a colour in a lookup table.

In your case you probably want a single Ogre material with a shader which will look at the MaterialID which has been passed. The shader can then decide how the material ID should be interpreted.

AuraofMana wrote:
3b. This question has to do with the density threshold in MaterialDensityPair or Material. What does PolyVox consider solid? Is > Threshold solid or non-solid? What about at the Threshold?


If you use the Material8 class then zero is empty space and anything else is solid.

AuraofMana wrote:
4. What is the difference between LargeVolume and SimpleVolume? Is SimpleVolume simply where each Voxel is a block and this is why a class SimpleVolumeBlock is provided?


They are just different methods of storing the volume data. LargeVolume supports paging and compression and so can hold much larger volumes. It is very easy to switch between them so just use SimpleVolume for now.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Tue Jun 21, 2011 4:50 am 

Joined: Sat Jun 18, 2011 3:29 am
Posts: 17
I've been playing the the shader all day. A good beginner's tutorial I found was this: http://www.ogre3d.org/tikiwiki/JaJDoo+Shader+Guide&structure=Cookbook

Now, using material + program + shader code I got form this thread (written by David Williams himself): http://www.thermite3d.org/phpBB3/viewtopic.php?t=77, I am not seeing the texture to show up. Originally I had some problem with "Attempted to load Cg program 'ColoredCubicVoxelFP', but no supported profile was found." I corrected this by using: profiles ps_2_0 arbfp1 in the fragment_program. For good measure I did this for the vertex_program as well via: profiles vs_2_0 arbvp1. I plan on changing these back later (and find out whichever profile it can't find) once I get something working.

This is the ColoredCubicVoxel.material:

Code:
vertex_program VP cg
{
    source ColoredCubicVoxel.cg
    entry_point ColoredCubicVoxelVP
    profiles vs_2_0 arbvp1

    default_params
    {
        param_named_auto world world_matrix
        param_named_auto viewProj viewproj_matrix
    }
}

fragment_program FP cg
{
    source ColoredCubicVoxel.cg
    entry_point ColoredCubicVoxelFP
    profiles ps_2_0 arbfp1
   
    default_params
    {
    }
}

material ColouredCubicVoxel
{
    technique
    {               
        pass
        {                   
            vertex_program_ref VP
            {
            }

            fragment_program_ref FP
            {
            }   

            texture_unit
            {
                texture Dirt.jpg 2d
                filtering anisotropic
                max_anisotropy 16
            }       
        }
    }
}


This is the ColoredCubicVoxel.cg:

Code:
void ColoredCubicVoxelVP(
    float4 inPosition             : POSITION,
    float4 inNormal                 : NORMAL,

    out float4 outClipPosition      : POSITION,
    out float4 outWorldPosition       : TEXCOORD0,
    out float4 outWorldNormal       : TEXCOORD1,

    uniform float4x4 world,
    uniform float4x4 viewProj
    )
{   
    //Compute the world space position
    outWorldPosition = mul(world, inPosition);   
   
    //Just pass though the normals without transforming them in any way. No rotation occurs.
    outWorldNormal = inNormal;

    //Compute the clip space position
    outClipPosition = mul(viewProj, outWorldPosition);
}

void ColoredCubicVoxelFP(
    float4 inPosition           : POSITION,
    float4 inWorldPosition       : TEXCOORD0,
    float4 inWorldNormal       : TEXCOORD1,

    uniform sampler2D heightMap : TEXUNIT0,
   
    out float4 result           : COLOR)
{   
    inWorldNormal = normalize(inWorldNormal);
   
    float3 col;
   
    //World position is used as texture coordinates. Choose which
    //two components of world position to use based on normal. Could
    //optionally use a different texture for each face here as well.
    if(inWorldNormal. x > 0.5)
    {
        col = tex2D(heightMap, inWorldPosition.yz);
    }
   
    if(inWorldNormal. x < -0.5)
    {
        col = tex2D(heightMap, inWorldPosition.yz);
    }
   
    if(inWorldNormal. y > 0.5)
    {
        col = tex2D(heightMap, inWorldPosition.xz);
    }
   
    if(inWorldNormal. y < -0.5)
    {
        col = tex2D(heightMap, inWorldPosition.xz);
    }
   
    if(inWorldNormal. z > 0.5)
    {
        col = tex2D(heightMap, inWorldPosition.xy);
    }
   
    if(inWorldNormal. z < -0.5)
    {
        col = tex2D(heightMap, inWorldPosition.xy);
    }
   
    result = float4(col, 1.0);
}


Basically what happens is that the texture is not drawn and thus I just see a white mass. I am sure the texture works because I've seen it drawn before (albeit all messed up due to screwing up the texture coordinates but that's what this is for). I am having trouble debugging this as it seems to work for someone in the thread mentioned about but the texture isn't showing up. I compared his C++ code with mine and they look to be similar:

Code:
void GraphicsManager::LoadManualObject(PolyVox::SimpleVolume<PolyVox::MaterialDensityPair44>& volData, utils::NoiseMap& heightMap)
{
   float scale = 1.f;
   int widthChunks = heightMap.GetWidth() / chunkSize;
   int heightChunks = heightMap.GetHeight() / chunkSize;
   int depthChunks = 4;

   for(int i = 0; i < heightChunks; i++)
   {
      for(int j = 0; j < widthChunks; j++)
      {
         for(int k = 0; k < depthChunks; k++)
         {
            Vector3DInt32 start(j * chunkSize, k * chunkSize, i * chunkSize);
            Vector3DInt32 end((j + 1) * chunkSize, (k + 1) * chunkSize, (i + 1) * chunkSize);

            SurfaceMesh<PositionMaterialNormal> mesh;
            CubicSurfaceExtractorWithNormals<SimpleVolume, MaterialDensityPair44> surfaceExtractor(&volData, Region(start, end), &mesh);
            surfaceExtractor.execute();

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

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

            ManualObject *obj = manager->createManualObject();
            obj->begin("ColoredCubicVoxel", Ogre::RenderOperation::OT_TRIANGLE_LIST);

            float vecCnt = 0;
            std::vector<PositionMaterialNormal>::iterator vecItr;
            float texX = 0.f, texY = 0.f;
            for(vecItr = vecVertices.begin(); vecItr != vecVertices.end(); vecItr++, vecCnt++)
            {
               PolyVox::Vector3DFloat pos = vecItr->getPosition() * scale;
               pos += Vector3DFloat(j * chunkSize, k * chunkSize, i * chunkSize);
               obj->position(pos.getX(), pos.getY(), pos.getZ());
               obj->normal(vecItr->getNormal().getX(), vecItr->getNormal().getY(), vecItr->getNormal().getZ());
               //obj->textureCoord(vecCnt / vecVertices.size(), vecCnt / vecVertices.size()); //This is commented out because the shader is supposed to handle texture coordinates now
            }

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

            obj->end();

            string strName(str);
            manualObjects[strName] = obj;
            root_sn->attachObject(obj);
         }
         printf("#");
      }
      printf("\n");
   }
}


Can anyone spot where I am missing a link?

I do plan on calculating the normal and such later in the shader after I get something to work.

Thanks for the help so far!


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

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
A pure white material usually means there is an error in the material or shader, and so Ogre uses the material 'BaseWhiteNoLigthting' instead. Are there any warnings, errors, or exceptions in the log?

Failng that, the most effective way to debug shaders is to simplify them until they work. Cut your fragment shader do so that it returns a single colour - does the whole mesh then get displayed with that colour? If so try sampling the texture with hard coded texture coordinates. If that works then try generating texture coordinates to project along a single axis. I know it's tedious, but shader debugging is just a slow task :-(


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Tue Jun 21, 2011 11:24 pm 

Joined: Sat Jun 18, 2011 3:29 am
Posts: 17
Okay, I made some progress but am still not quite there yet. I changed a few syntax (still had ColouredCubicVoxel instead of ColoredCubicVoxel in the .material among other things). I saw the png get mipmap'd so it's definitely loaded. The FPS also dropped in half (was around 200~, now around 100~). It's drawing something but all i see is pure darkness. I do have ambient light turned on and I have a spotlight attached to the camera. I am also printing out physics so I know I landed on the same place I've always landed on (random terrain is off for now, using the same seed for testing).

I was also running in OpenGL and the Ogre crashed when I tried to render a scene. I switched to DirectX (9) and it went away. This happened with InstancedGeometry. I guess ATI doesn't play well with OpenGL.

I am hoping you can take a look at my .material and .cg and see if you can spot something because I've checked with the pasted version in the other thread and I am not noticing anything that I am missing.

ColoredCubicVoxel.material:
Code:
vertex_program VP cg
{
    source ColoredCubicVoxel.cg
    entry_point VP
    profiles vs_3_0 vs_2_x vs_2_0 vs_1_1 vp40 vp30 vp20 arbvp1

    default_params
    {
        param_named_auto world world_matrix
        param_named_auto viewProj viewproj_matrix
    }
}

fragment_program FP cg
{
    source ColoredCubicVoxel.cg
    entry_point FP
    profiles ps_3_x ps_3_0 ps_2_x ps_2_0 ps_1_4 ps_1_3 ps_1_2 ps_1_1 fp40 fp30 fp20 arbfp1
   
    default_params
    {
    }
}

material ColoredCubicVoxel
{
   receive_shadows on
    technique
    {               
        pass
        {                   
            vertex_program_ref VP
            {
            }

            fragment_program_ref FP
            {
            }
         
            texture_unit
            {
                texture Dirt.png 2d
            }       
        }
    }
}


ColoredCubicVoxel.cg:
Code:
void VP(
    float4 inPosition         : POSITION,
    float4 inNormal            : NORMAL,

    out float4 outClipPosition   : POSITION,
    out float4 outWorldPosition   : TEXCOORD0,
    out float4 outWorldNormal   : TEXCOORD1,

    uniform float4x4 world,
    uniform float4x4 viewProj)
{   
    //Compute the world space position
    outWorldPosition = mul(world, inPosition);   
   
    //Just pass though the normals without transforming them in any way. No rotation occurs.
    outWorldNormal = inNormal;

    //Compute the clip space position
    outClipPosition = mul(viewProj, outWorldPosition);
}

void FP(
    float4 inPosition           : POSITION,
    float4 inWorldPosition       : TEXCOORD0,
    float4 inWorldNormal       : TEXCOORD1,

    uniform sampler2D heightMap : TEXUNIT0,
   
    out float4 result           : COLOR)
{   
    inWorldNormal = normalize(inWorldNormal);
   
    float3 col;
   
    //World position is used as texture coordinates. Choose which
    //two components of world position to use based on normal. Could
    //optionally use a different texture for each face here as well.
    if(inWorldNormal.x > 0.5)
    {
        col = tex2D(heightMap, inWorldPosition.yz);
    }
   
    if(inWorldNormal.x < -0.5)
    {
        col = tex2D(heightMap, inWorldPosition.yz);
    }
   
    if(inWorldNormal.y > 0.5)
    {
        col = tex2D(heightMap, inWorldPosition.xz);
    }
   
    if(inWorldNormal.y < -0.5)
    {
        col = tex2D(heightMap, inWorldPosition.xz);
    }
   
    if(inWorldNormal.z > 0.5)
    {
        col = tex2D(heightMap, inWorldPosition.xy);
    }
   
    if(inWorldNormal.z < -0.5)
    {
        col = tex2D(heightMap, inWorldPosition.xy);
    }
   
    result = float4(col, 1.0);
}


I am also using this picture as Dirt.png right now because I wanted something that stands out.

Image

Thanks for all your help!

Edit: I also did try to simplify FP in the .cg. I did something like:
Code:
void FP(
    float4 inPosition           : POSITION,
    float4 inWorldPosition       : TEXCOORD0,
    float4 inWorldNormal       : TEXCOORD1,

    uniform sampler2D heightMap : TEXUNIT0,
   
    out float4 result           : COLOR)
{   
    inWorldNormal = normalize(inWorldNormal);
   
       float3 col;
   col = float3(0.5, 0.5, 0.5);
    result = float4(col, 1.0);
}


And it still displayed nothing. At least I've made progress though!

Edit 2: I just tried using another .png and even tried changing its size from 256x256 to 16x16 and the same thing happens. All of these are taken from the Ogre directory.

Edit 3: I just ran something basic like described in this article: http://www.ogre3d.org/tikiwiki/Getting+Started+With+Ogre+CG+Materials&structure=Cookbook and it is still showing up as black. This is really strange...


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Wed Jun 22, 2011 7:58 am 

Joined: Sat Jun 18, 2011 3:29 am
Posts: 17
My previous post was too long so I decided to double post to make it clearer.

I've made a lot of progress and is only missing one final part.

Here is my new .cg that has worked so far:
Code:
void voxeltexture_vp(
   float4 inPosition         : POSITION,
   float4 inNormal            : NORMAL,

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

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

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

   out float4 color         : COLOR,

   uniform sampler2D texture)
{
   inWorldNormal = normalize(inWorldNormal);

    color = tex2D(texture, inWorldPosition.yz);
   
}


There are several things I want to note:

1. In David Williams' original .cg, it was uniform sampler2D [name] : TEXUNIT0
2. In David Williams' original .cg, under "void voxeltexture_fp" there was another parameter: float4 inPosition : POSITION. This is never referenced inside the FP itself so I didn't keep it.
3. In David Williams' original .cg, he created a float3 named col and used it to store the result of tex2D, and then returned a float4 with (col, 1.0).
4. I am aware that this displays the faces wrong. I'll explain why below.

Here is the intended code. However, Ogre crashes as soon as I add these conditions using inNormal. Ogre log part of this will be pasted after the code.
Code:
void voxeltexture_vp(
   float4 inPosition         : POSITION,
   float4 inNormal            : NORMAL,

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

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

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

   out float4 color         : COLOR,

   uniform sampler2D texture)
{
   inWorldNormal = normalize(inWorldNormal);

    if(inWorldNormal.x > 0.5)
    {
        color = tex2D(texture, inWorldPosition.yz);
    }
   
    if(inWorldNormal.x < -0.5)
    {
        color = tex2D(texture, inWorldPosition.yz);
    }
   
    if(inWorldNormal.y > 0.5)
    {
        color = tex2D(texture, inWorldPosition.xz);
    }
   
    if(inWorldNormal.y < -0.5)
    {
        color = tex2D(texture, inWorldPosition.xz);
    }
   
    if(inWorldNormal.z > 0.5)
    {
        color = tex2D(texture, inWorldPosition.xy);
    }
   
    if(inWorldNormal.z < -0.5)
    {
        color = tex2D(texture, inWorldPosition.xy);
    }
}


Here is the Ogre log part:
Code:
02:49:19: OGRE EXCEPTION(3:RenderingAPIException): Cannot assemble D3D9 shader VoxelTexture_FP Errors:
C:\Users\Aura\Documents\Personal Projects\TechDemo\MageGameTechDemo\Debug\memory(29,1): error X5204: Read of uninitialized components(*) in r2: *r/x/0 *g/y/1 *b/z/2 *a/w/3
 in D3D9GpuProgram::loadFromSource at ..\..\..\..\..\RenderSystems\Direct3D9\src\OgreD3D9GpuProgram.cpp (line 202)


Does anyone know why this is happening?

I am going to post this on the Ogre forum as well since this isn't PolyVox's doing. I'll update when I get a solution (or not if someone finds out here). This should be helpful for anyone who is looking to do something similar.

Edit: The thread on the Ogre forum: http://www.ogre3d.org/forums/viewtopic.php?f=2&t=65310

Edit 2: Turns out that it is crashing because CubicSurfaceExtractorWithNormals doesn't provide surface normals, only vertex normals. It is better to go with CubicSurfaceExtractor and calculate the surface normals in the shader myself.

What I found is this on PolyVox's wiki: http://thermite3d.org/dokuwiki/computing_normals_in_a_pixel_shader
Specifically:
Code:
float3 worldNormal = cross(ddy(inWorldPosition.xyz), ddx(inWorldPosition.xyz));
worldNormal = normalize(worldNormal);


I slapped that in and changed all the checks to check worldNormal instead of inWorldNormal and it is still crashing because worldNormal is blank after that.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Wed Jun 22, 2011 7:10 pm 

Joined: Sat Jun 18, 2011 3:29 am
Posts: 17
Okay made huge progress but still have a few clinks to work through. The image displays now according to the normal but the direction of it is not what I want.

First off, my .cg and .material for those who are curious:

VoxelTexture.cg
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, inWorldPosition.yz + VOXELCENTEROFFSET);
    }
   //Left
   if(worldNormal.x < -0.5)
    {
        color = tex2D(texture, inWorldPosition.yz + VOXELCENTEROFFSET);
    }
   //Top
    if(worldNormal.y > 0.5)
    {
        color = tex2D(texture, inWorldPosition.xz + VOXELCENTEROFFSET);
    }
   //Bottom
    if(worldNormal.y < -0.5)
    {
        color = tex2D(texture, inWorldPosition.xz + VOXELCENTEROFFSET);
    }
   //Front
    if(worldNormal.z > 0.5)
    {
        color = tex2D(texture, inWorldPosition.xy + VOXELCENTEROFFSET);
    }
   //Back
    if(worldNormal.z < -0.5)
    {
        color = tex2D(texture, inWorldPosition.xy + VOXELCENTEROFFSET);
    }
}

And my VoxelTexture.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 ps_2_x ps_2_0
}

material VoxelTexture
{
   technique
   {
      pass
      {
         vertex_program_ref VoxelTexture_VP
         {
         }
         
         fragment_program_ref VoxelTexture_FP
         {
         }
         
         texture_unit
         {
            texture Dirt.png 2d
         }
      }
   }
}


Now, I color coded the faces as such:
Yellow: front (facing you, all the rest of the faces are described assuming you are in front of the yellow face)
Green: back
Purple: left
Right: right
Blue: top
You can't see bottom because I haven't added any overhang or any of that yet and I don't have the ability to place blocks atm.

Here are some pictures:

Image

Image

Image

The orientation are not what I want. I would prefer that all the side faces would face the same way. So for example in this picture it would draw [10] faced like that across all side faces. I am not sure what I'll do for top and bottom.

My question is: how would I handle this? Do I handle this in the shader or in C++? In addition, when the directions would inevitably make its way in the code, what about that and how does that affect this? Specifically, there may be blocks where one of the side faces (most likely front, maybe even back) will be different. In addition, some textures may involve alpha of a certain color so that you can see through parts of it (glass for example).

Edit: To be more specific, there are possibly multiple scenarios:
Note: All side orientation should be the same.
1. Regular block (i.e., dirt and sand in Minecraft). Do not care about its direction and top/bottom.
2. Regular block with a different top (i.e., grass in Minecraft). The top should be different.
3. A directional block (i.e., furnace in Minecraft). The face (and possibly the back) facing you should be different.
4. A partially see-through block that looks like a block (i.e., glass in Minecraft). Part of the block should be transparent.
5. A partially see-through block that doesn't look like a block (i.e., weed/sugarcane in Minecraft). The diagonal of the cube are utilized and a texture is drawn on each diagonal. Part of that texture is transparent.
6. Fluid? Not even sure about this one.
7. Moving blocks like minecarts?

Another question: do I still need the vertex normals? How would I generate these myself in the shader?


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Wed Jun 22, 2011 8:50 pm 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
Great, looks like you are making progress :-) I'm only going to answer the questions in your last post because I guess you've worked through the earlier ones?

AuraofMana wrote:
The orientation are not what I want. I would prefer that all the side faces would face the same way. So for example in this picture it would draw [10] faced like that across all side faces. I am not sure what I'll do for top and bottom.


You can either rotate/flip the textures in (e.g. in Photoshop) or you can change the way the texture coordinates are generated. E.g Change:

Code:
color = tex2D(texture, inWorldPosition.yz + VOXELCENTEROFFSET);


to:

Code:
color = tex2D(texture, inWorldPosition.zy + VOXELCENTEROFFSET);


Or you could make one of the components negative if you need.

AuraofMana wrote:
Edit: To be more specific, there are possibly multiple scenarios:
Note: All side orientation should be the same.
1. Regular block (i.e., dirt and sand in Minecraft). Do not care about its direction and top/bottom.
2. Regular block with a different top (i.e., grass in Minecraft). The top should be different.
3. A directional block (i.e., furnace in Minecraft). The face (and possibly the back) facing you should be different.


I haven't really experimented with this, but I would imagine you could do it by using the normal to decide which texture to sample. Maybe pack six textures into one and compute a index from the normal. But it looks like you've done this already - at least you have a different colour on each face?


AuraofMana wrote:
4. A partially see-through block that looks like a block (i.e., glass in Minecraft). Part of the block should be transparent.


There is currently no support for transparent blocks. You could render a face transparent but then there is nothing behind it. It will come eventually, but for now you will have to implement it yourself by modifying the CubicSurfaceExtractor.

Edit: Check this link: viewtopic.php?f=14&t=219

AuraofMana wrote:
5. A partially see-through block that doesn't look like a block (i.e., weed/sugarcane in Minecraft). The diagonal of the cube are utilized and a texture is drawn on each diagonal. Part of that texture is transparent.


I doubt if this is even a block - it's probably just a mesh which is handled seperatly and just drawn at the right position. You probably need a custom voxel type which treats the appropriate materialID as empty space, and then just draw the mesh yourself.

AuraofMana wrote:
6. Fluid? Not even sure about this one.

The animation of fluid voxels is outside the scope of PolyVox. You update the voxels, PolyVox just create the mesh. But it has the same problem as glass in terms of transparency.

AuraofMana wrote:
7. Moving blocks like minecarts?


Again, I doubt if these are even blocks. They are just models in the world.

AuraofMana wrote:
Another question: do I still need the vertex normals? How would I generate these myself in the shader?


You cannot generate vertex normals in the shader. You probably don't need them anyway if you are creating fragment normals in the fragment shader. The only exception would be if you wanted vertex normals available in the vertex shader, because at this point the fragment shader has not yet been run.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Wed Jun 22, 2011 10:39 pm 

Joined: Sat Jun 18, 2011 3:29 am
Posts: 17
David Williams wrote:
You can either rotate/flip the textures in (e.g. in Photoshop) or you can change the way the texture coordinates are generated. E.g Change:

Code:
color = tex2D(texture, inWorldPosition.yz + VOXELCENTEROFFSET);


to:

Code:
color = tex2D(texture, inWorldPosition.zy + VOXELCENTEROFFSET);


Or you could make one of the components negative if you need.


I ended up doing it in the shader and it all works :D ! Here is my .cg if anyone is interested:
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.0)
    {
      float4 col;
        col = tex2D(texture, float2((1 - inWorldPosition.z) + VOXELCENTEROFFSET, (1 - inWorldPosition.y) + VOXELCENTEROFFSET));
      color = col + float4(1.0, 0.0, 0.0, 0.0);
    }
   //Left
   if(worldNormal.x < 0.0)
    {
      float4 col;
        col = tex2D(texture, float2(inWorldPosition.z + VOXELCENTEROFFSET, (1 - inWorldPosition.y) + VOXELCENTEROFFSET));
      color = col + float4(1.0, 0.0, 1.0, 0.0);
    }
   //Top
    if(worldNormal.y > 0.0)
    {
        color = tex2D(texture, inWorldPosition.xz + VOXELCENTEROFFSET);
    }
   //Bottom
    if(worldNormal.y < 0.0)
    {
        color = tex2D(texture, float2((1 - inWorldPosition.x) + VOXELCENTEROFFSET, inWorldPosition.z + VOXELCENTEROFFSET));
    }
   //Front
    if(worldNormal.z > 0.0)
    {
        color = tex2D(texture, float2(inWorldPosition.x + VOXELCENTEROFFSET, (1 - inWorldPosition.y) + VOXELCENTEROFFSET));
    }
   //Back
    if(worldNormal.z < 0.0)
    {
      float4 col;
        col = tex2D(texture, float2((1 - inWorldPosition.x) + VOXELCENTEROFFSET, (1 - inWorldPosition.y) + VOXELCENTEROFFSET));
      color = col + float4(0.0, 1.0, 0.0, 0.0);
    }
}


Now I am getting some graphics weirdness. I am not just using CubicSurfaceExtractor with PositionMaterial. This seems like a lighting problem. I am not sure what these are called. How would I go about fixing these?

Here are some pics of what I am talking about:

Image

Image

If you look carefully you can see black marks.

Here is my .material, maybe I shouldn't be using anisotropic filtering?
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
         }
      }
   }
}


Edit: This picture really shows it:
Image

It only seems to appear in these lines it seems. Maybe it's because these are the border between chunks? I'll have to talk to my partner who is handling this. He's not online right now but I'll come back with more info soon but if you know exactly what is wrong that would be great too. Thanks! Edit: turns out he doesn't know anything about this >_>

Edit 2: Another question: right now I am using MaterialDensityPair44 and I am not really setting the data for the material so it stays 0 but I set density as maxDensity. Why is it that when I change it to Material<unsigned_int> the object is gone (the maxDensity then would be 2)? What happens is I don't see anything and I keep falling so I can only assume the ManualObject is simply not there. I did not change anything besides this. I literally set up a typedef and swap between to make sure.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: PolyVox and a Minecraft-esque Game
PostPosted: Thu Jun 23, 2011 6:12 pm 

Joined: Sat Sep 18, 2010 9:45 pm
Posts: 189
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.

As for the density thing, look at the classes for Material<type> and MaterialDensityPair. For Material, the density is assumed to be a constant predefined value. The idea behind this is to give full precision for materials because you assume material 0 to be air and everything greater than 0 to be solid. That is, there are only be two density states, non-solid or solid. For example, let's say you use Material<uint_t> and we assume zero to be air. To do a comparing you would just do if (getMaterial() >= getThreshold()) { okay I'm solid!}

MaterialDensityPair on the other hand allows for controlling precision for both material and density. So for something like MaterialDensityPair44, you have 4 bits each for material and density, so 16 possible values for each.


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

All times are UTC


Who is online

Users browsing this forum: No registered users and 4 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