diff --git a/android/distancefieldfonts/.gitignore b/android/distancefieldfonts/.gitignore
new file mode 100644
index 00000000..7a5d249c
--- /dev/null
+++ b/android/distancefieldfonts/.gitignore
@@ -0,0 +1,10 @@
+/assets/
+/res/
+/bin/
+/libs/
+/obj/
+/build.xml
+/local.properties
+/project.properties
+/proguard-project.txt
+*.apk
\ No newline at end of file
diff --git a/android/distancefieldfonts/AndroidManifest.xml b/android/distancefieldfonts/AndroidManifest.xml
new file mode 100644
index 00000000..a1fdbb46
--- /dev/null
+++ b/android/distancefieldfonts/AndroidManifest.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/distancefieldfonts/build.bat b/android/distancefieldfonts/build.bat
new file mode 100644
index 00000000..9f5fddb6
--- /dev/null
+++ b/android/distancefieldfonts/build.bat
@@ -0,0 +1,23 @@
+cd jni
+call ndk-build
+if %ERRORLEVEL% EQU 0 (
+ echo ndk-build has failed, build cancelled
+ cd..
+
+ mkdir "assets\shaders\distancefieldfonts"
+ xcopy "..\..\data\shaders\distancefieldfonts\*.spv" "assets\shaders\distancefieldfonts" /Y
+
+ mkdir "assets\textures"
+ xcopy "..\..\data\textures\font_sdf_rgba.ktx" "assets\textures" /Y
+ xcopy "..\..\data\textures\font_bitmap_rgba.ktx" "assets\textures" /Y
+
+ xcopy "..\..\data\font.fnt" "assets" /Y
+
+ mkdir "res\drawable"
+ xcopy "..\..\android\images\icon.png" "res\drawable" /Y
+
+ call ant debug -Dout.final.file=vulkanDistancefieldfonts.apk
+) ELSE (
+ echo error : ndk-build failed with errors!
+ cd..
+)
diff --git a/android/distancefieldfonts/jni/Android.mk b/android/distancefieldfonts/jni/Android.mk
new file mode 100644
index 00000000..aabab29c
--- /dev/null
+++ b/android/distancefieldfonts/jni/Android.mk
@@ -0,0 +1,50 @@
+LOCAL_PATH := $(call my-dir)/../../distancefieldfonts
+
+# assimp
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := assimp
+LOCAL_SRC_FILES := $(LOCAL_PATH)/../../libs/assimp/$(TARGET_ARCH_ABI)/libassimp.a
+include $(PREBUILT_STATIC_LIBRARY)
+
+# vulkan example
+
+DATADIR := $(LOCAL_PATH)/../../data
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := vulkanDistancefieldfonts
+
+PROJECT_FILES := $(wildcard $(LOCAL_PATH)/../../distancefieldfonts/*.cpp)
+PROJECT_FILES += $(wildcard $(LOCAL_PATH)/../../base/*.cpp)
+
+# stringstream usage causes some warnings that would fail the build
+LOCAL_DISABLE_FATAL_LINKER_WARNINGS := true
+
+LOCAL_CPPFLAGS := -std=c++11
+LOCAL_CPPFLAGS += -D__STDC_LIMIT_MACROS
+LOCAL_CPPFLAGS += -DVK_NO_PROTOTYPES
+LOCAL_CPPFLAGS += -DVK_USE_PLATFORM_ANDROID_KHR
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../external/
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../external/glm
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../external/gli
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../external/assimp
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../base/
+#LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../base/android
+
+LOCAL_SRC_FILES := $(PROJECT_FILES)
+
+LOCAL_LDLIBS := -landroid -llog -lz
+
+LOCAL_DISABLE_FORMAT_STRING_CHECKS := true
+
+LOCAL_STATIC_LIBRARIES += android_native_app_glue
+LOCAL_STATIC_LIBRARIES += cpufeatures
+LOCAL_STATIC_LIBRARIES += libassimp
+
+include $(BUILD_SHARED_LIBRARY)
+
+$(call import-module, android/native_app_glue)
+$(call import-module, android/cpufeatures)
diff --git a/android/distancefieldfonts/jni/Application.mk b/android/distancefieldfonts/jni/Application.mk
new file mode 100644
index 00000000..62020feb
--- /dev/null
+++ b/android/distancefieldfonts/jni/Application.mk
@@ -0,0 +1,5 @@
+APP_PLATFORM := android-19
+APP_ABI := armeabi-v7a
+APP_STL := c++_static
+APP_CPPFLAGS := -std=c++11
+NDK_TOOLCHAIN_VERSION := clang
diff --git a/distancefieldfonts/distancefieldfonts.cpp b/distancefieldfonts/distancefieldfonts.cpp
index 15c768c3..587a5217 100644
--- a/distancefieldfonts/distancefieldfonts.cpp
+++ b/distancefieldfonts/distancefieldfonts.cpp
@@ -58,43 +58,6 @@ int32_t nextValuePair(std::stringstream *stream)
return val;
}
-void parsebmFont()
-{
- const char *filename = "../data/font.fnt";
-
- std::ifstream fstream(filename);
- assert(fstream.good());
-
- while (!fstream.eof())
- {
- std::string line;
- std::stringstream lineStream;
- std::getline(fstream, line);
- lineStream << line;
-
- std::string info;
- lineStream >> info;
-
- if (info == "char")
- {
- std::string pair;
-
- // char id
- uint32_t charid = nextValuePair(&lineStream);
- // Char properties
- fontChars[charid].x = nextValuePair(&lineStream);
- fontChars[charid].y = nextValuePair(&lineStream);
- fontChars[charid].width = nextValuePair(&lineStream);
- fontChars[charid].height = nextValuePair(&lineStream);
- fontChars[charid].xoffset = nextValuePair(&lineStream);
- fontChars[charid].yoffset = nextValuePair(&lineStream);
- fontChars[charid].xadvance = nextValuePair(&lineStream);
- fontChars[charid].page = nextValuePair(&lineStream);
- }
- }
-
-}
-
class VulkanExample : public VulkanExampleBase
{
public:
@@ -179,14 +142,73 @@ public:
vkFreeMemory(device, uniformData.vs.memory, nullptr);
}
+ // Basic parser fpr AngelCode bitmap font format files
+ // See http://www.angelcode.com/products/bmfont/doc/file_format.html for details
+ void parsebmFont()
+ {
+ std::string fileName = getAssetPath() + "font.fnt";
+
+#if defined(__ANDROID__)
+ // Font description file is stored inside the apk
+ // So we need to load it using the asset manager
+ AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, fileName.c_str(), AASSET_MODE_STREAMING);
+ assert(asset);
+ size_t size = AAsset_getLength(asset);
+
+ assert(size > 0);
+
+ void *fileData = malloc(size);
+ AAsset_read(asset, fileData, size);
+ AAsset_close(asset);
+
+ std::stringbuf sbuf((const char*)fileData);
+ std::istream istream(&sbuf);
+#else
+ FILE *file = fopen(fileName.c_str(), "r");
+ std::filebuf fileBuffer(file);
+ std::istream istream(&fileBuffer);
+#endif
+
+ assert(istream.good());
+
+ while (!istream.eof())
+ {
+ std::string line;
+ std::stringstream lineStream;
+ std::getline(istream, line);
+ lineStream << line;
+
+ std::string info;
+ lineStream >> info;
+
+ if (info == "char")
+ {
+ std::string pair;
+
+ // char id
+ uint32_t charid = nextValuePair(&lineStream);
+ // Char properties
+ fontChars[charid].x = nextValuePair(&lineStream);
+ fontChars[charid].y = nextValuePair(&lineStream);
+ fontChars[charid].width = nextValuePair(&lineStream);
+ fontChars[charid].height = nextValuePair(&lineStream);
+ fontChars[charid].xoffset = nextValuePair(&lineStream);
+ fontChars[charid].yoffset = nextValuePair(&lineStream);
+ fontChars[charid].xadvance = nextValuePair(&lineStream);
+ fontChars[charid].page = nextValuePair(&lineStream);
+ }
+ }
+
+ }
+
void loadTextures()
{
textureLoader->loadTexture(
- "./../data/textures/font_sdf_rgba.ktx",
+ getAssetPath() + "textures/font_sdf_rgba.ktx",
VK_FORMAT_R8G8B8A8_UNORM,
&textures.fontSDF);
textureLoader->loadTexture(
- "./../data/textures/font_bitmap_rgba.ktx",
+ getAssetPath() + "textures/font_bitmap_rgba.ktx",
VK_FORMAT_R8G8B8A8_UNORM,
&textures.fontBitmap);
}
@@ -207,7 +229,6 @@ public:
VkClearValue clearValues[2];
clearValues[0].color = defaultClearColor;
- clearValues[0].color = { {0.0f, 0.0f, 0.2f, 0.0f} };
clearValues[1].depthStencil = { 1.0f, 0 };
VkRenderPassBeginInfo renderPassBeginInfo = vkTools::initializers::renderPassBeginInfo();
@@ -555,13 +576,14 @@ public:
0xf,
VK_TRUE);
+ blendAttachmentState.blendEnable = VK_TRUE;
+ blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
+ blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
- blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR;
- blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
+ blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
+ blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
- blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
- blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
- blendAttachmentState.blendEnable = VK_FALSE;
+ blendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
VkPipelineColorBlendStateCreateInfo colorBlendState =
vkTools::initializers::pipelineColorBlendStateCreateInfo(
@@ -595,8 +617,8 @@ public:
// Load shaders
std::array shaderStages;
- shaderStages[0] = loadShader("./../data/shaders/distancefieldfonts/sdf.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
- shaderStages[1] = loadShader("./../data/shaders/distancefieldfonts/sdf.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
+ shaderStages[0] = loadShader(getAssetPath() + "shaders/distancefieldfonts/sdf.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
+ shaderStages[1] = loadShader(getAssetPath() + "shaders/distancefieldfonts/sdf.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
VkGraphicsPipelineCreateInfo pipelineCreateInfo =
vkTools::initializers::pipelineCreateInfo(
@@ -619,8 +641,8 @@ public:
assert(!err);
// Default bitmap font rendering pipeline
- shaderStages[0] = loadShader("./../data/shaders/distancefieldfonts/bitmap.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
- shaderStages[1] = loadShader("./../data/shaders/distancefieldfonts/bitmap.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
+ shaderStages[0] = loadShader(getAssetPath() + "shaders/distancefieldfonts/bitmap.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
+ shaderStages[1] = loadShader(getAssetPath() + "shaders/distancefieldfonts/bitmap.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.bitmap);
assert(!err);
}
@@ -728,8 +750,7 @@ public:
VulkanExample *vulkanExample;
-#ifdef _WIN32
-
+#if defined(_WIN32)
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (vulkanExample != NULL)
@@ -750,9 +771,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
return (DefWindowProc(hWnd, uMsg, wParam, lParam));
}
-
-#else
-
+#elif defined(__linux__) && !defined(__ANDROID__)
static void handleEvent(const xcb_generic_event_t *event)
{
if (vulkanExample != NULL)
@@ -762,21 +781,42 @@ static void handleEvent(const xcb_generic_event_t *event)
}
#endif
-#ifdef _WIN32
+// Main entry point
+#if defined(_WIN32)
+// Windows entry point
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow)
-#else
+#elif defined(__ANDROID__)
+// Android entry point
+void android_main(android_app* state)
+#elif defined(__linux__)
+// Linux entry point
int main(const int argc, const char *argv[])
#endif
{
+#if defined(__ANDROID__)
+ // Removing this may cause the compiler to omit the main entry point
+ // which would make the application crash at start
+ app_dummy();
+#endif
vulkanExample = new VulkanExample();
-#ifdef _WIN32
+#if defined(_WIN32)
vulkanExample->setupWindow(hInstance, WndProc);
-#else
+#elif defined(__ANDROID__)
+ // Attach vulkan example to global android application state
+ state->userData = vulkanExample;
+ state->onAppCmd = VulkanExample::handleAppCommand;
+ state->onInputEvent = VulkanExample::handleAppInput;
+ vulkanExample->androidApp = state;
+#elif defined(__linux__)
vulkanExample->setupWindow();
#endif
+#if !defined(__ANDROID__)
vulkanExample->initSwapchain();
vulkanExample->prepare();
+#endif
vulkanExample->renderLoop();
+#if !defined(__ANDROID__)
delete(vulkanExample);
return 0;
-}
+#endif
+}
\ No newline at end of file