【问题标题】:Vulkan: Loading floating point cubemap textures distortedVulkan:加载扭曲的浮点立方体贴图纹理
【发布时间】:2022-01-20 19:45:02
【问题描述】:

我正在使用 vulkan 教程代码并为立方体贴图进行了修改。 当我使用 VK_FORMAT_R8G8B8A8_UNORM 时正在使用此代码:

unsigned char* pixelsArray[6];
for (int i = 0; i < 6; ++i)
{
    pixelsArray[i] = stbi_load(imageFileArray[i].c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
}

VkDeviceSize allSize = texWidth * texHeight * 4 * 6;
VkDeviceSize size = texWidth * texHeight * 4 ;

VkBufferCreateInfo bufferInfo{};
...    
bufferInfo.size = allSize ;

vkMapMemory(device, stagingBufferMemory, 0, AllSize, 0, &data);
    for(int i = 0; i < 6; ++i)
    {            
        memcpy( (char*) data + (size*i) , pixelsArray[i], static_cast<size_t>(size));           
    }
vkUnmapMemory(device, stagingBufferMemory);

VkImageCreateInfo imageInfo{};
...    
imageInfo.arrayLayers = 6;
imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;    
imageInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;

VkImageViewCreateInfo viewInfo{};
...
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
viewInfo.format = VK_FORMAT_R8G8B8A8_UNORM;    
viewInfo.subresourceRange.layerCount = 6;

但是当我尝试 VK_FORMAT_R16G16B16A16_SFLOAT 时,显示失真,并且此代码没有验证错误:

float* pixelsArray[6];
for (int i = 0; i < 6; ++i)
{
    pixelsArray[i] = stbi_loadf(imageFileArray[i].c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
}

VkDeviceSize allSize = texWidth * texHeight * 4 * 6 * 2;//  I added *2
VkDeviceSize size = texWidth * texHeight * 4 * 2;// I added *2

VkBufferCreateInfo bufferInfo{};
...    
bufferInfo.size = allSize ;

vkMapMemory(device, stagingBufferMemory, 0, AllSize, 0, &data);
    for(int i = 0; i < 6; ++i)
    {            
        memcpy( (char*) data + (size*i) , pixelsArray[i], static_cast<size_t>(size));           
    }
vkUnmapMemory(device, stagingBufferMemory);

VkImageCreateInfo imageInfo{};
...    
imageInfo.arrayLayers = 6;
imageInfo.format = VK_FORMAT_R16G16B16A16_SFLOAT;    
imageInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;

VkImageViewCreateInfo viewInfo{};
...
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
viewInfo.format = VK_FORMAT_R16G16B16A16_SFLOAT;    
viewInfo.subresourceRange.layerCount = 6;

当 VK_FORMAT_R8G8B8A8_UNORM :

当 VK_FORMAT_R16G16B16A16_SFLOAT :

【问题讨论】:

    标签: vulkan


    【解决方案1】:

    我解决了这个问题。问题是我想使用半浮点数,但我将浮点数发送到 memcpy 函数。我搜索了如何使用半浮点数,我找到了一个不使用额外库的解决方案。

    我添加了辅助函数:

    typedef unsigned int uint;
    typedef unsigned short ushort;
    
    uint as_uint(const float x)
    {
        return *(uint*)&x;
    }
    
    ushort float_to_half(const float x)
    { 
        // IEEE-754 16-bit floating-point format (without infinity): 1-5-10, exp-15, +-131008.0, +-6.1035156E-5, +-5.9604645E-8, 3.311 digits
        const uint b = as_uint(x)+0x00001000; // round-to-nearest-even: add last bit after truncated mantissa
        const uint e = (b&0x7F800000)>>23; // exponent
        const uint m = b&0x007FFFFF; // mantissa; in line below: 0x007FF000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding
        return (b&0x80000000)>>16 | (e>112)*((((e-112)<<10)&0x7C00)|m>>13) | ((e<113)&(e>101))*((((0x007FF000+m)>>(125-e))+1)>>1) | (e>143)*0x7FFF; // sign : normalized : denormalized : saturate
    }
    

    并解决此辅助函数的问题:

    VkDeviceSize size_2 = texWidth * texHeight * 4;// different from the above variables in question : allSize or size
    
    //create half float for cubemap
    void* half_pixelsArray[6];
    half_pixelsArray[0] = new ushort[size_2];
    half_pixelsArray[1] = new ushort[size_2];
    half_pixelsArray[2] = new ushort[size_2];
    half_pixelsArray[3] = new ushort[size_2];
    half_pixelsArray[4] = new ushort[size_2];
    half_pixelsArray[5] = new ushort[size_2];
    
    //copy from float to half float
    for (int i = 0; i < 6; ++i)
    {
        for (int j = 0; j < size_2; ++j)
        {
            ((ushort*)half_pixelsArray[i])[j] =  float_to_half( pixelsArray[i][j] );
        }
    }
    
    // and change float to half flaot in memcpy
    memcpy( (char*) data + (layerSize*i) , half_pixelsArray[i], static_cast<size_t>(layerSize));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-06
      • 2014-12-15
      • 1970-01-01
      • 2012-11-24
      • 2018-07-29
      • 1970-01-01
      • 2019-06-03
      相关资源
      最近更新 更多