【问题标题】:3D Texture emulation in shader (subpixel related)着色器中的 3D 纹理仿真(与子像素相关)
【发布时间】:2013-09-03 19:51:03
【问题描述】:

我正在开发一个暂时依赖 3D 纹理的 Unity3D 项目。

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

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

(添加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)。

大部分时间它都能正常工作,但有时它会显示错误的像素,这可能是因为它正在获取亚像素信息。我怎样才能解决这个问题?限制输入不起作用。

【问题讨论】:

    标签: unity3d glsl hlsl cg


    【解决方案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 纹理中打包为 16 个 17 像素宽的切片,每个切片的第 17 列是第 1 列的副本(换行地址模式)... 当然,这种技术不允许使用 mip-mapping。

    【讨论】:

    • 我忘记指定纹理的 X 分量包含当前切片的值,而 Y 分量包含下一个切片的值。这样,您可以使用单个纹理点击沿 W 方向倾斜。这将这些“3D”纹理限制为只有 2 个组件,但这没关系,因为我只存储了一个单色噪声值......
    • 我不得不说这真是太天才了!感谢您的帮助:)
    • 你能详细说明一下神奇的数字吗?或者你在某处有一些文档?
    【解决方案2】:

    这是我用来创建 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;
    }
    

    【讨论】:

      【解决方案3】:

      我关注了 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;
                  }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-03
        • 1970-01-01
        • 1970-01-01
        • 2020-09-06
        • 1970-01-01
        相关资源
        最近更新 更多