Skip to content

Commit

Permalink
Implemented normal mapping demo
Browse files Browse the repository at this point in the history
  • Loading branch information
vcoda committed Jul 23, 2020
1 parent a68e104 commit 1165af6
Show file tree
Hide file tree
Showing 18 changed files with 632 additions and 19 deletions.
15 changes: 15 additions & 0 deletions aggregated-graphics-samples.sln
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shadowmapping-poisson-stabl
{67B01ECD-2613-4FA0-84F7-87F5BCF40EB1} = {67B01ECD-2613-4FA0-84F7-87F5BCF40EB1}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "normalmapping", "normalmapping\normalmapping.vcxproj", "{0CC7CBF2-BFCD-477F-A639-5CAB35FCBA6C}"
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 @@ -138,6 +145,14 @@ Global
{DD90A343-7897-442B-9D19-7FF0676E80EB}.Release|x64.Build.0 = Release|x64
{DD90A343-7897-442B-9D19-7FF0676E80EB}.Release|x86.ActiveCfg = Release|Win32
{DD90A343-7897-442B-9D19-7FF0676E80EB}.Release|x86.Build.0 = Release|Win32
{0CC7CBF2-BFCD-477F-A639-5CAB35FCBA6C}.Debug|x64.ActiveCfg = Debug|x64
{0CC7CBF2-BFCD-477F-A639-5CAB35FCBA6C}.Debug|x64.Build.0 = Debug|x64
{0CC7CBF2-BFCD-477F-A639-5CAB35FCBA6C}.Debug|x86.ActiveCfg = Debug|Win32
{0CC7CBF2-BFCD-477F-A639-5CAB35FCBA6C}.Debug|x86.Build.0 = Debug|Win32
{0CC7CBF2-BFCD-477F-A639-5CAB35FCBA6C}.Release|x64.ActiveCfg = Release|x64
{0CC7CBF2-BFCD-477F-A639-5CAB35FCBA6C}.Release|x64.Build.0 = Release|x64
{0CC7CBF2-BFCD-477F-A639-5CAB35FCBA6C}.Release|x86.ActiveCfg = Release|Win32
{0CC7CBF2-BFCD-477F-A639-5CAB35FCBA6C}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Binary file added assets/textures/steelplate1_normal-dx.dds
Binary file not shown.
3 changes: 2 additions & 1 deletion framework/arcball.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once
#include "core/noncopyable.h"
#include "core/aligned.h"
#include "rapid/rapid.h"

/*
Expand All @@ -11,7 +12,7 @@
https://www.talisman.org/~erlkonig/misc/shoemake92-arcball.pdf
*/

class Arcball : public core::NonCopyable
class Arcball : public core::Aligned<16>, public core::NonCopyable
{
public:
Arcball(const rapid::vector2& center, float radius,
Expand Down
1 change: 1 addition & 0 deletions framework/framework.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
<ClInclude Include="shaders\common\poisson16.h" />
<ClInclude Include="shaders\common\poisson32.h" />
<ClInclude Include="shaders\common\poisson8.h" />
<ClInclude Include="shaders\common\reconstruct.h" />
<ClInclude Include="shaders\common\sRGB.h" />
<ClInclude Include="shaders\common\transforms.h" />
<ClInclude Include="textureLoader.h" />
Expand Down
3 changes: 3 additions & 0 deletions framework/framework.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@
<ClInclude Include="shaders\common\noise3d.h">
<Filter>Resource Files</Filter>
</ClInclude>
<ClInclude Include="shaders\common\reconstruct.h">
<Filter>Resource Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="arcball.cpp">
Expand Down
18 changes: 18 additions & 0 deletions framework/graphicsApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,23 @@ GraphicsApp::GraphicsApp(const AppEntry& entry, const core::tstring& caption, ui
magma::descriptors::CombinedImageSampler(8)
}));

arcball = std::shared_ptr<Trackball>(new Trackball(rapid::vector2(width/2.f, height/2.f), 300.f, false));
timer = std::make_unique<Timer>();
}

void GraphicsApp::onMouseMove(int x, int y)
{
arcball->rotate(rapid::vector2((float)x, height - (float)y));
}

void GraphicsApp::onMouseLButton(bool down, int x, int y)
{
if (down)
arcball->touch(rapid::vector2((float)x, height - (float)y));
else
arcball->release();
}

void GraphicsApp::createMultisampleFramebuffer(VkFormat colorFormat)
{
const VkFormat depthFormat = utilities::getSupportedDepthFormat(physicalDevice, false, true);
Expand Down Expand Up @@ -216,6 +230,8 @@ std::shared_ptr<magma::GraphicsPipeline> GraphicsApp::createFullscreenPipeline(c

void GraphicsApp::updateViewProjTransforms()
{
viewProj->updateView();
viewProj->updateProjection();
magma::helpers::mapScoped<ViewProjTransforms>(viewProjTransforms,
[this](auto *transforms)
{
Expand Down Expand Up @@ -252,6 +268,8 @@ void GraphicsApp::updateObjectTransforms(const std::vector<rapid::matrix, core::

void GraphicsApp::updateLightSource()
{
lightViewProj->updateView();
lightViewProj->updateProjection();
magma::helpers::mapScoped<LightSource>(lightSource,
[this](auto *light)
{
Expand Down
4 changes: 4 additions & 0 deletions framework/graphicsApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
#include "core/alignedAllocator.h"
#include "common.h"
#include "viewProjection.h"
#include "arcball.h"
#include "timer.h"

class GraphicsApp : public VulkanApp
{
public:
GraphicsApp(const AppEntry& entry, const core::tstring& caption,
uint32_t width, uint32_t height, bool sRGB);
virtual void onMouseMove(int x, int y) override;
virtual void onMouseLButton(bool down, int x, int y) override;

protected:
virtual void createMultisampleFramebuffer(VkFormat colorFormat);
Expand Down Expand Up @@ -71,5 +74,6 @@ class GraphicsApp : public VulkanApp
std::shared_ptr<magma::Sampler> trilinearClampToEdge;
std::shared_ptr<magma::Sampler> anisotropicClampToEdge;

std::shared_ptr<Arcball> arcball;
std::unique_ptr<Timer> timer;
};
7 changes: 7 additions & 0 deletions framework/shaders/common/reconstruct.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
vec3 reconstructNormal(vec2 xy)
{
vec3 n;
n.xy = xy;
n.z = sqrt(1. - dot(xy, xy));
return normalize(n);
}
100 changes: 84 additions & 16 deletions framework/textureLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,106 @@ static VkFormat blockCompressedFormat(const gliml::context& ctx)
}
}

static void loadBC5SignedNorm(const gliml::dds_header *hdr, VkExtent2D& extent, magma::Image::MipmapLayout& mipOffsets, VkDeviceSize& baseMipOffset)
{
const unsigned char* dataBytePtr = (const unsigned char *)hdr;
dataBytePtr += sizeof(gliml::dds_header);

constexpr int MaxNumMipmaps = 16;
struct Face {
int numMipmaps;
struct mipmap {
int width;
int height;
int depth;
int size;
const void* data;
} mipmaps[MaxNumMipmaps];
} face;

face.numMipmaps = (hdr->dwMipMapCount == 0) ? 1 : hdr->dwMipMapCount;
// For each mipmap
for (int mipIndex = 0; mipIndex < face.numMipmaps; mipIndex++)
{
Face::mipmap& curMip = face.mipmaps[mipIndex];
// mipmap dimensions
int w = hdr->dwWidth >> mipIndex;
if (w <= 0) w = 1;
int h = hdr->dwHeight >> mipIndex;
if (h <= 0) h = 1;
int d = hdr->dwDepth >> mipIndex;
if (d <= 0) d = 1;
curMip.width = w;
curMip.height = h;
curMip.depth = d;
// Mipmap byte size
constexpr int bytesPerElement = 16;
curMip.size = ((w + 3) / 4) * ((h + 3) / 4) * d * bytesPerElement;
// Set and advance surface data pointer
curMip.data = dataBytePtr;
dataBytePtr += curMip.size;
}

extent.width = static_cast<uint32_t>(face.mipmaps[0].width);
extent.height = static_cast<uint32_t>(face.mipmaps[0].height);
for (int level = 1; level < face.numMipmaps; ++level)
{ // Compute relative offset
const intptr_t mipOffset = (const uint8_t *)face.mipmaps[level].data - (const uint8_t *)face.mipmaps[level - 1].data;
mipOffsets.push_back(mipOffset);
}
// Skip DDS header
baseMipOffset = (const uint8_t *)face.mipmaps[0].data - (const uint8_t *)hdr;
}

std::shared_ptr<magma::ImageView> loadDxtTexture(std::shared_ptr<magma::CommandBuffer> cmdCopy, const std::string& filename)
{
std::ifstream file("../assets/textures/" + filename, std::ios::in | std::ios::binary | std::ios::ate);
if (!file.is_open())
throw std::runtime_error("failed to open file ../assets/textures/\"" + filename + "\"");
throw std::runtime_error("failed to open file \"../assets/textures/" + filename + "\"");
const std::streamoff size = file.tellg();
file.seekg(0, std::ios::beg);
gliml::context ctx;
VkFormat format;
VkExtent2D extent;
VkDeviceSize baseMipOffset = 0;
magma::Image::MipmapLayout mipOffsets(1, 0);
std::shared_ptr<magma::SrcTransferBuffer> buffer = std::make_shared<magma::SrcTransferBuffer>(cmdCopy->getDevice(), size);
magma::helpers::mapScoped<uint8_t>(buffer, [&](uint8_t *data)
{ // Read data to buffer
file.read(reinterpret_cast<char *>(data), size);
file.close();
ctx.enable_dxt(true);
if (!ctx.load(data, static_cast<unsigned>(size)))
if (ctx.load(data, static_cast<unsigned>(size)))
{ // Setup texture data description
format = blockCompressedFormat(ctx);
extent.width = static_cast<uint32_t>(ctx.image_width(0, 0));
extent.height = static_cast<uint32_t>(ctx.image_height(0, 0));
for (int level = 1; level < ctx.num_mipmaps(0); ++level)
{ // Compute relative offset
const intptr_t mipOffset = (const uint8_t *)ctx.image_data(0, level) - (const uint8_t *)ctx.image_data(0, level - 1);
mipOffsets.push_back(mipOffset);
}
// Skip DDS header
baseMipOffset = (const uint8_t *)ctx.image_data(0, 0) - data;
}
else if (ctx.error() == GLIML_ERROR_INVALID_COMPRESSED_FORMAT)
{ // Not supported, proceed ourself
const gliml::dds_header *hdr = (const gliml::dds_header *)data;
switch (hdr->ddspf.dwFourCC)
{
case MAKEFOURCC('B', 'C', '5', 'S'): // ATI1
format = VK_FORMAT_BC5_SNORM_BLOCK;
loadBC5SignedNorm(hdr, extent, mipOffsets, baseMipOffset);
break;
default:
throw std::runtime_error("unknown compressed format");
}
}
else
{
throw std::runtime_error("failed to load DDS texture");
// Skip DDS header
baseMipOffset = reinterpret_cast<const uint8_t *>(ctx.image_data(0, 0)) - data;
}
});
// Setup texture data description
const VkFormat format = blockCompressedFormat(ctx);
const VkExtent2D extent = {
static_cast<uint32_t>(ctx.image_width(0, 0)),
static_cast<uint32_t>(ctx.image_height(0, 0))
};
magma::Image::MipmapLayout mipOffsets(1, 0);
for (int level = 1; level < ctx.num_mipmaps(0); ++level)
{ // Compute relative offset
const intptr_t mipOffset = (const uint8_t *)ctx.image_data(0, level) - (const uint8_t *)ctx.image_data(0, level - 1);
mipOffsets.push_back(mipOffset);
}
// Upload texture data from buffer
magma::Image::CopyLayout bufferLayout{baseMipOffset, 0, 0};
std::shared_ptr<magma::Image2D> image = std::make_shared<magma::Image2D>(cmdCopy,
Expand Down
2 changes: 1 addition & 1 deletion framework/viewProjection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

ViewProjection::ViewProjection(bool lhs) noexcept:
lhs(lhs),
eyePos(0.f, 0.f, 0.f),
eyePos(0.f, 0.f, -1.f),
focusPos(0.f, 0.f, 0.f)
{}

Expand Down
2 changes: 1 addition & 1 deletion framework/viewProjection.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class ViewProjection : public core::Aligned<16>, public core::NonCopyable
bool lhs;
rapid::float3 eyePos;
rapid::float3 focusPos;
float fieldOfView = 0.f;
float fieldOfView = 45.f;
float aspectRatio = 1.f;
float zNear = 0.1f;
float zFar = 100.f;
Expand Down
Loading

0 comments on commit 1165af6

Please sign in to comment.