It is currently Sat Aug 22, 2020 3:36 am


All times are UTC




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Question about material ids and marching cubes
PostPosted: Mon Apr 21, 2014 2:57 pm 

Joined: Tue Apr 08, 2014 5:10 pm
Posts: 124
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 10265 times ]


Attachment:
mids2.jpg
mids2.jpg [ 57.12 KiB | Viewed 10265 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;
}



Top
Offline Profile  
Reply with quote  
 Post subject: Re: Question about material ids and marching cubes
PostPosted: Tue Apr 22, 2014 6:37 pm 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
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.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Question about material ids and marching cubes
PostPosted: Wed Apr 23, 2014 2:53 pm 

Joined: Tue Apr 08, 2014 5:10 pm
Posts: 124
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.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Question about material ids and marching cubes
PostPosted: Thu Apr 24, 2014 3:10 pm 

Joined: Tue Apr 08, 2014 5:10 pm
Posts: 124
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 10242 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


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Question about material ids and marching cubes
PostPosted: Fri Apr 25, 2014 8:19 am 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
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.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Question about material ids and marching cubes
PostPosted: Fri Apr 25, 2014 10:08 am 

Joined: Tue Apr 08, 2014 5:10 pm
Posts: 124
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.


Top
Offline Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC


Who is online

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