Volumes Of Fun
http://www.volumesoffun.com/phpBB3/

Question about material ids and marching cubes
http://www.volumesoffun.com/phpBB3/viewtopic.php?f=2&t=584
Page 1 of 1

Author:  petersvp [ Mon Apr 21, 2014 2:57 pm ]
Post subject:  Question about material ids and marching cubes

I am experimenting with the material ids now.

with cubic extractor I don't have problems, but with the MArching Cubes I get somehow non-perfectly-smooth result. How can I fix that?

Attachment:
mids.jpg
mids.jpg [ 53.19 KiB | Viewed 10266 times ]


Attachment:
mids2.jpg
mids2.jpg [ 57.12 KiB | Viewed 10266 times ]


Useful snippets:
Code:
SVT& SVT::operator +(const SVT &other)
{
    if(this->material==0) this->material = other.material;
    this->density += other.density;
    return *this;
}

SVT& SVT::operator -(const SVT &other)
{
    if(this->material==0) this->material = other.material;
    this->density -= other.density;
    return *this;
}

SVT& SVT::operator /(const int &other)
{
    this->density /= other;
    return *this;
}
/**/

SVT& SVT::operator +=(const SVT &other)
{
    if(this->material==0) this->material = other.material;
    this->density += other.density;
    return *this;
}

SVT& SVT::operator -=(const SVT &other)
{
    if(this->material==0) this->material = other.material;
    this->density -= other.density;
    return *this;
}

SVT& SVT::operator /=(const int &other)
{
    this->density /= other;
    return *this;
}
...
            //Smooth chunk

            RawVolume<SVT> tempVolume(Region(-1,-1,-1,c->sx+1,c->sy+1,c->sz+1));
            LowPassFilter< RawVolume<SVT>, RawVolume<SVT>, SVT >
                    lpf(c->voxdata,     Region(-1,-1,-1,c->sx+1,c->sy+1,c->sz+1),
                        &tempVolume,    Region(-1,-1,-1,c->sx+1,c->sy+1,c->sz+1),
                    3);
            lpf.execute();


            MarchingCubesSurfaceExtractor< RawVolume<SVT>, PGFMarchingCubesController >
                    ext2(&tempVolume, Region(0,0,0,c->sx,c->sy,c->sz), c->newmesh);
            ext2.execute();
...
                for(uint32_t i = 0; i < vertices.size(); i++)
                {
                    const PolyVox::PositionMaterialNormal& vertex = vertices.at(i);
                    const MaterialAlpha& ma = vertex_extra_data.at(i);
                    PolyVox::Vector3DFloat vertex_pos = vertex.getPosition();
                    no->position(vertex_pos.getX(), vertex_pos.getY(), vertex_pos.getZ());
                    no->normal(vertex.getNormal().getX(), vertex.getNormal().getY(),  vertex.getNormal().getZ());
                                        Ogre::Vector4 color;
                    int mid = vertex.getMaterial();
                    switch(mid)
                    {
                            case   0:   color =    Ogre::Vector4(   0   ,   0   ,   0   ,   0   );   break;
                            case   1:   color =    Ogre::Vector4(   0   ,   0   ,   0   ,   1   );   break;
                            case   2:   color =    Ogre::Vector4(   0   ,   0   ,   1   ,   0   );   break;
                            case   3:   color =    Ogre::Vector4(   0   ,   0   ,   1   ,   1   );   break;
                            case   4:   color =    Ogre::Vector4(   0   ,   1   ,   0   ,   0   );   break;
                            case   5:   color =    Ogre::Vector4(   0   ,   1   ,   0   ,   1   );   break;
                            case   6:   color =    Ogre::Vector4(   0   ,   1   ,   1   ,   0   );   break;
                            case   7:   color =    Ogre::Vector4(   0   ,   1   ,   1   ,   1   );   break;
                            case   8:   color =    Ogre::Vector4(   1   ,   0   ,   0   ,   0   );   break;
                            case   9:   color =    Ogre::Vector4(   1   ,   0   ,   0   ,   1   );   break;
                            case   10:   color =    Ogre::Vector4(   1   ,   0   ,   1   ,   0   );   break;
                            case   11:   color =    Ogre::Vector4(   1   ,   0   ,   1   ,   1   );   break;
                            case   12:   color =    Ogre::Vector4(   1   ,   1   ,   0   ,   0   );   break;
                            case   13:   color =    Ogre::Vector4(   1   ,   1   ,   0   ,   1   );   break;
                            case   14:   color =    Ogre::Vector4(   1   ,   1   ,   1   ,   0   );   break;
                            case   15:   color =    Ogre::Vector4(   1   ,   1   ,   1   ,   1   );   break;
                    }
                    no->colour(color.x,color.y,color.z,color.w);
...

Shaders:

struct vsout
{
   float4 op: POSITION;    // Transformed vertex position
   float3 uv: TEXCOORD0;    // UV0
   float3 nm: TEXCOORD1;
   float4 cl: COLOR;
};

vsout vert(
        // Vertex Inputs
        float4 position     : POSITION,    // Vertex position in model space
        float3 texCoord0    : TEXCOORD0,   // Texture UV set 0
      float3 normal       : NORMAL, 
      float4 color      : COLOR,
        // Model Level Inputs
        uniform float4x4 WVPMAT
)
{
   vsout o;
   float4 p = mul(WVPMAT, position);
   o.op = p;
   o.nm = normal;
    o.uv = position.xyz /1 * float3(-1,1,1) + 0.5;
   o.cl = color;
   return o;
}

void frag(
        // Pixel Inputs
        float3 pos        : TEXCOORD0,   // UV interpolated for current pixel
      float3 vnormal    : TEXCOORD1,      
      float4 col        : COLOR,      // the encoded material id
 
        // Outputs
        out float4 color    : COLOR,    // Output color we want to write
 
        // Model Level Inputs
        uniform sampler2D texture)        // Texture we're going to use
{
   color = col - (1-pos.z/70)+0.4;
}


Author:  David Williams [ Tue Apr 22, 2014 6:37 pm ]
Post subject:  Re: Question about material ids and marching cubes

I think that multiple materials with Marching Cubes does not have a simple solution. The problem here is that each voxel has a single material, but vertices are placed between voxels. How should the material of the vertex be decided? Taking the average doesn't make sense, but taking the maximum is one option (though it's not clear that it's correct).

I think you need to consider which values you assign to voxels, what threshold you use, how you compute a vertices' material from the materials of the surrounding voxels, and how you use these material ID's in the shader. Actually I don't have an exact answer here, but look at the MarhcingCubesController and the comments in it.

You might also find this interesting, though it's old and I'm not sure I still agree with the solution I proposed. It explains the problem though: http://books.google.com/books?id=WNfD2u8nIlIC&lpg=PR1&dq=game%20engine%20gems&pg=PA39#v=onepage&q&f=false

In Cubiquity we have a more complex and powerful approach, where we store several material ID's with each voxel and also with each vertex. This gives more flexibility with controlling the blending, but at the moment the code is on a seperate branch of PolyVox. We'll try to merge it across once Cubiquity is released.

You might also find it looks better when you are blending textures rather than solid colors.

Author:  petersvp [ Wed Apr 23, 2014 2:53 pm ]
Post subject:  Re: Question about material ids and marching cubes

I think that I will try with 3D texture containing color-encoded material IDs and sampling it in the Pixel shader, then based on color differences between passed tex coords and snapped tex coords the blending factor will be applied. This will be limited to 16 materials, but will not be so perfect.
We don't need material IDs in the vertex declarations AT ALL in this case :)

I already tried with similar solution, encoding blend factors in 3D Texture's RGBA, but this had limit of 4 materials, which is not a solution (I need at least 15 materials to be happy), So I will now play with encoding at least 16 materials this way. Hope I won't hit the Shader Model Limitations with this approach - and conditional branching is huge bottleneck to be work-arounded.

About the textures, they looked so terrible and "teethy" like these control colors. Going with 3D Textures now. One chunk is 16x16x128 so I feel like 100 3D Textures won't be so big bottleneck. Or they will? I have to test.

Author:  petersvp [ Thu Apr 24, 2014 3:10 pm ]
Post subject:  Re: Question about material ids and marching cubes

The implementation with 16 materials is impossible and VERY slow. So I ended up with my 4-materials approach and multi-passing.

This is the result after applying 3D texture lookup - definitely smooth :)

Now I will make multi-pass implementation, a pass can only render 4 materials.

Attachment:
multicolor.jpg
multicolor.jpg [ 213.73 KiB | Viewed 10243 times ]


This is the CG Fragment shader I use:

Code:
void frag(
        // Pixel Inputs
        float3 Position        : TEXCOORD0,   // UV interpolated for current pixel
      float4 VertexNormal      : TEXCOORD1,      
      float4 col            : COLOR,
      float4 ps,
 
        // Outputs
        out float4 color    : COLOR
)     
{
   //two samplers
   float4 mids = tex3D(tx3d, Position);
   
   float scale = 8;
   float4 m0 = tex2D(tex1, Position*scale);
   float4 m1 = tex2D(tex2, Position*scale);
   float4 m2 = tex2D(tex3, Position*scale);
   float4 m3 = tex2D(tex4, Position*scale);
   
   color = m0*mids.x + m1*mids.y + m2*mids.z + m3*mids.w;
   
   return;
}


The algorithm is simple: you have N passes, a pass for 4 materials. If you have 6 materials, you need 2 passes.

For each pass you make a volume texture, RGBA, every channel is blend weight.

You must only use colors: (1,0,0,0), (0,1,0,0), (0,0,1,0), (0,0,0,1).
Materials that does not belong to this pass must be set to (0,0,0,0).

First pass fills everything, next passes must blend with previous pass's result.

The algorighm is memory-intensive as we have (passes/4) count of volume textures.
I am optimizing this per chunk - if a chunk have only 3 materials, I render them in one pass only - In Ogre 3D, I am generating material per chunk.

Vertex shader does nothing.
NO material IDs are needed in the resulting mesh, they are interpolated in the volume texture. Interpolation is not breaking anything as we have alpha-peer-channel.

Hope this technique helps anybody.

Image

p.s. please add some plugin to not break layout on img

Author:  David Williams [ Fri Apr 25, 2014 8:19 am ]
Post subject:  Re: Question about material ids and marching cubes

Very interesting! If I understand you correctly then you are using the RGBA channels of the 3D textures to encode the presence of up to four different materials? This means that each material is interpolated separately and so you get the smooth blending?

If the above is correct then this is conceptually similar to what we do in Cubiquity, except that we store all four material 'strengths' as RGBA components of a vertex color (rather than as a single maerial id). Again they are then interpolated separately. But this more flexible vertex format is what we added to the Cubiquity branch of PolyVox and which should be merged across to the main branch in the future.

Anyway, it's good to see that it is working well for you.

Author:  petersvp [ Fri Apr 25, 2014 10:08 am ]
Post subject:  Re: Question about material ids and marching cubes

Exactly. Overusing the Hardware interpolation of 3D textures.

Code:
float4 mids = tex3D(tx3d, Position);

This line gets the interpolated color. Which means - interpolated material alphas :)
Because Source Colors are only 1000, 0100, 0010, 0001, and... 0000 for materials not intended to be drawn on current pass

Then I sample the 4 material textures:
Code:
   float4 m0 = tex2D(tex1, Position*scale);
   float4 m1 = tex2D(tex2, Position*scale);
   float4 m2 = tex2D(tex3, Position*scale);
   float4 m3 = tex2D(tex4, Position*scale);


... and multiply them by the interpolated alphas
Code:
   color = m0*mids.x + m1*mids.y + m2*mids.z + m3*mids.w;


Well, however, this is NOT a triplanar texturing :) But once we have a way to seamlessly blend materials based on 3D Texture with material IDs, triplanar texturing is no longer a problem.

Quote:
should be merged across to the main branch in the future

I hope you merge back soon.

The only drawback of my approach is the memory usage - maintaining n 3D textures per chunk, where n = MaterialCount / 4. Plus, I will make additional one 3D texture that holds Light level and possibly other things.

Plus a 2D texture for biome / climate lookup.

Page 1 of 1 All times are UTC
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/