diff --git a/CMakeLists.txt b/CMakeLists.txt
index b9886bcb..02a7a06e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -132,6 +132,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/")
set(EXAMPLES
bloom
+ computecloth
computecullandlod
computenbody
computeparticles
@@ -171,6 +172,7 @@ set(EXAMPLES
specializationconstants
sphericalenvmapping
ssao
+ stencilbuffer
subpasses
terraintessellation
tessellation
diff --git a/android/build-all.py b/android/build-all.py
index 8e2fe745..9a2df48f 100644
--- a/android/build-all.py
+++ b/android/build-all.py
@@ -43,6 +43,7 @@ EXAMPLES = [
"skeletalanimation",
"specializationconstants",
"sphericalenvmapping",
+ "stencilbuffer",
"subpasses",
"terraintessellation",
"tessellation",
diff --git a/android/stencilbuffer/.gitignore b/android/stencilbuffer/.gitignore
new file mode 100644
index 00000000..7a5d249c
--- /dev/null
+++ b/android/stencilbuffer/.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/stencilbuffer/AndroidManifest.xml b/android/stencilbuffer/AndroidManifest.xml
new file mode 100644
index 00000000..56fb2a79
--- /dev/null
+++ b/android/stencilbuffer/AndroidManifest.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/stencilbuffer/example.json b/android/stencilbuffer/example.json
new file mode 100644
index 00000000..b044522a
--- /dev/null
+++ b/android/stencilbuffer/example.json
@@ -0,0 +1,11 @@
+{
+ "apkname": "vulkanStencilbuffer",
+ "directories": {
+ "shaders": "stencilbuffer"
+ },
+ "assets": {
+ "models": [
+ "venus.fbx"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/android/stencilbuffer/jni/Android.mk b/android/stencilbuffer/jni/Android.mk
new file mode 100644
index 00000000..9489ce88
--- /dev/null
+++ b/android/stencilbuffer/jni/Android.mk
@@ -0,0 +1,48 @@
+LOCAL_PATH := $(call my-dir)/../../stencilbuffer
+
+# 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 := vulkanStencilbuffer
+
+PROJECT_FILES := $(wildcard $(LOCAL_PATH)/../../stencilbuffer/*.cpp)
+PROJECT_FILES += $(wildcard $(LOCAL_PATH)/../../base/*.cpp)
+
+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_DISABLE_FATAL_LINKER_WARNINGS := 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/stencilbuffer/jni/Application.mk b/android/stencilbuffer/jni/Application.mk
new file mode 100644
index 00000000..62020feb
--- /dev/null
+++ b/android/stencilbuffer/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/android/uninstall-all.py b/android/uninstall-all.py
index 0ff262fa..5b3700a7 100644
--- a/android/uninstall-all.py
+++ b/android/uninstall-all.py
@@ -42,6 +42,7 @@ APP_NAMES = [
"de.saschawillems.vulkanSkeletalanimation",
"de.saschawillems.vulkanSpecializationconstants",
"de.saschawillems.vulkanSphericalenvmapping",
+ "de.saschawillems.vulkanStencilbuffer",
"de.saschawillems.vulkanSubpasses",
"de.saschawillems.vulkanTerraintessellation",
"de.saschawillems.vulkanTessellation",
diff --git a/stencilbuffer/stencilbuffer.cpp b/stencilbuffer/stencilbuffer.cpp
new file mode 100644
index 00000000..5ab614bd
--- /dev/null
+++ b/stencilbuffer/stencilbuffer.cpp
@@ -0,0 +1,362 @@
+/*
+* Vulkan Example - Rendering outlines using the stencil buffer
+*
+* Copyright (C) 2016-2017 by Sascha Willems - www.saschawillems.de
+*
+* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+*/
+
+#include
+#include
+#include
+#include
+#include
+
+#define GLM_FORCE_RADIANS
+#define GLM_FORCE_DEPTH_ZERO_TO_ONE
+#include
+#include
+
+#include
+#include "vulkanexamplebase.h"
+#include "VulkanModel.hpp"
+#include "VulkanBuffer.hpp"
+
+#define ENABLE_VALIDATION false
+
+class VulkanExample : public VulkanExampleBase
+{
+public:
+ // Vertex layout for the models
+ vks::VertexLayout vertexLayout = vks::VertexLayout({
+ vks::VERTEX_COMPONENT_POSITION,
+ vks::VERTEX_COMPONENT_COLOR,
+ vks::VERTEX_COMPONENT_NORMAL,
+ });
+
+ vks::Model model;
+
+ struct UBO {
+ glm::mat4 projection;
+ glm::mat4 model;
+ glm::vec4 lightPos = glm::vec4(0.0f, -2.0f, 1.0f, 0.0f);
+ // Vertex shader extrudes model by this value along normals for outlining
+ float outlineWidth = 0.05f;
+ } uboVS;
+
+ vks::Buffer uniformBufferVS;
+
+ struct {
+ VkPipeline stencil;
+ VkPipeline outline;
+ } pipelines;
+
+ VkPipelineLayout pipelineLayout;
+ VkDescriptorSet descriptorSet;
+ VkDescriptorSetLayout descriptorSetLayout;
+
+ VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
+ {
+ title = "Vulkan Example - Stencil buffer outlines";
+ timerSpeed *= 0.25f;
+ enableTextOverlay = true;
+ camera.type = Camera::CameraType::lookat;
+ camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f);
+ camera.setRotation(glm::vec3(2.5f, -35.0f, 0.0f));
+ camera.setTranslation(glm::vec3(0.08f, 3.6f, -8.4f));
+ }
+
+ ~VulkanExample()
+ {
+ vkDestroyPipeline(device, pipelines.stencil, nullptr);
+ vkDestroyPipeline(device, pipelines.outline, nullptr);
+
+ vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
+
+ vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
+
+ model.destroy();
+ uniformBufferVS.destroy();
+ }
+
+ void buildCommandBuffers()
+ {
+ VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo();
+
+ VkClearValue clearValues[2];
+ clearValues[0].color = { { 1.0f, 1.0f, 1.0f, 1.0f } };
+ clearValues[0].color = defaultClearColor;
+ clearValues[1].depthStencil = { 1.0f, 0 };
+
+ VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo();
+ renderPassBeginInfo.renderPass = renderPass;
+ renderPassBeginInfo.renderArea.offset.x = 0;
+ renderPassBeginInfo.renderArea.offset.y = 0;
+ renderPassBeginInfo.renderArea.extent.width = width;
+ renderPassBeginInfo.renderArea.extent.height = height;
+ renderPassBeginInfo.clearValueCount = 2;
+ renderPassBeginInfo.pClearValues = clearValues;
+
+ for (int32_t i = 0; i < drawCmdBuffers.size(); ++i)
+ {
+ renderPassBeginInfo.framebuffer = frameBuffers[i];
+
+ VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo));
+
+ vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f);
+ vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport);
+
+ VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0);
+ vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor);
+
+ VkDeviceSize offsets[1] = { 0 };
+
+ vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &model.vertices.buffer, offsets);
+ vkCmdBindIndexBuffer(drawCmdBuffers[i], model.indices.buffer, 0, VK_INDEX_TYPE_UINT32);
+
+ vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL);
+
+ // First pass renders object (toon shaded) and fills stencil buffer
+ vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.stencil);
+ vkCmdDrawIndexed(drawCmdBuffers[i], model.indexCount, 1, 0, 0, 0);
+
+ // Second pass renders scaled object only where stencil was not set by first pass
+ vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.outline);
+ vkCmdDrawIndexed(drawCmdBuffers[i], model.indexCount, 1, 0, 0, 0);
+
+ vkCmdEndRenderPass(drawCmdBuffers[i]);
+
+ VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i]));
+ }
+ }
+
+ void loadAssets()
+ {
+ model.loadFromFile(getAssetPath() + "models/venus.fbx", vertexLayout, 0.3f, vulkanDevice, queue);
+ }
+
+ void setupDescriptorPool()
+ {
+ std::vector poolSizes = {
+ vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1),
+ };
+ VkDescriptorPoolCreateInfo descriptorPoolInfo =
+ vks::initializers::descriptorPoolCreateInfo(static_cast(poolSizes.size()), poolSizes.data(), 1);
+ VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool));
+ }
+
+ void setupDescriptorSetLayout()
+ {
+ std::vector setLayoutBindings = {
+ vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0)
+ };
+
+ VkDescriptorSetLayoutCreateInfo descriptorLayoutInfo =
+ vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), 1);
+ VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutInfo, nullptr, &descriptorSetLayout));
+
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo =
+ vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1);
+ VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout));
+ }
+
+ void setupDescriptorSet()
+ {
+ VkDescriptorSetAllocateInfo allocInfo =
+ vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1);
+ VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet));
+ std::vector modelWriteDescriptorSets = {
+ vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBufferVS.descriptor)
+ };
+ vkUpdateDescriptorSets(device, static_cast(modelWriteDescriptorSets.size()), modelWriteDescriptorSets.data(), 0, NULL);
+ }
+
+ void preparePipelines()
+ {
+ VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
+ vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE);
+
+ VkPipelineRasterizationStateCreateInfo rasterizationState =
+ vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_FRONT_BIT, VK_FRONT_FACE_CLOCKWISE, 0);
+
+ VkPipelineColorBlendAttachmentState blendAttachmentState =
+ vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE);
+
+ VkPipelineColorBlendStateCreateInfo colorBlendState =
+ vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState);
+
+ VkPipelineDepthStencilStateCreateInfo depthStencilState =
+ vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL);
+
+ VkPipelineViewportStateCreateInfo viewportState =
+ vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0);
+
+ VkPipelineMultisampleStateCreateInfo multisampleState =
+ vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0);
+
+ std::vector dynamicStateEnables = {
+ VK_DYNAMIC_STATE_VIEWPORT,
+ VK_DYNAMIC_STATE_SCISSOR
+ };
+ VkPipelineDynamicStateCreateInfo dynamicState =
+ vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables);
+
+ std::array shaderStages;
+
+ VkGraphicsPipelineCreateInfo pipelineCreateInfo =
+ vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass, 0);
+
+ // Vertex bindings an attributes
+ std::vector vertexInputBindings = {
+ vks::initializers::vertexInputBindingDescription(0, vertexLayout.stride(), VK_VERTEX_INPUT_RATE_VERTEX),
+ };
+ std::vector vertexInputAttributes = {
+ vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0), // Location 0: Position
+ vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 3), // Location 1: Color
+ vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 6) // Location 2: Normal
+ };
+
+ VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo();
+ vertexInputState.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size());
+ vertexInputState.pVertexBindingDescriptions = vertexInputBindings.data();
+ vertexInputState.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size());
+ vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data();
+
+ pipelineCreateInfo.pVertexInputState = &vertexInputState;
+ pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
+ pipelineCreateInfo.pRasterizationState = &rasterizationState;
+ pipelineCreateInfo.pColorBlendState = &colorBlendState;
+ pipelineCreateInfo.pMultisampleState = &multisampleState;
+ pipelineCreateInfo.pViewportState = &viewportState;
+ pipelineCreateInfo.pDepthStencilState = &depthStencilState;
+ pipelineCreateInfo.pDynamicState = &dynamicState;
+ pipelineCreateInfo.stageCount = static_cast(shaderStages.size());
+ pipelineCreateInfo.pStages = shaderStages.data();
+
+ // Toon render and stencil fill pass
+ shaderStages[0] = loadShader(getAssetPath() + "shaders/stencilbuffer/toon.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
+ shaderStages[1] = loadShader(getAssetPath() + "shaders/stencilbuffer/toon.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
+
+ rasterizationState.cullMode = VK_CULL_MODE_NONE;
+
+ depthStencilState.stencilTestEnable = VK_TRUE;
+
+ depthStencilState.back.compareOp = VK_COMPARE_OP_ALWAYS;
+ depthStencilState.back.failOp = VK_STENCIL_OP_REPLACE;
+ depthStencilState.back.depthFailOp = VK_STENCIL_OP_REPLACE;
+ depthStencilState.back.passOp = VK_STENCIL_OP_REPLACE;
+ depthStencilState.back.compareMask = 0xff;
+ depthStencilState.back.writeMask = 0xff;
+ depthStencilState.back.reference = 1;
+ depthStencilState.front = depthStencilState.back;
+
+ VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.stencil));
+
+ // Outline pass
+ depthStencilState.back.compareOp = VK_COMPARE_OP_NOT_EQUAL;
+ depthStencilState.back.failOp = VK_STENCIL_OP_KEEP;
+ depthStencilState.back.depthFailOp = VK_STENCIL_OP_KEEP;
+ depthStencilState.back.passOp = VK_STENCIL_OP_REPLACE;
+ depthStencilState.front = depthStencilState.back;
+ depthStencilState.depthTestEnable = VK_FALSE;
+
+ shaderStages[0] = loadShader(getAssetPath() + "shaders/stencilbuffer/outline.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
+ shaderStages[1] = loadShader(getAssetPath() + "shaders/stencilbuffer/outline.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
+ VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.outline));
+ }
+
+ // Prepare and initialize uniform buffer containing shader uniforms
+ void prepareUniformBuffers()
+ {
+ // Mesh vertex shader uniform buffer block
+ VK_CHECK_RESULT(vulkanDevice->createBuffer(
+ VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+ &uniformBufferVS,
+ sizeof(uboVS)));
+
+ // Map persistent
+ VK_CHECK_RESULT(uniformBufferVS.map());
+
+ updateUniformBuffers();
+ }
+
+ void updateUniformBuffers()
+ {
+ uboVS.projection = camera.matrices.perspective;
+ uboVS.model = camera.matrices.view;
+ memcpy(uniformBufferVS.mapped, &uboVS, sizeof(uboVS));
+ }
+
+ void draw()
+ {
+ VulkanExampleBase::prepareFrame();
+
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
+ VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
+
+ VulkanExampleBase::submitFrame();
+ }
+
+ void prepare()
+ {
+ VulkanExampleBase::prepare();
+ loadAssets();
+ prepareUniformBuffers();
+ setupDescriptorSetLayout();
+ preparePipelines();
+ setupDescriptorPool();
+ setupDescriptorSet();
+ buildCommandBuffers();
+ prepared = true;
+ }
+
+ virtual void render()
+ {
+ if (!prepared)
+ return;
+ draw();
+ }
+
+ virtual void viewChanged()
+ {
+ updateUniformBuffers();
+ }
+
+ virtual void changeOutlineWidth(float delta)
+ {
+ if (uboVS.outlineWidth + delta > 0.01f) {
+ uboVS.outlineWidth += delta;
+ updateUniformBuffers();
+ }
+ }
+
+ virtual void keyPressed(uint32_t keyCode)
+ {
+ switch (keyCode)
+ {
+ case KEY_KPADD:
+ case GAMEPAD_BUTTON_R1:
+ changeOutlineWidth(0.01f);
+ break;
+ case KEY_KPSUB:
+ case GAMEPAD_BUTTON_L1:
+ changeOutlineWidth(-0.01f);
+ break;
+ }
+ }
+
+ virtual void getOverlayText(VulkanTextOverlay *textOverlay)
+ {
+#if defined(__ANDROID__)
+ textOverlay->addText("\"L1/R1\" to change outline width", 5.0f, 85.0f, VulkanTextOverlay::alignLeft);
+#else
+ textOverlay->addText("\"NUMPAD +/-\" to outline width", 5.0f, 85.0f, VulkanTextOverlay::alignLeft);
+#endif
+ }
+};
+
+VULKAN_EXAMPLE_MAIN()
diff --git a/stencilbuffer/stencilbuffer.vcxproj b/stencilbuffer/stencilbuffer.vcxproj
new file mode 100644
index 00000000..d34ccc13
--- /dev/null
+++ b/stencilbuffer/stencilbuffer.vcxproj
@@ -0,0 +1,101 @@
+
+
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {B154F271-9F07-4788-B563-E36DA74ED6F5}
+ Win32Proj
+ 8.1
+
+
+
+ Application
+ true
+ v140
+
+
+ Application
+ false
+ v140
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\bin\
+ $(SolutionDir)\bin\intermediate\$(ProjectName)\$(ConfigurationName)
+
+
+ true
+ $(SolutionDir)\bin\
+ $(SolutionDir)\bin\intermediate\$(ProjectName)\$(ConfigurationName)
+
+
+
+ WIN32;_DEBUG;_WINDOWS;VK_USE_PLATFORM_WIN32_KHR;_USE_MATH_DEFINES;NOMINMAX;%(PreprocessorDefinitions)
+ MultiThreadedDebugDLL
+ Level3
+ ProgramDatabase
+ Disabled
+ ..\base;..\external\glm;..\external\gli;..\external\assimp;..\external;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ true
+ Windows
+ ..\libs\vulkan\vulkan-1.lib;..\libs\assimp\assimp.lib;%(AdditionalDependencies)
+
+
+
+
+ WIN32;NDEBUG;_WINDOWS;VK_USE_PLATFORM_WIN32_KHR;_USE_MATH_DEFINES;NOMINMAX;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ Level3
+ ProgramDatabase
+ ..\base;..\external\glm;..\external\gli;..\external\assimp;..\external;%(AdditionalIncludeDirectories)
+
+
+ true
+ Windows
+ true
+ true
+ ..\libs\vulkan\vulkan-1.lib;..\libs\assimp\assimp.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/stencilbuffer/stencilbuffer.vcxproj.filters b/stencilbuffer/stencilbuffer.vcxproj.filters
new file mode 100644
index 00000000..bd059c00
--- /dev/null
+++ b/stencilbuffer/stencilbuffer.vcxproj.filters
@@ -0,0 +1,59 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+ {48c6f71e-9013-4586-8584-1d35c10fc728}
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders
+
+
+
\ No newline at end of file
diff --git a/vulkanExamples.sln b/vulkanExamples.sln
index 97156091..1bec7321 100644
--- a/vulkanExamples.sln
+++ b/vulkanExamples.sln
@@ -153,6 +153,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pbrtexture", "pbrtexture\pb
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "computecloth", "computecloth\computecloth.vcxproj", "{12ACF921-90B1-44D9-AF06-B5C0F0B8191A}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stencilbuffer", "stencilbuffer\stencilbuffer.vcxproj", "{B154F271-9F07-4788-B563-E36DA74ED6F5}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -375,6 +377,10 @@ Global
{12ACF921-90B1-44D9-AF06-B5C0F0B8191A}.Debug|x64.Build.0 = Debug|x64
{12ACF921-90B1-44D9-AF06-B5C0F0B8191A}.Release|x64.ActiveCfg = Release|x64
{12ACF921-90B1-44D9-AF06-B5C0F0B8191A}.Release|x64.Build.0 = Release|x64
+ {B154F271-9F07-4788-B563-E36DA74ED6F5}.Debug|x64.ActiveCfg = Debug|x64
+ {B154F271-9F07-4788-B563-E36DA74ED6F5}.Debug|x64.Build.0 = Debug|x64
+ {B154F271-9F07-4788-B563-E36DA74ED6F5}.Release|x64.ActiveCfg = Release|x64
+ {B154F271-9F07-4788-B563-E36DA74ED6F5}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE