Unity3d 着色器中的3D纹理仿真(与子像素相关)

Unity3d 着色器中的3D纹理仿真(与子像素相关),unity3d,glsl,hlsl,cg,Unity3d,Glsl,Hlsl,Cg,我正在做一个Unity3D项目,它暂时依赖于3D纹理 问题是,Unity只允许专业用户使用Texture3D。因此,我正在寻找Texture3D的替代品,可能是一种一维纹理(尽管在Unity中本机不可用),在着色器中被解释为三维纹理(使用3D纹理) 在(最好)保留亚像素信息的同时,有没有办法做到这一点 (添加GLSL和Cg标签是因为问题的核心在这里) 编辑:问题也在此处解决: 但是,这项工作尚未完成并正常工作 编辑:目前我忽略了适当的亚像素信息。因此,任何有关将2D纹理转换为包含3D信息的帮助都

我正在做一个Unity3D项目,它暂时依赖于3D纹理

问题是,Unity只允许专业用户使用Texture3D。因此,我正在寻找Texture3D的替代品,可能是一种一维纹理(尽管在Unity中本机不可用),在着色器中被解释为三维纹理(使用3D纹理)

在(最好)保留亚像素信息的同时,有没有办法做到这一点

(添加GLSL和Cg标签是因为问题的核心在这里)

编辑:问题也在此处解决: 但是,这项工作尚未完成并正常工作

编辑:目前我忽略了适当的亚像素信息。因此,任何有关将2D纹理转换为包含3D信息的帮助都将不胜感激

编辑:我收回了我自己的答案,因为这还不够:

    float2 uvFromUvw( float3 uvw ) {
        float2 uv = float2(uvw.x, uvw.y / _VolumeTextureSize.z);
        uv.y += float(round(uvw.z * (_VolumeTextureSize.z - 1))) / _VolumeTextureSize.z;
        return uv;
    }
初始化为Texture2D(卷宽、卷高*卷深)


大多数情况下它都能工作,但有时它会显示错误的像素,可能是因为它拾取的是亚像素信息。我怎样才能解决这个问题?钳制输入不起作用。

如果有帮助的话,我会将其用于我的3D云:

float   SampleNoiseTexture( float3 _UVW, float _MipLevel )
{
    float2  WrappedUW = fmod( 16.0 * (1000.0 + _UVW.xz), 16.0 );    // UW wrapped in [0,16[

    float   IntW = floor( WrappedUW.y );                // Integer slice number
    float   dw = WrappedUW.y - IntW;                    // Remainder for intepolating between slices

    _UVW.x = (17.0 * IntW + WrappedUW.x + 0.25) * 0.00367647058823529411764705882353;   // divided by 17*16 = 272

    float4  Value = tex2D( _TexNoise3D, float4( _UVW.xy, 0.0, 0.0 ) );

    return lerp( Value.x, Value.y, dw );
}
“3D纹理”在272x16纹理中压缩为17像素宽的16个切片,每个切片的第17列是第1列的副本(包裹地址模式)。。。
当然,这种技术不允许进行mip映射。

我跟踪了Patapoms的反应,得出以下结论。然而,它仍然是关闭的,因为它应该是

float getAlpha(float3 position)
{
    float2  WrappedUW = fmod( _Volume.xz * (1000.0 + position.xz), _Volume.xz );    // UW wrapped in [0,16[

    float   IntW = floor( WrappedUW.y );                // Integer slice number
    float   dw = WrappedUW.y - IntW;                    // Remainder for intepolating between slices

    position.x = ((_Volume.z + 1.0) * IntW + WrappedUW.x + 0.25) / ((_Volume.z + 1.0) * _Volume.x);   // divided by 17*16 = 272

    float4  Value = tex2Dlod( _VolumeTex, float4( position.xy, 0.0, 0.0 ) );

    return lerp( Value.x, Value.y, dw );
}


public int GetPixelId(int x, int y, int z) {
    return y * (volumeWidth + 1) * volumeDepth + z * (volumeWidth + 1) + x;
}

             // Code to set the pixelbuffer one pixel at a time starting from a clean slate
            pixelBuffer[GetPixelId(x, y, z)].r = color.r;

            if (z > 0)
                pixelBuffer[GetPixelId(x, y, z - 1)].g = color.r;

            if (z == volumeDepth - 1 || z == 0)
                pixelBuffer[GetPixelId(x, y, z)].g = color.r;

            if (x == 0) {
                pixelBuffer[GetPixelId(volumeWidth, y, z)].r = color.r;
                if (z > 0)
                    pixelBuffer[GetPixelId(volumeWidth, y, z - 1)].g = color.r;

                if (z == volumeDepth - 1 || z == 0)
                    pixelBuffer[GetPixelId(volumeWidth, y, z)].g = color.r;
            }

下面是我用来创建3D纹理的代码,如果这是困扰您的原因:

static const    NOISE3D_TEXTURE_POT = 4;
static const    NOISE3D_TEXTURE_SIZE = 1 << NOISE3D_TEXTURE_POT;

// <summary>
// Create the "3D noise" texture
// To simulate 3D textures that are not available in Unity, I create a single long 2D slice of (17*16) x 16
// The width is 17*16 so that all 3D slices are packed into a single line, and I use 17 as a single slice width
//  because I pad the last pixel with the first column of the same slice so bilinear interpolation is correct.
// The texture contains 2 significant values in Red and Green :
//      Red is the noise value in the current W slice
//      Green is the noise value in the next W slice
//  Then, the actual 3D noise value is an interpolation of red and green based on the W remainder
// </summary>
protected NuajTexture2D Build3DNoise()
{
    // Build first noise mip level
    float[,,]   NoiseValues = new float[NOISE3D_TEXTURE_SIZE,NOISE3D_TEXTURE_SIZE,NOISE3D_TEXTURE_SIZE];
    for ( int W=0; W < NOISE3D_TEXTURE_SIZE; W++ )
        for ( int V=0; V < NOISE3D_TEXTURE_SIZE; V++ )
            for ( int U=0; U < NOISE3D_TEXTURE_SIZE; U++ )
                NoiseValues[U,V,W] = (float) SimpleRNG.GetUniform();

    // Build actual texture
    int MipLevel = 0;  // In my original code, I build several textures for several mips...
    int MipSize = NOISE3D_TEXTURE_SIZE >> MipLevel;
    int Width = MipSize*(MipSize+1);    // Pad with an additional column
    Color[] Content = new Color[MipSize*Width];

    // Build content
    for ( int W=0; W < MipSize; W++ )
    {
        int Offset = W * (MipSize+1);   // W Slice offset
        for ( int V=0; V < MipSize; V++ )
        {
            for ( int U=0; U <= MipSize; U++ )
            {
                Content[Offset+Width*V+U].r = NoiseValues[U & (MipSize-1),V,W];
                Content[Offset+Width*V+U].g = NoiseValues[U & (MipSize-1),V,(W+1) & (MipSize-1)];
            }
        }
    }

    // Create texture
    NuajTexture2D   Result = Help.CreateTexture( "Noise3D", Width, MipSize, TextureFormat.ARGB32, false, FilterMode.Bilinear, TextureWrapMode.Repeat );
    Result.SetPixels( Content, 0 );
    Result.Apply( false, true );

    return Result;
}
static const NOISE3D\u TEXTURE\u POT=4;
静态常量NOISE3D\u纹理大小=1>mipglevel;
int Width=MipSize*(MipSize+1);//用一根额外的柱子垫起来
颜色[]内容=新颜色[MipSize*宽度];
//构建内容
对于(int W=0;W对于(int U=0;U),我忘了指定纹理的X分量包含当前切片的值,而Y分量包含下一个切片的值。这样,您可以使用单个纹理轻触沿W方向移动。这限制了这些“3D”虽然只有两个组件的纹理,但这没关系,因为我只存储了一个单色噪声值…我必须说,这真是太棒了!谢谢你的帮助:)你能详细说明一些关于魔法数字的信息吗?或者你有什么文档吗?