2

一時的に 3D テクスチャに依存する Unity3D プロジェクトに取り組んでいます。

問題は、Unity では Pro ユーザーのみが Texture3D を使用できることです。したがって、私は Texture3D に代わるものを探しています。おそらく、シェーダー (3D テクスチャを使用) で 3 次元として解釈される 1 次元テクスチャ (Unity ではネイティブに利用できません) です。

(できれば) サブピクセル情報を保持しながらこれを行う方法はありますか?

(ここに問題の核心があるため、GLSL および Cg タグが追加されました)

編集: 問題はここでも解決されます: webgl glsl emulate texture3d ただし、これはまだ完成しておらず、適切に機能しています。

編集:当分の間、適切なサブピクセル情報を無視します。そのため、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(volumeWidth, volumeHeight * volumeDepth) として初期化します。

ほとんどの場合は機能しますが、おそらくサブピクセル情報が取得されているために、間違ったピクセルが表示されることがあります。どうすればこれを修正できますか? 入力のクランプは機能しません。

4

3 に答える 3

1

3D テクスチャが気になる場合は、次のコードを使用して 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;
}
于 2013-09-02T19:09:57.603 に答える
1

それが役立つ場合、私は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 列目のコピーです (ラップ アドレス モード)... もちろん、ミップ マッピングは許可されませんこのテクニック。

于 2013-07-20T13:36:02.663 に答える