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

The best way to deals with "direct" color as a material.
http://www.volumesoffun.com/phpBB3/viewtopic.php?f=14&t=617
Page 1 of 1

Author:  arthuro [ Wed Oct 29, 2014 12:35 pm ]
Post subject:  The best way to deals with "direct" color as a material.

First, I would like to thanks the authors of this library. It is very well refined.

I have a question.
I want to use the marching cube algorithm of Polyvox with material that are simply a color.

Thus I use materialDensityPair<uint32_t,8*4,8> to be my VoxelType.
The material codes the color with the following convention : 0xRRGGBBAA

Here is what I get :
Image

My problem is that polyvox don't assign the same material to vertices that are on the same location.
You can see on this picture some points where there is a color discontinuity.

I would like some advices to get smooth colors. In a more general way, how do deals with color?

Thanks to everyone that could give some answers.


(ps: I'm french, so some of my english sentences may be weird, sorry)

Author:  petersvp [ Wed Oct 29, 2014 10:21 pm ]
Post subject:  Re: The best way to deals with "direct" color as a material.

In Crafterria, we solved this glitch by using 3D textures.

Generate a 3D texture with your color data and just sample it into your shader.
You can use the alpha channel for something other than translucency, for example, to store light information.

for texture splatting, you are limited to 4 materials per pass - store them in the R,G,B,A channels and use multipass rendering. Check my topic in Showcase.

Author:  David Williams [ Thu Oct 30, 2014 9:19 am ]
Post subject:  Re: The best way to deals with "direct" color as a material.

I haven't actually worked with pure colors in conjunction with the marching cubes surface extractor, but in principle it should work. Firstly though, are you using the last release of PolyVox (0.2.1) or the latest develop version from Git? What I say below applies to the develop version. You may be able to adjust it for the last stable release but I'm a bit hazy as to exactly what has changed.

Anyway, a key issue will be the way that the vertex's color/material is chosen based on it's neighbours. A vertex is always positioned between two voxels and gets it color/material by sampling them. You can see this in the code:

Code:
// Allow the controller to decide how the material should be derived from the voxels.
const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v100, fInterp);


Now, most people use PolyVox with 'material IDs', and in general there is no sensible way to blend between them. The default implementation just picks one based on the density:

Code:
MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> blendMaterials(MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> a, MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> b, float /*weight*/)
{
   if(convertToDensity(a) > convertToDensity(b))
   {
      return a;
   }
   else
   {
      return b;
   }
}


But if you have colors then you *can* blend between then. To test, you can probably do this by editing the function above (found in MateriaDensityPair.h). Something like:

Code:
MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> blendMaterials(MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> a, MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> b, float /*weight*/)
{
   // Untested pseudocode!
   MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> result;
   result.Red = (a.Red + b.Red) / 2.0 // Note: Probably convert to floats first?
   result.Green = ...
   result.Blue = ...
   return result;
}


If you can get this to work then later you can make a proper 'Color' voxel type by duplicating MaterialDensityPair and modifying it to your needs.

@petersvp - I think this is different to your problem because colors can be interpolated whereas material IDs cannot. But I'm not certain... let's see what happens.

Author:  arthuro [ Fri Oct 31, 2014 1:02 am ]
Post subject:  Re: The best way to deals with "direct" color as a material.

Thanks you for yours answers.

I am trying your answers David. I think it is exactly what I wanted.
I am going to implement my color voxel type and test it.
I will give you feedback and my code when it will be done.
Thanks you again.

Author:  petersvp [ Fri Oct 31, 2014 12:55 pm ]
Post subject:  Re: The best way to deals with "direct" color as a material.

My way have a benefit - it does not care about vertices. It only needs their positions. Single triangle may end up with many than three colors. And interpolation is made in hardware rather than in software.
Decimating the mesh and rendering it this way preserves the color information. So everything with its pros and cons.
3D textures are ultimate solution for the problem with vertex attributes. Attributes are there, but not on vertices (as we only use vertex position).

Drawback is that 3D the textures approach requires way too much texture memory than vertex-based approach, but if used with care, it's not a real problem.

Author:  David Williams [ Fri Oct 31, 2014 1:25 pm ]
Post subject:  Re: The best way to deals with "direct" color as a material.

So just to be clear (for arthuro) you are suggesting that he can upload his color volume data to the GPU as a 3D texture, generate the mesh as usual using PolyVox, and then write a fragment program which colors the fragment by using the fragment's interpolated position as a 3D texture coordinate for the texture which was uploaded? This is indeed another possible solution, and as you say there are trade-offs with each approach.

Author:  arthuro [ Sat Nov 01, 2014 12:51 pm ]
Post subject:  Re: The best way to deals with "direct" color as a material.

Thanks,
Yes a 3D textures is also a good solution. Especially for the project I am actually working on.

Anyway, I have tried David's solution and it's work well.
I install de development version and translate my actual engine.

This is my actual marchingCubeController:
Code:
#include "utils/glm.hpp"
#include "PolyVoxCore/MaterialDensityPair.h"
#include "PolyVoxCore/Mesh.h"
#include "PolyVoxCore/Vertex.h"

typedef PolyVox::MaterialDensityPair<uint32_t, 8*4, 8> Voxel;
typedef PolyVox::Mesh<PolyVox::Vertex<Voxel>,uint32_t> Mesh;

namespace PolyVox
{
    template<>
    class DefaultMarchingCubesController<Voxel>
    {
    public:
        typedef uint8_t DensityType;
        typedef uint32_t MaterialType;

        DefaultMarchingCubesController(void)
        {   
        }
        DensityType convertToDensity(Voxel voxel)
        {
            return voxel.getDensity();
        }
        //MaterialType convertToMaterial(Voxel voxel)
        //{
            //return voxel.getMaterial();
        //}

        Voxel blendMaterials(Voxel a, Voxel b, float weight)
        {
            MaterialType m1 = a.getMaterial();
            MaterialType m2 = b.getMaterial();

            uint32_t d1 = a.getDensity();
            uint32_t d2 = b.getDensity();
           
            float cWeight = (d2*weight+1.0)/(d1*(1.0-weight)+d2*weight+1.0);
            //cWeight = weight;

            float a1 = m1&0xFF; m1>>=8;
            float b1 = m1&0xFF; m1>>=8;
            float g1 = m1&0xFF; m1>>=8;
            float r1 = m1&0xFF; m1>>=8;

            float a2 = m2&0xFF; m2>>=8;
            float b2 = m2&0xFF; m2>>=8;
            float g2 = m2&0xFF; m2>>=8;
            float r2 = m2&0xFF; m2>>=8;

           
            uint8_t cr = r1*(1.0-cWeight)+r2*cWeight ;           
            uint8_t cg = g1*(1.0-cWeight)+g2*cWeight ;           
            uint8_t cb = b1*(1.0-cWeight)+b2*cWeight ;           
            uint8_t ca = a1*(1.0-cWeight)+a2*cWeight ;           

            MaterialType m = ca + (cb<<8) + (cg<<16) + (cr<<24);

            return Voxel(
                    m,
                    d1*(1.0-weight)+
                    d2*weight
            );
        }

        DensityType getThreshold(void)
        {
            return 128;
        }

    private:
        uint8_t m_tThreshold;
    };
}


Here is an image without and with this controller.
The vertices color are now smooth.
I don't explain why, but the mesh geometry is also smoother (So I am happy). Does anyone know why ?
On this picture, I only use 2 color : white and red.
Image
The image is more beautifull if I use a pencil that don't assign directly a color(red) and a density but use an interpolation with the previous Voxel.

Author:  David Williams [ Mon Nov 03, 2014 9:02 pm ]
Post subject:  Re: The best way to deals with "direct" color as a material.

Great, I'm really glad it worked for you. As for the improved smoothness, the shape of the mesh is completely determined by the density values. In your original version were you using some of the density bits to store the color, or using less density bits? Actually I'm not exactly sure why it is different but I'm glad it's working for you :-)

Author:  arthuro [ Tue Nov 04, 2014 1:04 pm ]
Post subject:  Re: The best way to deals with "direct" color as a material.

Thanks you again.

In the both case, I use:
PolyVox::MaterialDensityPair<uint32_t, 8*4, 8>
to be my VoxelType. Thus I allocate the same amount (8) of bits for the density.

I just use a specialized version DefaultMarchingCubesController<Voxel> that implement:
Voxel blendMaterials(Voxel a, Voxel b, float weight)

On the image, the only difference is the use of this class or not.
So it is strange.

Anyway, It works very well, thanks you.

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