Skip to content

Commit

Permalink
Implemented displacement mapping demo
Browse files Browse the repository at this point in the history
  • Loading branch information
vcoda committed Jul 26, 2020
1 parent f7a82b6 commit 631986e
Show file tree
Hide file tree
Showing 14 changed files with 664 additions and 0 deletions.
15 changes: 15 additions & 0 deletions aggregated-graphics-samples.sln
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bumpmapping", "bumpmapping\
{67B01ECD-2613-4FA0-84F7-87F5BCF40EB1} = {67B01ECD-2613-4FA0-84F7-87F5BCF40EB1}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "displacement-mapping", "displacement-mapping\displacement-mapping.vcxproj", "{6642AD41-5A38-45DC-9646-A265B73E0858}"
ProjectSection(ProjectDependencies) = postProject
{8D9D4A3E-439A-4210-8879-259B20D992CA} = {8D9D4A3E-439A-4210-8879-259B20D992CA}
{51CC36B3-921E-4853-ACD5-CB6CBC27FBA1} = {51CC36B3-921E-4853-ACD5-CB6CBC27FBA1}
{67B01ECD-2613-4FA0-84F7-87F5BCF40EB1} = {67B01ECD-2613-4FA0-84F7-87F5BCF40EB1}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Expand Down Expand Up @@ -168,6 +175,14 @@ Global
{7399BABD-C433-4275-A9DD-7663241B31BE}.Release|x64.Build.0 = Release|x64
{7399BABD-C433-4275-A9DD-7663241B31BE}.Release|x86.ActiveCfg = Release|Win32
{7399BABD-C433-4275-A9DD-7663241B31BE}.Release|x86.Build.0 = Release|Win32
{6642AD41-5A38-45DC-9646-A265B73E0858}.Debug|x64.ActiveCfg = Debug|x64
{6642AD41-5A38-45DC-9646-A265B73E0858}.Debug|x64.Build.0 = Debug|x64
{6642AD41-5A38-45DC-9646-A265B73E0858}.Debug|x86.ActiveCfg = Debug|Win32
{6642AD41-5A38-45DC-9646-A265B73E0858}.Debug|x86.Build.0 = Debug|Win32
{6642AD41-5A38-45DC-9646-A265B73E0858}.Release|x64.ActiveCfg = Release|x64
{6642AD41-5A38-45DC-9646-A265B73E0858}.Release|x64.Build.0 = Release|x64
{6642AD41-5A38-45DC-9646-A265B73E0858}.Release|x86.ActiveCfg = Release|Win32
{6642AD41-5A38-45DC-9646-A265B73E0858}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Binary file added assets/textures/stucco1_normal_height.dds
Binary file not shown.
271 changes: 271 additions & 0 deletions displacement-mapping/displacement-mapping.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
#include "graphicsApp.h"
#include "textureLoader.h"
#include "colorTable.h"
#include "quadric/include/torus.h"
#include "quadric/include/sphere.h"

class DisplacementMapping : public GraphicsApp
{
struct Constants
{
VkBool32 showNormals;
};

struct alignas(16) Parameters
{
rapid::float4a screenSize; // x, y, 1/x, 1/y
float displacement;
};

std::unique_ptr<quadric::Torus> torus;
std::unique_ptr<quadric::Sphere> dot;
std::shared_ptr<magma::ImageView> displacementMap;
std::shared_ptr<magma::UniformBuffer<Parameters>> parameters;
std::shared_ptr<magma::DynamicUniformBuffer<PhongMaterial>> material;
std::shared_ptr<magma::GraphicsPipeline> displacementPipeline;
std::shared_ptr<magma::GraphicsPipeline> fillPipeline;
DescriptorSet displacementDescriptor;
DescriptorSet fillDescriptor;

Constants constants = {false};
float displacement = 0.35f;

public:
explicit DisplacementMapping(const AppEntry& entry):
GraphicsApp(entry, TEXT("Displacement mapping"), 1280, 720, true)
{
setupViewProjection();
setupMaterials();
updateParameters();
createTransformBuffer(2);
createMeshObjects();
loadDisplacementMap();
setupDescriptorSets();
setupGraphicsPipelines();

renderScene(drawCmdBuffer);
blit(msaaFramebuffer->getColorView(), FrontBuffer);
blit(msaaFramebuffer->getColorView(), BackBuffer);
}

virtual void render(uint32_t bufferIndex) override
{
updateTransforms();
submitCommandBuffers(bufferIndex);
std::this_thread::sleep_for(std::chrono::milliseconds(2)); // Cap fps
}

virtual void onKeyDown(char key, int repeat, uint32_t flags) override
{
constexpr float step = 0.1f;
switch (key)
{
case AppKey::Left:
lightViewProj->translate(-step, 0.f, 0.f);
break;
case AppKey::Right:
lightViewProj->translate(step, 0.f, 0.f);
break;
case AppKey::Up:
lightViewProj->translate(0.f, step, 0.f);
break;
case AppKey::Down:
lightViewProj->translate(0.f, -step, 0.f);
break;
case AppKey::PgUp:
lightViewProj->translate(0.f, 0.f, step);
break;
case AppKey::PgDn:
lightViewProj->translate(0.f, 0.f, -step);
break;
case AppKey::Home:
if (displacement < 0.5f)
{
displacement += 0.01f;
updateParameters();
}
break;
case AppKey::End:
if (displacement >= 0.21f)
{
displacement -= 0.01f;
updateParameters();
}
break;
case AppKey::Space:
constants.showNormals = !constants.showNormals;
setupGraphicsPipelines();
renderScene(drawCmdBuffer);
break;
}
updateTransforms();
updateLightSource();
VulkanApp::onKeyDown(key, repeat, flags);
}

virtual void onMouseWheel(float distance) override
{
float step = distance * 0.2f;
float z = viewProj->getPosition().z;
if ((z + step < -2.5f) && (z + step > -15.f))
viewProj->translate(0.f, 0.f, step);
updateViewProjTransforms();
}

virtual void updateLightSource()
{
magma::helpers::mapScoped<LightSource>(lightSource,
[this](auto *light)
{
constexpr float ambientFactor = 0.4f;
light->viewPosition = viewProj->getView() * lightViewProj->getPosition();
light->ambient = ghost_white * ambientFactor;
light->diffuse = ghost_white;
light->specular = ghost_white;
});
}

void updateTransforms()
{
rapid::matrix lightTransform = rapid::translation(rapid::vector3(lightViewProj->getPosition()));
const std::vector<rapid::matrix, core::aligned_allocator<rapid::matrix>> transforms = {
arcball->transform(),
lightTransform
};
updateObjectTransforms(transforms);
}

void updateParameters()
{
if (!parameters)
parameters = std::make_shared<magma::UniformBuffer<Parameters>>(device);
magma::helpers::mapScoped<Parameters>(parameters,
[this](auto *parameters)
{
parameters->screenSize = rapid::float4a(float(width), float(height), 1.f/width, 1.f/height);
parameters->displacement = displacement;
});
}

void setupViewProjection()
{
viewProj = std::make_unique<LeftHandedViewProjection>();
viewProj->setPosition(0.f, 0.f, -4.f);
viewProj->setFocus(0.f, 0.f, 0.f);
viewProj->setFieldOfView(60.f);
viewProj->setNearZ(1.f);
viewProj->setFarZ(100.f);
viewProj->setAspectRatio(width / (float)height);
viewProj->updateView();
viewProj->updateProjection();

lightViewProj = std::make_unique<LeftHandedViewProjection>();
lightViewProj->setPosition(-1., 2.f, -1.f);

updateViewProjTransforms();
}

void setupMaterials()
{
material = std::make_shared<magma::DynamicUniformBuffer<PhongMaterial>>(device, 1);
magma::helpers::mapScoped<PhongMaterial>(material,
[this](magma::helpers::AlignedUniformArray<PhongMaterial>& materials)
{
constexpr float ambientFactor = 0.4f;
materials[0].ambient = azure * ambientFactor;
materials[0].diffuse = azure;
materials[0].specular = alice_blue;
materials[0].shininess = 64.f;
});
}

void createMeshObjects()
{
torus = std::make_unique<quadric::Torus>(0.2f, 1.0f, 128, 128, true, cmdCopyBuf);
dot = std::make_unique<quadric::Sphere>(0.02f, 8, 8, true, cmdCopyBuf);
}

void loadDisplacementMap()
{ // https://freepbr.com/materials/stucco-1/
displacementMap = loadDxtTexture(cmdCopyImg, "stucco1_normal_height.dds");
}

void setupDescriptorSets()
{
displacementDescriptor.layout = std::shared_ptr<magma::DescriptorSetLayout>(new magma::DescriptorSetLayout(device,
{
magma::bindings::VertexFragmentStageBinding(0, magma::descriptors::DynamicUniformBuffer(1)),
magma::bindings::FragmentStageBinding(1, magma::descriptors::UniformBuffer(1)),
magma::bindings::FragmentStageBinding(2, magma::descriptors::UniformBuffer(1)),
magma::bindings::FragmentStageBinding(3, magma::descriptors::DynamicUniformBuffer(1)),
magma::bindings::VertexFragmentStageBinding(4, magma::descriptors::UniformBuffer(1)),
magma::bindings::VertexFragmentStageBinding(5, magma::descriptors::CombinedImageSampler(1))
}));
displacementDescriptor.set = descriptorPool->allocateDescriptorSet(displacementDescriptor.layout);
displacementDescriptor.set->update(0, transforms);
displacementDescriptor.set->update(1, viewProjTransforms);
displacementDescriptor.set->update(2, lightSource);
displacementDescriptor.set->update(3, material);
displacementDescriptor.set->update(4, parameters);
displacementDescriptor.set->update(5, displacementMap, anisotropicClampToEdge);

fillDescriptor.layout = std::shared_ptr<magma::DescriptorSetLayout>(new magma::DescriptorSetLayout(device,
{
magma::bindings::VertexStageBinding(0, magma::descriptors::DynamicUniformBuffer(1))
}));
fillDescriptor.set = descriptorPool->allocateDescriptorSet(fillDescriptor.layout);
fillDescriptor.set->update(0, transforms);
}

void setupGraphicsPipelines()
{
std::shared_ptr<magma::Specialization> specialization(new magma::Specialization(constants,
{
magma::SpecializationEntry(0, &Constants::showNormals)
}
));
displacementPipeline = createCommonSpecializedPipeline(
"displace.o", "phong.o",
std::move(specialization),
torus->getVertexInput(),
displacementDescriptor.layout);
if (!fillPipeline)
{
fillPipeline = createCommonPipeline(
"transform.o", "fill.o",
dot->getVertexInput(),
fillDescriptor.layout);
}
}

void renderScene(std::shared_ptr<magma::CommandBuffer> cmdBuffer)
{
cmdBuffer->begin();
{
cmdBuffer->beginRenderPass(msaaFramebuffer->getRenderPass(), msaaFramebuffer->getFramebuffer(),
{
magma::ClearColor(0.1f, 0.243f, 0.448f, 1.f),
magma::clears::depthOne
});
{
cmdBuffer->bindPipeline(displacementPipeline);
cmdBuffer->bindDescriptorSet(displacementPipeline, displacementDescriptor.set,
{
transforms->getDynamicOffset(0),
material->getDynamicOffset(0)
});
torus->draw(cmdBuffer);
cmdBuffer->bindPipeline(fillPipeline);
cmdBuffer->bindDescriptorSet(fillPipeline, fillDescriptor.set, transforms->getDynamicOffset(1));
dot->draw(cmdBuffer);
}
cmdBuffer->endRenderPass();
}
cmdBuffer->end();
}
};

std::unique_ptr<IApplication> appFactory(const AppEntry& entry)
{
return std::unique_ptr<DisplacementMapping>(new DisplacementMapping(entry));
}
Loading

0 comments on commit 631986e

Please sign in to comment.