VkBool32 VKTS_APIENTRY imageDataSaveGli(const std::string& name, const IImageDataSP& imageData, const uint32_t mipLevel, const uint32_t arrayLayer) { gli::format format = imageDataTranslateFormat(imageData->getFormat()); if (format == gli::FORMAT_UNDEFINED) { return VK_FALSE; } VkExtent3D currentExtent; size_t currentOffset; if (!imageData->getExtentAndOffset(currentExtent, currentOffset, mipLevel, arrayLayer)) { return VK_FALSE; } gli::texture::extent_type extent{currentExtent.width, currentExtent.height, currentExtent.depth}; gli::texture texture(gli::TARGET_2D, format, extent, 1, 1, 1); VkSubresourceLayout subresourceLayout{0, (VkDeviceSize)texture.size(0), texture.size(0) / extent.y, 0, 0}; if (!imageData->copy(texture.data(0, 0, 0), mipLevel, arrayLayer, subresourceLayout)) { return VK_FALSE; } return (VkBool32)gli::save(texture, name.c_str()); }
glm::vec3 VKTS_APIENTRY renderLambert(const IImageDataSP& cubeMap, const VkFilter filter, const uint32_t mipLevel, const glm::vec2& randomPoint, const glm::mat3& basis) { if (!cubeMap.get() || cubeMap->getArrayLayers() != 6) { return glm::vec3(0.0f, 0.0f, 0.0f); } glm::vec3 LtangentSpace = renderGetCosineWeightedVector(randomPoint); // Transform light ray to world space. glm::vec3 L = basis * LtangentSpace; return glm::vec3(cubeMap->getSampleCubeMap(L.x, L.y, L.z, filter, mipLevel)); }
glm::vec3 VKTS_APIENTRY renderCookTorrance(const IImageDataSP& cubeMap, const VkFilter filter, const uint32_t mipLevel, const glm::vec2& randomPoint, const glm::mat3& basis, const glm::vec3& N, const glm::vec3& V, const float roughness) { if (!cubeMap.get() || cubeMap->getArrayLayers() != 6) { return glm::vec3(0.0f, 0.0f, 0.0f); } glm::vec3 HtangentSpace = renderGetGGXWeightedVector(randomPoint, roughness); // Transform H to world space. glm::vec3 H = basis * HtangentSpace; // Note: reflect takes incident vector. glm::vec3 L = glm::reflect(-V, H); return glm::vec3(cubeMap->getSampleCubeMap(L.x, L.y, L.z, filter, mipLevel)); }
glm::vec3 VKTS_APIENTRY renderOrenNayar(const IImageDataSP& cubeMap, const VkFilter filter, const uint32_t mipLevel, const glm::vec2& randomPoint, const glm::mat3& basis, const glm::vec3& N, const glm::vec3& V, const float roughness) { if (!cubeMap.get() || cubeMap->getArrayLayers() != 6) { return glm::vec3(0.0f, 0.0f, 0.0f); } glm::vec3 LtangentSpace = renderGetCosineWeightedVector(randomPoint); // Transform light ray to world space. glm::vec3 L = basis * LtangentSpace; float NdotL = glm::dot(N, L); float NdotV = glm::dot(N, V); float angleVN = acosf(NdotV); float angleLN = acosf(NdotL); float alpha = glm::max(angleVN, angleLN); float beta = glm::min(angleVN, angleLN); float gamma = glm::dot(V - N * NdotV, L - N * NdotL); float roughnessSquared = roughness * roughness; float A = 1.0f - 0.5f * (roughnessSquared / (roughnessSquared + 0.57f)); float B = 0.45f * (roughnessSquared / (roughnessSquared + 0.09f)); float C = sinf(alpha) * tanf(beta); float Lr = glm::max(0.0f, NdotL) * (A + B * glm::max(0.0f, gamma) * C); return glm::vec3(cubeMap->getSampleCubeMap(L.x, L.y, L.z, filter, mipLevel)) * Lr; }
SmartPointerVector<IImageDataSP> VKTS_APIENTRY imageDataCubemap(const IImageDataSP& sourceImage, const std::string& name) { if (name.size() == 0 || !sourceImage.get()) { return SmartPointerVector<IImageDataSP>(); } std::string sourceImageFilename = name; auto dotIndex = sourceImageFilename.rfind("."); if (dotIndex == sourceImageFilename.npos) { return SmartPointerVector<IImageDataSP>(); } auto sourceImageName = sourceImageFilename.substr(0, dotIndex); auto sourceImageExtension = sourceImageFilename.substr(dotIndex); // TODO: Implement. return SmartPointerVector<IImageDataSP>(); }
IMemoryImageSP VKTS_APIENTRY memoryImageCreate(IImageSP& stageImage, IBufferSP& stageBuffer, IDeviceMemorySP& stageDeviceMemory, const IInitialResourcesSP& initialResources, const ICommandBuffersSP& cmdBuffer, const std::string& name, const IImageDataSP& imageData, const VkImageCreateInfo& imageCreateInfo, const VkAccessFlags srcAccessMask, const VkAccessFlags dstAccessMask, const VkImageLayout newLayout, const VkImageSubresourceRange& subresourceRange, const VkMemoryPropertyFlags memoryPropertyFlags) { if (!cmdBuffer || !imageData.get()) { return IMemoryImageSP(); } VkResult result; // IImageSP image; IDeviceMemorySP deviceMemory; // if (!memoryImagePrepare(image, deviceMemory, initialResources, cmdBuffer, imageCreateInfo, srcAccessMask, dstAccessMask, newLayout, subresourceRange, memoryPropertyFlags)) { return IMemoryImageSP(); } // if (memoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { for (uint32_t i = 0; i < imageData->getMipLevels(); i++) { VkImageSubresource imageSubresource; imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageSubresource.mipLevel = i; imageSubresource.arrayLayer = 0; VkSubresourceLayout subresourceLayout; image->getImageSubresourceLayout(subresourceLayout, imageSubresource); if (!memoryImageUpload(deviceMemory, imageData, i, subresourceLayout)) { logPrint(VKTS_LOG_ERROR, "MemoryImage: Could not upload image data."); return IMemoryImageSP(); } } } else { if (initialResources->getPhysicalDevice()->isImageTilingAvailable(VK_IMAGE_TILING_LINEAR, imageData->getFormat(), imageData->getImageType(), 0, imageData->getExtent3D(), imageData->getMipLevels(), 1, VK_SAMPLE_COUNT_1_BIT, imageData->getSize())) { VkImageCreateInfo stageImageCreateInfo; memcpy(&stageImageCreateInfo, &imageCreateInfo, sizeof(VkImageCreateInfo)); stageImageCreateInfo.tiling = VK_IMAGE_TILING_LINEAR; stageImageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; stageImageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; if (!memoryImagePrepare(stageImage, stageDeviceMemory, initialResources, cmdBuffer, stageImageCreateInfo, VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, subresourceRange, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) { logPrint(VKTS_LOG_ERROR, "MemoryImage: Could not prepare staging image."); return IMemoryImageSP(); } for (uint32_t i = 0; i < imageData->getMipLevels(); i++) { VkImageSubresource imageSubresource; imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageSubresource.mipLevel = i; imageSubresource.arrayLayer = 0; VkSubresourceLayout subresourceLayout; stageImage->getImageSubresourceLayout(subresourceLayout, imageSubresource); if (!memoryImageUpload(stageDeviceMemory, imageData, i, subresourceLayout)) { logPrint(VKTS_LOG_ERROR, "MemoryImage: Could not upload image data."); return IMemoryImageSP(); } VkImageCopy imageCopy; imageCopy.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, i, 0, 1}; imageCopy.srcOffset = {0, 0, 0}; imageCopy.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, i, 0, 1}; imageCopy.dstOffset = {0, 0, 0}; imageCopy.extent = {glm::max(imageData->getWidth() >> i, 1u), glm::max(imageData->getHeight() >> i, 1u), glm::max(imageData->getDepth() >> i, 1u)}; stageImage->copyImage(cmdBuffer->getCommandBuffer(), image, imageCopy); } }
SmartPointerVector<IImageDataSP> VKTS_APIENTRY imageDataMipmap(const IImageDataSP& sourceImage, VkBool32 addSourceAsCopy, const std::string& name) { if (name.size() == 0 || !sourceImage.get()) { return SmartPointerVector<IImageDataSP>(); } std::string sourceImageFilename = name; auto dotIndex = sourceImageFilename.rfind("."); if (dotIndex == sourceImageFilename.npos) { return SmartPointerVector<IImageDataSP>(); } auto sourceImageName = sourceImageFilename.substr(0, dotIndex); auto sourceImageExtension = sourceImageFilename.substr(dotIndex); IImageDataSP currentSourceImage = sourceImage; int32_t width = currentSourceImage->getWidth(); int32_t height = currentSourceImage->getHeight(); int32_t depth = currentSourceImage->getDepth(); IImageDataSP currentTargetImage; std::string targetImageFilename; int32_t level = 0; SmartPointerVector<IImageDataSP> result; if (addSourceAsCopy) { targetImageFilename = sourceImageName + "_L" + std::to_string(level++) + sourceImageExtension; currentTargetImage = imageDataCopy(sourceImage, targetImageFilename); if (!currentTargetImage.get()) { return SmartPointerVector<IImageDataSP>(); } result.append(currentTargetImage); } else { result.append(sourceImage); level++; } while (width > 1 || height > 1 || depth > 1) { width = glm::max(width / 2, 1); height = glm::max(height / 2, 1); depth = glm::max(depth / 2, 1); targetImageFilename = sourceImageName + "_L" + std::to_string(level++) + sourceImageExtension; currentTargetImage = imageDataCreate(targetImageFilename, width, height, depth, 0.0f, 0.0f, 0.0f, 0.0f, sourceImage->getImageType(), sourceImage->getFormat()); if (!currentTargetImage.get()) { return SmartPointerVector<IImageDataSP>(); } for (int32_t z = 0; z < depth; z++) { for (int32_t y = 0; y < height; y++) { for (int32_t x = 0; x < width; x++) { glm::vec4 rgba = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f); float sampleCount = 0.0f; for (int32_t iz = z * 2; iz < z * 2 + 1; iz++) { for (int32_t iy = y * 2; iy < y * 2 + 1; iy++) { for (int32_t ix = x * 2; ix < x * 2 + 1; ix++) { rgba += currentSourceImage->getTexel(ix, iy, iz); sampleCount += 1.0f; } } } if (sampleCount > 0.0f) { rgba /= sampleCount; currentTargetImage->setTexel(rgba, x, y, z); } } } } result.append(currentTargetImage); // currentSourceImage = currentTargetImage; width = currentSourceImage->getWidth(); height = currentSourceImage->getHeight(); depth = currentSourceImage->getDepth(); } return result; }
FontCacheEntry* FreeTypeFont::getGlyph(const char32_t character, const size_t size) { if (!face) { return nullptr; } // auto results = cache.find(character); while (results != cache.cend()) { if (results->second.size == size) { return &results->second; } results++; } // if (FT_Set_Char_Size(face, VKTS_TO_CHAR_SIZE(size), VKTS_TO_CHAR_SIZE(size), 0, 0)) { return nullptr; } auto glyphIndex = FT_Get_Char_Index(face, character); if (FT_Load_Glyph(face, glyphIndex, FT_LOAD_DEFAULT)) { return nullptr; } if (FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL)) { return nullptr; } // IImageDataSP glyphImageData; if (face->glyph->bitmap.buffer) { glyphImageData = imageDataCreate("FontCharacterImageData", face->glyph->bitmap.width, face->glyph->bitmap.rows, 1, VK_IMAGE_TYPE_2D, VK_FORMAT_R8_UNORM); if (!glyphImageData.get()) { return nullptr; } VkSubresourceLayout subresourceLayout; subresourceLayout.offset = 0; subresourceLayout.size = face->glyph->bitmap.width * face->glyph->bitmap.rows; subresourceLayout.rowPitch = face->glyph->bitmap.width; subresourceLayout.arrayPitch = 0; subresourceLayout.depthPitch = 0; if (!glyphImageData->upload(face->glyph->bitmap.buffer, 0, subresourceLayout)) { return nullptr; } } else { // For space, no data is created. glyphImageData = imageDataCreate("FontCharacterImageData", 1, 1, 1, 0.0f, 0.0f, 0.0f, 0.0f, VK_IMAGE_TYPE_2D, VK_FORMAT_R8_UNORM); if (!glyphImageData.get()) { return nullptr; } } // FontCacheEntry fontCacheEntry; fontCacheEntry.character = character; fontCacheEntry.size = size; fontCacheEntry.width = face->glyph->bitmap.width; fontCacheEntry.height = face->glyph->bitmap.rows; fontCacheEntry.advanceX = VKTS_FROM_CHAR_SIZE(face->glyph->advance.x); fontCacheEntry.advanceY = VKTS_FROM_CHAR_SIZE(face->glyph->advance.y); fontCacheEntry.offsetX = VKTS_FROM_CHAR_SIZE(face->glyph->metrics.vertBearingX - face->glyph->metrics.width); fontCacheEntry.offsetY = VKTS_FROM_CHAR_SIZE(face->glyph->metrics.horiBearingY - face->glyph->metrics.height); fontCacheEntry.glyphImageData = glyphImageData; fontCacheEntry.texture = ITextureSP(); cache.insert(std::make_pair(character, fontCacheEntry)); // results = cache.find(character); while (results != cache.cend()) { if (results->second.size == size) { return &results->second; } results++; } return nullptr; }