<|start_filename|>MSAAFilter/MSAAFilter.cpp<|end_filename|>
//=================================================================================================
//
//  MSAA Filtering 2.0 Sample
//  by MJP
//  http://mynameismjp.wordpress.com/
//
//  All code licensed under the MIT license
//
//=================================================================================================

#include <PCH.h>

#include "MSAAFilter.h"
#include "SharedConstants.h"

#include "resource.h"
#include <InterfacePointers.h>
#include <Window.h>
#include <Graphics\\DeviceManager.h>
#include <Input.h>
#include <Graphics\\SpriteRenderer.h>
#include <Graphics\\Model.h>
#include <Utility.h>
#include <Graphics\\Camera.h>
#include <Graphics\\ShaderCompilation.h>
#include <Graphics\\Profiler.h>
#include <Graphics\\Textures.h>
#include <Graphics\\Sampling.h>

using namespace SampleFramework11;
using std::wstring;

static const float NearClip = 0.01f;
static const float FarClip = 100.0f;

static const float ModelScales[uint64(Scenes::NumValues)] = { 0.1f, 1.0f, 1.0f, 5.0f, 0.01f, };
static const Float3 ModelPositions[uint64(Scenes::NumValues)] = { Float3(-1.0f, 2.0f, 0.0f), Float3(0.0f, 0.0f, 0.0f), Float3(0.0f, 0.0f, 0.0f), Float3(0.0f, 0.0f, 0.0f), Float3(0.0f, 0.0f, 0.0f) };

// Model filenames
static const wchar* ModelPaths[uint64(Scenes::NumValues)] =
{
    L"..\\Content\\Models\\RoboHand\\RoboHand.meshdata",
    nullptr,
    nullptr,
    L"..\\Content\\Models\\Soldier\\Soldier.sdkmesh",
    L"..\\Content\\Models\\Tower\\Tower.sdkmesh",
};

static const wchar* ModelNormalMapSuffix[uint64(Scenes::NumValues)] =
{
    nullptr,
    nullptr,
    nullptr,
    L"_norm",
    nullptr
};

MSAAFilter::MSAAFilter() :  App(L"MSAA Filtering 2.0", MAKEINTRESOURCEW(IDI_DEFAULT)),
                            camera(16.0f / 9.0f, Pi_4 * 0.75f, NearClip, FarClip)
{
    deviceManager.SetMinFeatureLevel(D3D_FEATURE_LEVEL_11_0);
}

void MSAAFilter::BeforeReset()
{
    App::BeforeReset();
}

void MSAAFilter::AfterReset()
{
    App::AfterReset();

    float aspect = static_cast<float>(deviceManager.BackBufferWidth()) / deviceManager.BackBufferHeight();
    camera.SetAspectRatio(aspect);

    CreateRenderTargets();

    meshRenderer.CreateReductionTargets(deviceManager.BackBufferWidth(), deviceManager.BackBufferHeight());

    postProcessor.AfterReset(deviceManager.BackBufferWidth(), deviceManager.BackBufferHeight());
}

void MSAAFilter::Initialize()
{
    App::Initialize();

    ID3D11DevicePtr device = deviceManager.Device();
    ID3D11DeviceContextPtr deviceContext = deviceManager.ImmediateContext();

    // Create a font + SpriteRenderer
    font.Initialize(L"Arial", 18, SpriteFont::Regular, true, device);
    spriteRenderer.Initialize(device);

    // Camera setup
    camera.SetPosition(Float3(0.0f, 2.5f, -10.0f));

    // Load the scenes
    for(uint64 i = 0; i < uint64(Scenes::NumValues); ++i)
    {
        if(i == uint64(Scenes::BrickPlane))
            models[i].GeneratePlaneScene(device, Float2(10.0f, 10.0f), Float3(), Quaternion(),
                                         L"Bricks.dds", L"Bricks_NML.dds");
        else if(i == uint64(Scenes::UIPlane))
            models[i].GeneratePlaneScene(device, Float2(10.0f, 10.0f), Float3(), Quaternion(),
                                         L"UI.png", L"");
        else if(i == uint64(Scenes::RoboHand))
            models[i].CreateFromMeshData(device, ModelPaths[i]);
        else
            models[i].CreateFromSDKMeshFile(device, ModelPaths[i], ModelNormalMapSuffix[i], true);
    }

    modelOrientations[uint64(Scenes::RoboHand)] = Quaternion(0.41f, -0.55f, -0.29f, 0.67f);
    AppSettings::ModelOrientation.SetValue(modelOrientations[AppSettings::CurrentScene]);

    meshRenderer.Initialize(device, deviceManager.ImmediateContext());
    meshRenderer.SetModel(&models[AppSettings::CurrentScene]);
    skybox.Initialize(device);

    envMap = LoadTexture(device, L"..\\Content\\EnvMaps\\Ennis.dds");

    FileReadSerializer serializer(L"..\\Content\\EnvMaps\\Ennis.shdata");
    SerializeItem(serializer, envMapSH);

    // Load shaders
    for(uint32 msaaMode = 0; msaaMode < uint32(MSAAModes::NumValues); ++msaaMode)
    {
        CompileOptions opts;
        opts.Add("MSAASamples_", AppSettings::NumMSAASamples(MSAAModes(msaaMode)));
        resolvePS[msaaMode] = CompilePSFromFile(device, L"Resolve.hlsl", "ResolvePS", "ps_5_0", opts);
    }

    resolveVS = CompileVSFromFile(device, L"Resolve.hlsl", "ResolveVS");

    backgroundVelocityVS = CompileVSFromFile(device, L"BackgroundVelocity.hlsl", "BackgroundVelocityVS");
    backgroundVelocityPS = CompilePSFromFile(device, L"BackgroundVelocity.hlsl", "BackgroundVelocityPS");

    resolveConstants.Initialize(device);
    backgroundVelocityConstants.Initialize(device);

    // Init the post processor
    postProcessor.Initialize(device);
}

// Creates all required render targets
void MSAAFilter::CreateRenderTargets()
{
    ID3D11Device* device = deviceManager.Device();
    uint32 width = deviceManager.BackBufferWidth();
    uint32 height = deviceManager.BackBufferHeight();

    const uint32 NumSamples = AppSettings::NumMSAASamples();
    const uint32 Quality = NumSamples > 0 ? D3D11_STANDARD_MULTISAMPLE_PATTERN : 0;
    colorTarget.Name = "colorTarget";
    colorTarget.Initialize(device, width, height, DXGI_FORMAT_R16G16B16A16_FLOAT, 1, NumSamples, Quality);
    depthBuffer.Name = "depthBuffer";
    depthBuffer.Initialize(device, width, height, DXGI_FORMAT_D32_FLOAT, true, NumSamples, Quality);
    velocityTarget.Name = "velocityBuffer";
    velocityTarget.Initialize(device, width, height, DXGI_FORMAT_R16G16_SNORM, true, NumSamples, Quality);

    if(resolveTarget.Width != width || resolveTarget.Height != height)
    {
       resolveTarget.Name = "resolveTarget";
        resolveTarget.Initialize(device, width, height, colorTarget.Format);
       prevFrameTarget.Name = "previousFrame";
       prevFrameTarget.Initialize(device, width, height, colorTarget.Format);

    }
}

void MSAAFilter::Update(const Timer& timer)
{
    AppSettings::UpdateUI();

    MouseState mouseState = MouseState::GetMouseState(window);
    KeyboardState kbState = KeyboardState::GetKeyboardState(window);

    if(kbState.IsKeyDown(KeyboardState::Escape))
        window.Destroy();

    float CamMoveSpeed = 5.0f * timer.DeltaSecondsF();
    const float CamRotSpeed = 0.180f * timer.DeltaSecondsF();
    const float MeshRotSpeed = 0.180f * timer.DeltaSecondsF();

    // Move the camera with keyboard input
    if(kbState.IsKeyDown(KeyboardState::LeftShift))
        CamMoveSpeed *= 0.25f;

    Float3 camPos = camera.Position();
    if(kbState.IsKeyDown(KeyboardState::W))
        camPos += camera.Forward() * CamMoveSpeed;
    else if (kbState.IsKeyDown(KeyboardState::S))
        camPos += camera.Back() * CamMoveSpeed;
    if(kbState.IsKeyDown(KeyboardState::A))
        camPos += camera.Left() * CamMoveSpeed;
    else if (kbState.IsKeyDown(KeyboardState::D))
        camPos += camera.Right() * CamMoveSpeed;
    if(kbState.IsKeyDown(KeyboardState::Q))
        camPos += camera.Up() * CamMoveSpeed;
    else if (kbState.IsKeyDown(KeyboardState::E))
        camPos += camera.Down() * CamMoveSpeed;
    camera.SetPosition(camPos);

    // Rotate the camera with the mouse
    if(mouseState.RButton.Pressed && mouseState.IsOverWindow)
    {
        float xRot = camera.XRotation();
        float yRot = camera.YRotation();
        xRot += mouseState.DY * CamRotSpeed;
        yRot += mouseState.DX * CamRotSpeed;
        camera.SetXRotation(xRot);
        camera.SetYRotation(yRot);
    }

    // Reset the camera projection
    camera.SetAspectRatio(camera.AspectRatio());
    Float2 jitter = 0.0f;
    if(AppSettings::EnableTemporalAA && AppSettings::EnableJitter() && AppSettings::UseStandardResolve == false)
    {
        if(AppSettings::JitterMode == JitterModes::Uniform2x)
        {
            jitter = frameCount % 2 == 0 ? -0.5f : 0.5f;
        }
        else if(AppSettings::JitterMode == JitterModes::Hammersley4x)
        {
            uint64 idx = frameCount % 4;
            jitter = Hammersley2D(idx, 4) * 2.0f - Float2(1.0f);
        }
        else if(AppSettings::JitterMode == JitterModes::Hammersley8x)
        {
            uint64 idx = frameCount % 8;
            jitter = Hammersley2D(idx, 8) * 2.0f - Float2(1.0f);
        }
        else if(AppSettings::JitterMode == JitterModes::Hammersley16x)
        {
            uint64 idx = frameCount % 16;
            jitter = Hammersley2D(idx, 16) * 2.0f - Float2(1.0f);
        }

        jitter *= AppSettings::JitterScale;

        const float offsetX = jitter.x * (1.0f / colorTarget.Width);
        const float offsetY = jitter.y * (1.0f / colorTarget.Height);
        Float4x4 offsetMatrix = Float4x4::TranslationMatrix(Float3(offsetX, -offsetY, 0.0f));
        camera.SetProjection(camera.ProjectionMatrix() * offsetMatrix);
    }

    jitterOffset = (jitter - prevJitter) * 0.5f;
    prevJitter = jitter;

    // Toggle VSYNC
    if(kbState.RisingEdge(KeyboardState::V))
        deviceManager.SetVSYNCEnabled(!deviceManager.VSYNCEnabled());

    deviceManager.SetNumVSYNCIntervals(AppSettings::DoubleSyncInterval ? 2 : 1);

    if(AppSettings::CurrentScene.Changed())
    {
        meshRenderer.SetModel(&models[AppSettings::CurrentScene]);
        AppSettings::ModelOrientation.SetValue(modelOrientations[AppSettings::CurrentScene]);
    }

    Quaternion orientation = AppSettings::ModelOrientation;
    orientation = orientation * Quaternion::FromAxisAngle(Float3(0.0f, 1.0f, 0.0f), AppSettings::ModelRotationSpeed * timer.DeltaSecondsF());
    AppSettings::ModelOrientation.SetValue(orientation);

    modelTransform = orientation.ToFloat4x4() * Float4x4::ScaleMatrix(ModelScales[AppSettings::CurrentScene]);
    modelTransform.SetTranslation(ModelPositions[AppSettings::CurrentScene]);
}

void MSAAFilter::RenderAA()
{
    PIXEvent pixEvent(L"MSAA Resolve + Temporal AA");
    ProfileBlock profileBlock(L"MSAA Resolve + Temporal AA");

    ID3D11DeviceContext* context = deviceManager.ImmediateContext();

    ID3D11RenderTargetView* rtvs[1] = { resolveTarget.RTView };

    context->OMSetRenderTargets(1, rtvs, nullptr);

    if(AppSettings::UseStandardResolve)
    {
        if(AppSettings::MSAAMode == 0)
            context->CopyResource(resolveTarget.Texture, colorTarget.Texture);
        else
            context->ResolveSubresource(resolveTarget.Texture, 0, colorTarget.Texture, 0, colorTarget.Format);
        return;
    }

    const uint32 SampleRadius = static_cast<uint32>((AppSettings::ResolveFilterDiameter / 2.0f) + 0.499f);
    ID3D11PixelShader* pixelShader = resolvePS[AppSettings::MSAAMode];
    context->PSSetShader(pixelShader, nullptr, 0);
    context->VSSetShader(resolveVS, nullptr, 0);

    resolveConstants.Data.TextureSize = Float2(static_cast<float>(colorTarget.Width), static_cast<float>(colorTarget.Height));
    resolveConstants.Data.SampleRadius = SampleRadius;;
    resolveConstants.ApplyChanges(context);
    resolveConstants.SetPS(context, 0);

    ID3D11ShaderResourceView* srvs[] = { colorTarget.SRView, velocityTarget.SRView, depthBuffer.SRView, prevFrameTarget.SRView};
    context->PSSetShaderResources(0, ArraySize_(srvs), srvs);

    ID3D11SamplerState* samplers[] = { samplerStates.LinearClamp(), samplerStates.Point() };
    context->PSSetSamplers(0, ArraySize_(samplers), samplers);

    ID3D11Buffer* vbs[1] = { nullptr };
    UINT strides[1] = { 0 };
    UINT offsets[1] = { 0 };
    context->IASetVertexBuffers(0, 1, vbs, strides, offsets);
    context->IASetInputLayout(nullptr);
    context->IASetIndexBuffer(nullptr, DXGI_FORMAT_R16_UINT, 0);
    context->Draw(3, 0);

    rtvs[0] = nullptr;
    context->OMSetRenderTargets(1, rtvs, nullptr);

    srvs[0] = srvs[1] = srvs[2] = nullptr;
    context->PSSetShaderResources(0, 3, srvs);

    context->CopyResource(prevFrameTarget.Texture, resolveTarget.Texture);
}

void MSAAFilter::Render(const Timer& timer)
{
    if(AppSettings::MSAAMode.Changed())
        CreateRenderTargets();

    ID3D11DeviceContextPtr context = deviceManager.ImmediateContext();

    AppSettings::UpdateCBuffer(context);

    RenderScene();

    RenderBackgroundVelocity();

    RenderAA();

    {
        // Kick off post-processing
        PIXEvent pixEvent(L"Post Processing");
        postProcessor.Render(context, resolveTarget.SRView, deviceManager.BackBuffer(), timer.DeltaSecondsF());
    }

    ID3D11RenderTargetView* renderTargets[1] = { deviceManager.BackBuffer() };
    context->OMSetRenderTargets(1, renderTargets, NULL);

    SetViewport(context, deviceManager.BackBufferWidth(), deviceManager.BackBufferHeight());

    RenderHUD();

    ++frameCount;
}

void MSAAFilter::RenderScene()
{
    PIXEvent event(L"Render Scene");

    ID3D11DeviceContextPtr context = deviceManager.ImmediateContext();

    SetViewport(context, colorTarget.Width, colorTarget.Height);

    float clearColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
    context->ClearRenderTargetView(colorTarget.RTView, clearColor);
    context->ClearRenderTargetView(velocityTarget.RTView, clearColor);
    context->ClearDepthStencilView(depthBuffer.DSView, D3D11_CLEAR_DEPTH, 1.0f, 0);

    ID3D11RenderTargetView* renderTargets[2] = { nullptr, nullptr };
    context->OMSetRenderTargets(1, renderTargets, depthBuffer.DSView);
    meshRenderer.RenderDepth(context, camera, modelTransform, false);

    meshRenderer.ReduceDepth(context, depthBuffer, camera);
    meshRenderer.RenderShadowMap(context, camera, modelTransform);

    renderTargets[0] = colorTarget.RTView;
    renderTargets[1] = velocityTarget.RTView;
    context->OMSetRenderTargets(2, renderTargets, depthBuffer.DSView);

    meshRenderer.Render(context, camera, modelTransform, envMap, envMapSH, jitterOffset);

    renderTargets[0] = colorTarget.RTView;
    renderTargets[1] = nullptr;
    context->OMSetRenderTargets(2, renderTargets, depthBuffer.DSView);

    if(AppSettings::RenderBackground)
        skybox.RenderEnvironmentMap(context, envMap, camera.ViewMatrix(), camera.ProjectionMatrix(), Float3(std::exp2(AppSettings::ExposureScale)));

    renderTargets[0] = renderTargets[1] = nullptr;
    context->OMSetRenderTargets(2, renderTargets, nullptr);
}

void MSAAFilter::RenderBackgroundVelocity()
{
    PIXEvent pixEvent(L"Render Background Velocity");

    ID3D11DeviceContextPtr context = deviceManager.ImmediateContext();

    SetViewport(context, velocityTarget.Width, velocityTarget.Height);

    // Don't use camera translation for background velocity
    FirstPersonCamera tempCamera = camera;
    tempCamera.SetPosition(Float3(0.0f, 0.0f, 0.0f));

    backgroundVelocityConstants.Data.InvViewProjection = Float4x4::Transpose(Float4x4::Invert(tempCamera.ViewProjectionMatrix()));
    backgroundVelocityConstants.Data.PrevViewProjection = Float4x4::Transpose(prevViewProjection);
    backgroundVelocityConstants.Data.RTSize.x = float(velocityTarget.Width);
    backgroundVelocityConstants.Data.RTSize.y = float(velocityTarget.Height);
    backgroundVelocityConstants.Data.JitterOffset = jitterOffset;
    backgroundVelocityConstants.ApplyChanges(context);
    backgroundVelocityConstants.SetPS(context, 0);

    prevViewProjection = tempCamera.ViewProjectionMatrix();

    float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
    context->OMSetBlendState(blendStates.BlendDisabled(), blendFactor, 0xFFFFFFFF);
    context->OMSetDepthStencilState(depthStencilStates.DepthEnabled(), 0);
    context->RSSetState(rasterizerStates.NoCull());

    ID3D11RenderTargetView* rtvs[1] = { velocityTarget.RTView };
    context->OMSetRenderTargets(1, rtvs, depthBuffer.DSView);

    context->VSSetShader(backgroundVelocityVS, nullptr, 0);
    context->PSSetShader(backgroundVelocityPS, nullptr, 0);
    context->GSSetShader(nullptr, nullptr, 0);
    context->HSSetShader(nullptr, nullptr, 0);
    context->DSSetShader(nullptr, nullptr, 0);

    ID3D11Buffer* vbs[1] = { nullptr };
    UINT strides[1] = { 0 };
    UINT offsets[1] = { 0 };
    context->IASetVertexBuffers(0, 1, vbs, strides, offsets);
    context->IASetInputLayout(nullptr);
    context->IASetIndexBuffer(nullptr, DXGI_FORMAT_R16_UINT, 0);
    context->Draw(3, 0);

    rtvs[0] = nullptr;
    context->OMSetRenderTargets(1, rtvs, nullptr);
}

void MSAAFilter::RenderHUD()
{
    PIXEvent pixEvent(L"HUD Pass");

    spriteRenderer.Begin(deviceManager.ImmediateContext(), SpriteRenderer::Point);

    Float4x4 transform = Float4x4::TranslationMatrix(Float3(25.0f, 25.0f, 0.0f));
    wstring fpsText(L"FPS: ");
    fpsText += ToString(fps) + L" (" + ToString(1000.0f / fps) + L"ms)";
    spriteRenderer.RenderText(font, fpsText.c_str(), transform, XMFLOAT4(1, 1, 0, 1));

    transform._42 += 25.0f;
    wstring vsyncText(L"VSYNC (V): ");
    vsyncText += deviceManager.VSYNCEnabled() ? L"Enabled" : L"Disabled";
    spriteRenderer.RenderText(font, vsyncText.c_str(), transform, XMFLOAT4(1, 1, 0, 1));

    Profiler::GlobalProfiler.EndFrame(spriteRenderer, font);

    spriteRenderer.End();
}

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
    MSAAFilter app;
    app.Run();
}

<|start_filename|>SampleFramework11/v1.01/App.h<|end_filename|>
//=================================================================================================
//
//  MJP's DX11 Sample Framework
//  http://mynameismjp.wordpress.com/
//
//  All code licensed under the MIT license
//
//=================================================================================================

#pragma once

#include "PCH.h"

#include "Window.h"
#include "Graphics\\DeviceManager.h"
#include "Graphics\\DeviceStates.h"
#include "Timer.h"
#include "Graphics\\SpriteFont.h"
#include "Graphics\\SpriteRenderer.h"

namespace SampleFramework11
{

class App
{

public:

    App(const wchar* appName, const wchar* iconResource = NULL);
    virtual ~App();

    int32 Run();

    void RenderText(const std::wstring& text, Float2 pos);
    void RenderCenteredText(const std::wstring& text);

protected:

    virtual void Initialize();
    virtual void Update(const Timer& timer) = 0;
    virtual void Render(const Timer& timer) = 0;

    virtual void BeforeReset();
    virtual void AfterReset();

    void Exit();
    void ToggleFullScreen(bool fullScreen);
    void CalculateFPS();

    static LRESULT OnWindowResized(void* context, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

    Window window;
    DeviceManager deviceManager;
    Timer timer;

    BlendStates blendStates;
    RasterizerStates rasterizerStates;
    DepthStencilStates depthStencilStates;
    SamplerStates samplerStates;

    SpriteFont font;
    SpriteRenderer spriteRenderer;

    static const uint32 NumTimeDeltaSamples = 64;
    float timeDeltaBuffer[NumTimeDeltaSamples];
    uint32 currentTimeDeltaSample;
    uint32 fps;

    TwBar* tweakBar;

    std::wstring applicationName;

    bool createConsole;
    bool showWindow;
    int32 returnCode;

public:

    // Accessors
    Window& Window() { return window; }
    DeviceManager& DeviceManager() { return deviceManager; }
    SpriteFont& Font() { return font; }
    SpriteRenderer& SpriteRenderer() { return spriteRenderer; }
    TwBar* TweakBar() { return tweakBar; }
};

extern App* GlobalApp;

}

<|start_filename|>SampleFramework11/v1.01/ColorConversions.cpp<|end_filename|>
//=================================================================================================
//
//  Auto Exposure CS Sample
//  by MJP
//  http://mynameismjp.wordpress.com/
//
//  All code licensed under the MIT license
//
//=================================================================================================

#include <PCH.h>

// -- my includes
#include "ColorConversions.h"

using namespace SampleFramework11;

static const int nCIESamples = 471;
const float CIE_X[nCIESamples] =
{
    // CIE X function values
    0.0001299000f, 0.0001458470f, 0.0001638021f, 0.0001840037f,
    0.0002066902f, 0.0002321000f, 0.0002607280f, 0.0002930750f,
    0.0003293880f, 0.0003699140f, 0.0004149000f, 0.0004641587f,
    0.0005189860f, 0.0005818540f, 0.0006552347f, 0.0007416000f,
    0.0008450296f, 0.0009645268f, 0.001094949f, 0.001231154f,
    0.001368000f, 0.001502050f, 0.001642328f, 0.001802382f,
    0.001995757f, 0.002236000f, 0.002535385f, 0.002892603f,
    0.003300829f, 0.003753236f, 0.004243000f, 0.004762389f,
    0.005330048f, 0.005978712f, 0.006741117f, 0.007650000f,
    0.008751373f, 0.01002888f, 0.01142170f, 0.01286901f,
    0.01431000f, 0.01570443f, 0.01714744f, 0.01878122f,
    0.02074801f, 0.02319000f, 0.02620736f, 0.02978248f,
    0.03388092f, 0.03846824f, 0.04351000f, 0.04899560f,
    0.05502260f, 0.06171880f, 0.06921200f, 0.07763000f,
    0.08695811f, 0.09717672f, 0.1084063f, 0.1207672f,
    0.1343800f, 0.1493582f, 0.1653957f, 0.1819831f,
    0.1986110f, 0.2147700f, 0.2301868f, 0.2448797f,
    0.2587773f, 0.2718079f, 0.2839000f, 0.2949438f,
    0.3048965f, 0.3137873f, 0.3216454f, 0.3285000f,
    0.3343513f, 0.3392101f, 0.3431213f, 0.3461296f,
    0.3482800f, 0.3495999f, 0.3501474f, 0.3500130f,
    0.3492870f, 0.3480600f, 0.3463733f, 0.3442624f,
    0.3418088f, 0.3390941f, 0.3362000f, 0.3331977f,
    0.3300411f, 0.3266357f, 0.3228868f, 0.3187000f,
    0.3140251f, 0.3088840f, 0.3032904f, 0.2972579f,
    0.2908000f, 0.2839701f, 0.2767214f, 0.2689178f,
    0.2604227f, 0.2511000f, 0.2408475f, 0.2298512f,
    0.2184072f, 0.2068115f, 0.1953600f, 0.1842136f,
    0.1733273f, 0.1626881f, 0.1522833f, 0.1421000f,
    0.1321786f, 0.1225696f, 0.1132752f, 0.1042979f,
    0.09564000f, 0.08729955f, 0.07930804f, 0.07171776f,
    0.06458099f, 0.05795001f, 0.05186211f, 0.04628152f,
    0.04115088f, 0.03641283f, 0.03201000f, 0.02791720f,
    0.02414440f, 0.02068700f, 0.01754040f, 0.01470000f,
    0.01216179f, 0.009919960f, 0.007967240f, 0.006296346f,
    0.004900000f, 0.003777173f, 0.002945320f, 0.002424880f,
    0.002236293f, 0.002400000f, 0.002925520f, 0.003836560f,
    0.005174840f, 0.006982080f, 0.009300000f, 0.01214949f,
    0.01553588f, 0.01947752f, 0.02399277f, 0.02910000f,
    0.03481485f, 0.04112016f, 0.04798504f, 0.05537861f,
    0.06327000f, 0.07163501f, 0.08046224f, 0.08973996f,
    0.09945645f, 0.1096000f, 0.1201674f, 0.1311145f,
    0.1423679f, 0.1538542f, 0.1655000f, 0.1772571f,
    0.1891400f, 0.2011694f, 0.2133658f, 0.2257499f,
    0.2383209f, 0.2510668f, 0.2639922f, 0.2771017f,
    0.2904000f, 0.3038912f, 0.3175726f, 0.3314384f,
    0.3454828f, 0.3597000f, 0.3740839f, 0.3886396f,
    0.4033784f, 0.4183115f, 0.4334499f, 0.4487953f,
    0.4643360f, 0.4800640f, 0.4959713f, 0.5120501f,
    0.5282959f, 0.5446916f, 0.5612094f, 0.5778215f,
    0.5945000f, 0.6112209f, 0.6279758f, 0.6447602f,
    0.6615697f, 0.6784000f, 0.6952392f, 0.7120586f,
    0.7288284f, 0.7455188f, 0.7621000f, 0.7785432f,
    0.7948256f, 0.8109264f, 0.8268248f, 0.8425000f,
    0.8579325f, 0.8730816f, 0.8878944f, 0.9023181f,
    0.9163000f, 0.9297995f, 0.9427984f, 0.9552776f,
    0.9672179f, 0.9786000f, 0.9893856f, 0.9995488f,
    1.0090892f, 1.0180064f, 1.0263000f, 1.0339827f,
    1.0409860f, 1.0471880f, 1.0524667f, 1.0567000f,
    1.0597944f, 1.0617992f, 1.0628068f, 1.0629096f,
    1.0622000f, 1.0607352f, 1.0584436f, 1.0552244f,
    1.0509768f, 1.0456000f, 1.0390369f, 1.0313608f,
    1.0226662f, 1.0130477f, 1.0026000f, 0.9913675f,
    0.9793314f, 0.9664916f, 0.9528479f, 0.9384000f,
    0.9231940f, 0.9072440f, 0.8905020f, 0.8729200f,
    0.8544499f, 0.8350840f, 0.8149460f, 0.7941860f,
    0.7729540f, 0.7514000f, 0.7295836f, 0.7075888f,
    0.6856022f, 0.6638104f, 0.6424000f, 0.6215149f,
    0.6011138f, 0.5811052f, 0.5613977f, 0.5419000f,
    0.5225995f, 0.5035464f, 0.4847436f, 0.4661939f,
    0.4479000f, 0.4298613f, 0.4120980f, 0.3946440f,
    0.3775333f, 0.3608000f, 0.3444563f, 0.3285168f,
    0.3130192f, 0.2980011f, 0.2835000f, 0.2695448f,
    0.2561184f, 0.2431896f, 0.2307272f, 0.2187000f,
    0.2070971f, 0.1959232f, 0.1851708f, 0.1748323f,
    0.1649000f, 0.1553667f, 0.1462300f, 0.1374900f,
    0.1291467f, 0.1212000f, 0.1136397f, 0.1064650f,
    0.09969044f, 0.09333061f, 0.08740000f, 0.08190096f,
    0.07680428f, 0.07207712f, 0.06768664f, 0.06360000f,
    0.05980685f, 0.05628216f, 0.05297104f, 0.04981861f,
    0.04677000f, 0.04378405f, 0.04087536f, 0.03807264f,
    0.03540461f, 0.03290000f, 0.03056419f, 0.02838056f,
    0.02634484f, 0.02445275f, 0.02270000f, 0.02108429f,
    0.01959988f, 0.01823732f, 0.01698717f, 0.01584000f,
    0.01479064f, 0.01383132f, 0.01294868f, 0.01212920f,
    0.01135916f, 0.01062935f, 0.009938846f, 0.009288422f,
    0.008678854f, 0.008110916f, 0.007582388f, 0.007088746f,
    0.006627313f, 0.006195408f, 0.005790346f, 0.005409826f,
    0.005052583f, 0.004717512f, 0.004403507f, 0.004109457f,
    0.003833913f, 0.003575748f, 0.003334342f, 0.003109075f,
    0.002899327f, 0.002704348f, 0.002523020f, 0.002354168f,
    0.002196616f, 0.002049190f, 0.001910960f, 0.001781438f,
    0.001660110f, 0.001546459f, 0.001439971f, 0.001340042f,
    0.001246275f, 0.001158471f, 0.001076430f, 0.0009999493f,
    0.0009287358f, 0.0008624332f, 0.0008007503f, 0.0007433960f,
    0.0006900786f, 0.0006405156f, 0.0005945021f, 0.0005518646f,
    0.0005124290f, 0.0004760213f, 0.0004424536f, 0.0004115117f,
    0.0003829814f, 0.0003566491f, 0.0003323011f, 0.0003097586f,
    0.0002888871f, 0.0002695394f, 0.0002515682f, 0.0002348261f,
    0.0002191710f, 0.0002045258f, 0.0001908405f, 0.0001780654f,
    0.0001661505f, 0.0001550236f, 0.0001446219f, 0.0001349098f,
    0.0001258520f, 0.0001174130f, 0.0001095515f, 0.0001022245f,
    0.00009539445f, 0.00008902390f, 0.00008307527f, 0.00007751269f,
    0.00007231304f, 0.00006745778f, 0.00006292844f, 0.00005870652f,
    0.00005477028f, 0.00005109918f, 0.00004767654f, 0.00004448567f,
    0.00004150994f, 0.00003873324f, 0.00003614203f, 0.00003372352f,
    0.00003146487f, 0.00002935326f, 0.00002737573f, 0.00002552433f,
    0.00002379376f, 0.00002217870f, 0.00002067383f, 0.00001927226f,
    0.00001796640f, 0.00001674991f, 0.00001561648f, 0.00001455977f,
    0.00001357387f, 0.00001265436f, 0.00001179723f, 0.00001099844f,
    0.00001025398f, 0.000009559646f, 0.000008912044f, 0.000008308358f,
    0.000007745769f, 0.000007221456f, 0.000006732475f, 0.000006276423f,
    0.000005851304f, 0.000005455118f, 0.000005085868f, 0.000004741466f,
    0.000004420236f, 0.000004120783f, 0.000003841716f, 0.000003581652f,
    0.000003339127f, 0.000003112949f, 0.000002902121f, 0.000002705645f,
    0.000002522525f, 0.000002351726f, 0.000002192415f, 0.000002043902f,
    0.000001905497f, 0.000001776509f, 0.000001656215f, 0.000001544022f,
    0.000001439440f, 0.000001341977f, 0.000001251141f
};

const float CIE_Y[nCIESamples] =
{
    // CIE Y function values
    0.000003917000f, 0.000004393581f, 0.000004929604f, 0.000005532136f,
    0.000006208245f, 0.000006965000f, 0.000007813219f, 0.000008767336f,
    0.000009839844f, 0.00001104323f, 0.00001239000f, 0.00001388641f,
    0.00001555728f, 0.00001744296f, 0.00001958375f, 0.00002202000f,
    0.00002483965f, 0.00002804126f, 0.00003153104f, 0.00003521521f,
    0.00003900000f, 0.00004282640f, 0.00004691460f, 0.00005158960f,
    0.00005717640f, 0.00006400000f, 0.00007234421f, 0.00008221224f,
    0.00009350816f, 0.0001061361f, 0.0001200000f, 0.0001349840f,
    0.0001514920f, 0.0001702080f, 0.0001918160f, 0.0002170000f,
    0.0002469067f, 0.0002812400f, 0.0003185200f, 0.0003572667f,
    0.0003960000f, 0.0004337147f, 0.0004730240f, 0.0005178760f,
    0.0005722187f, 0.0006400000f, 0.0007245600f, 0.0008255000f,
    0.0009411600f, 0.001069880f, 0.001210000f, 0.001362091f,
    0.001530752f, 0.001720368f, 0.001935323f, 0.002180000f,
    0.002454800f, 0.002764000f, 0.003117800f, 0.003526400f,
    0.004000000f, 0.004546240f, 0.005159320f, 0.005829280f,
    0.006546160f, 0.007300000f, 0.008086507f, 0.008908720f,
    0.009767680f, 0.01066443f, 0.01160000f, 0.01257317f,
    0.01358272f, 0.01462968f, 0.01571509f, 0.01684000f,
    0.01800736f, 0.01921448f, 0.02045392f, 0.02171824f,
    0.02300000f, 0.02429461f, 0.02561024f, 0.02695857f,
    0.02835125f, 0.02980000f, 0.03131083f, 0.03288368f,
    0.03452112f, 0.03622571f, 0.03800000f, 0.03984667f,
    0.04176800f, 0.04376600f, 0.04584267f, 0.04800000f,
    0.05024368f, 0.05257304f, 0.05498056f, 0.05745872f,
    0.06000000f, 0.06260197f, 0.06527752f, 0.06804208f,
    0.07091109f, 0.07390000f, 0.07701600f, 0.08026640f,
    0.08366680f, 0.08723280f, 0.09098000f, 0.09491755f,
    0.09904584f, 0.1033674f, 0.1078846f, 0.1126000f,
    0.1175320f, 0.1226744f, 0.1279928f, 0.1334528f,
    0.1390200f, 0.1446764f, 0.1504693f, 0.1564619f,
    0.1627177f, 0.1693000f, 0.1762431f, 0.1835581f,
    0.1912735f, 0.1994180f, 0.2080200f, 0.2171199f,
    0.2267345f, 0.2368571f, 0.2474812f, 0.2586000f,
    0.2701849f, 0.2822939f, 0.2950505f, 0.3085780f,
    0.3230000f, 0.3384021f, 0.3546858f, 0.3716986f,
    0.3892875f, 0.4073000f, 0.4256299f, 0.4443096f,
    0.4633944f, 0.4829395f, 0.5030000f, 0.5235693f,
    0.5445120f, 0.5656900f, 0.5869653f, 0.6082000f,
    0.6293456f, 0.6503068f, 0.6708752f, 0.6908424f,
    0.7100000f, 0.7281852f, 0.7454636f, 0.7619694f,
    0.7778368f, 0.7932000f, 0.8081104f, 0.8224962f,
    0.8363068f, 0.8494916f, 0.8620000f, 0.8738108f,
    0.8849624f, 0.8954936f, 0.9054432f, 0.9148501f,
    0.9237348f, 0.9320924f, 0.9399226f, 0.9472252f,
    0.9540000f, 0.9602561f, 0.9660074f, 0.9712606f,
    0.9760225f, 0.9803000f, 0.9840924f, 0.9874812f,
    0.9903128f, 0.9928116f, 0.9949501f, 0.9967108f,
    0.9980983f, 0.9991120f, 0.9997482f, 1.0000000f,
    0.9998567f, 0.9993046f, 0.9983255f, 0.9968987f,
    0.9950000f, 0.9926005f, 0.9897426f, 0.9864444f,
    0.9827241f, 0.9786000f, 0.9740837f, 0.9691712f,
    0.9638568f, 0.9581349f, 0.9520000f, 0.9454504f,
    0.9384992f, 0.9311628f, 0.9234576f, 0.9154000f,
    0.9070064f, 0.8982772f, 0.8892048f, 0.8797816f,
    0.8700000f, 0.8598613f, 0.8493920f, 0.8386220f,
    0.8275813f, 0.8163000f, 0.8047947f, 0.7930820f,
    0.7811920f, 0.7691547f, 0.7570000f, 0.7447541f,
    0.7324224f, 0.7200036f, 0.7074965f, 0.6949000f,
    0.6822192f, 0.6694716f, 0.6566744f, 0.6438448f,
    0.6310000f, 0.6181555f, 0.6053144f, 0.5924756f,
    0.5796379f, 0.5668000f, 0.5539611f, 0.5411372f,
    0.5283528f, 0.5156323f, 0.5030000f, 0.4904688f,
    0.4780304f, 0.4656776f, 0.4534032f, 0.4412000f,
    0.4290800f, 0.4170360f, 0.4050320f, 0.3930320f,
    0.3810000f, 0.3689184f, 0.3568272f, 0.3447768f,
    0.3328176f, 0.3210000f, 0.3093381f, 0.2978504f,
    0.2865936f, 0.2756245f, 0.2650000f, 0.2547632f,
    0.2448896f, 0.2353344f, 0.2260528f, 0.2170000f,
    0.2081616f, 0.1995488f, 0.1911552f, 0.1829744f,
    0.1750000f, 0.1672235f, 0.1596464f, 0.1522776f,
    0.1451259f, 0.1382000f, 0.1315003f, 0.1250248f,
    0.1187792f, 0.1127691f, 0.1070000f, 0.1014762f,
    0.09618864f, 0.09112296f, 0.08626485f, 0.08160000f,
    0.07712064f, 0.07282552f, 0.06871008f, 0.06476976f,
    0.06100000f, 0.05739621f, 0.05395504f, 0.05067376f,
    0.04754965f, 0.04458000f, 0.04175872f, 0.03908496f,
    0.03656384f, 0.03420048f, 0.03200000f, 0.02996261f,
    0.02807664f, 0.02632936f, 0.02470805f, 0.02320000f,
    0.02180077f, 0.02050112f, 0.01928108f, 0.01812069f,
    0.01700000f, 0.01590379f, 0.01483718f, 0.01381068f,
    0.01283478f, 0.01192000f, 0.01106831f, 0.01027339f,
    0.009533311f, 0.008846157f, 0.008210000f, 0.007623781f,
    0.007085424f, 0.006591476f, 0.006138485f, 0.005723000f,
    0.005343059f, 0.004995796f, 0.004676404f, 0.004380075f,
    0.004102000f, 0.003838453f, 0.003589099f, 0.003354219f,
    0.003134093f, 0.002929000f, 0.002738139f, 0.002559876f,
    0.002393244f, 0.002237275f, 0.002091000f, 0.001953587f,
    0.001824580f, 0.001703580f, 0.001590187f, 0.001484000f,
    0.001384496f, 0.001291268f, 0.001204092f, 0.001122744f,
    0.001047000f, 0.0009765896f, 0.0009111088f, 0.0008501332f,
    0.0007932384f, 0.0007400000f, 0.0006900827f, 0.0006433100f,
    0.0005994960f, 0.0005584547f, 0.0005200000f, 0.0004839136f,
    0.0004500528f, 0.0004183452f, 0.0003887184f, 0.0003611000f,
    0.0003353835f, 0.0003114404f, 0.0002891656f, 0.0002684539f,
    0.0002492000f, 0.0002313019f, 0.0002146856f, 0.0001992884f,
    0.0001850475f, 0.0001719000f, 0.0001597781f, 0.0001486044f,
    0.0001383016f, 0.0001287925f, 0.0001200000f, 0.0001118595f,
    0.0001043224f, 0.00009733560f, 0.00009084587f, 0.00008480000f,
    0.00007914667f, 0.00007385800f, 0.00006891600f, 0.00006430267f,
    0.00006000000f, 0.00005598187f, 0.00005222560f, 0.00004871840f,
    0.00004544747f, 0.00004240000f, 0.00003956104f, 0.00003691512f,
    0.00003444868f, 0.00003214816f, 0.00003000000f, 0.00002799125f,
    0.00002611356f, 0.00002436024f, 0.00002272461f, 0.00002120000f,
    0.00001977855f, 0.00001845285f, 0.00001721687f, 0.00001606459f,
    0.00001499000f, 0.00001398728f, 0.00001305155f, 0.00001217818f,
    0.00001136254f, 0.00001060000f, 0.000009885877f, 0.000009217304f,
    0.000008592362f, 0.000008009133f, 0.000007465700f, 0.000006959567f,
    0.000006487995f, 0.000006048699f, 0.000005639396f, 0.000005257800f,
    0.000004901771f, 0.000004569720f, 0.000004260194f, 0.000003971739f,
    0.000003702900f, 0.000003452163f, 0.000003218302f, 0.000003000300f,
    0.000002797139f, 0.000002607800f, 0.000002431220f, 0.000002266531f,
    0.000002113013f, 0.000001969943f, 0.000001836600f, 0.000001712230f,
    0.000001596228f, 0.000001488090f, 0.000001387314f, 0.000001293400f,
    0.000001205820f, 0.000001124143f, 0.000001048009f, 0.0000009770578f,
    0.0000009109300f, 0.0000008492513f, 0.0000007917212f, 0.0000007380904f,
    0.0000006881098f, 0.0000006415300f, 0.0000005980895f, 0.0000005575746f,
    0.0000005198080f, 0.0000004846123f, 0.0000004518100f
};

const float CIE_Z[nCIESamples] =
{
    // CIE Z function values
    0.0006061000f, 0.0006808792f, 0.0007651456f, 0.0008600124f,
    0.0009665928f, 0.001086000f, 0.001220586f, 0.001372729f,
    0.001543579f, 0.001734286f, 0.001946000f, 0.002177777f,
    0.002435809f, 0.002731953f, 0.003078064f, 0.003486000f,
    0.003975227f, 0.004540880f, 0.005158320f, 0.005802907f,
    0.006450001f, 0.007083216f, 0.007745488f, 0.008501152f,
    0.009414544f, 0.01054999f, 0.01196580f, 0.01365587f,
    0.01558805f, 0.01773015f, 0.02005001f, 0.02251136f,
    0.02520288f, 0.02827972f, 0.03189704f, 0.03621000f,
    0.04143771f, 0.04750372f, 0.05411988f, 0.06099803f,
    0.06785001f, 0.07448632f, 0.08136156f, 0.08915364f,
    0.09854048f, 0.1102000f, 0.1246133f, 0.1417017f,
    0.1613035f, 0.1832568f, 0.2074000f, 0.2336921f,
    0.2626114f, 0.2947746f, 0.3307985f, 0.3713000f,
    0.4162091f, 0.4654642f, 0.5196948f, 0.5795303f,
    0.6456000f, 0.7184838f, 0.7967133f, 0.8778459f,
    0.9594390f, 1.0390501f, 1.1153673f, 1.1884971f,
    1.2581233f, 1.3239296f, 1.3856000f, 1.4426352f,
    1.4948035f, 1.5421903f, 1.5848807f, 1.6229600f,
    1.6564048f, 1.6852959f, 1.7098745f, 1.7303821f,
    1.7470600f, 1.7600446f, 1.7696233f, 1.7762637f,
    1.7804334f, 1.7826000f, 1.7829682f, 1.7816998f,
    1.7791982f, 1.7758671f, 1.7721100f, 1.7682589f,
    1.7640390f, 1.7589438f, 1.7524663f, 1.7441000f,
    1.7335595f, 1.7208581f, 1.7059369f, 1.6887372f,
    1.6692000f, 1.6475287f, 1.6234127f, 1.5960223f,
    1.5645280f, 1.5281000f, 1.4861114f, 1.4395215f,
    1.3898799f, 1.3387362f, 1.2876400f, 1.2374223f,
    1.1878243f, 1.1387611f, 1.0901480f, 1.0419000f,
    0.9941976f, 0.9473473f, 0.9014531f, 0.8566193f,
    0.8129501f, 0.7705173f, 0.7294448f, 0.6899136f,
    0.6521049f, 0.6162000f, 0.5823286f, 0.5504162f,
    0.5203376f, 0.4919673f, 0.4651800f, 0.4399246f,
    0.4161836f, 0.3938822f, 0.3729459f, 0.3533000f,
    0.3348578f, 0.3175521f, 0.3013375f, 0.2861686f,
    0.2720000f, 0.2588171f, 0.2464838f, 0.2347718f,
    0.2234533f, 0.2123000f, 0.2011692f, 0.1901196f,
    0.1792254f, 0.1685608f, 0.1582000f, 0.1481383f,
    0.1383758f, 0.1289942f, 0.1200751f, 0.1117000f,
    0.1039048f, 0.09666748f, 0.08998272f, 0.08384531f,
    0.07824999f, 0.07320899f, 0.06867816f, 0.06456784f,
    0.06078835f, 0.05725001f, 0.05390435f, 0.05074664f,
    0.04775276f, 0.04489859f, 0.04216000f, 0.03950728f,
    0.03693564f, 0.03445836f, 0.03208872f, 0.02984000f,
    0.02771181f, 0.02569444f, 0.02378716f, 0.02198925f,
    0.02030000f, 0.01871805f, 0.01724036f, 0.01586364f,
    0.01458461f, 0.01340000f, 0.01230723f, 0.01130188f,
    0.01037792f, 0.009529306f, 0.008749999f, 0.008035200f,
    0.007381600f, 0.006785400f, 0.006242800f, 0.005749999f,
    0.005303600f, 0.004899800f, 0.004534200f, 0.004202400f,
    0.003900000f, 0.003623200f, 0.003370600f, 0.003141400f,
    0.002934800f, 0.002749999f, 0.002585200f, 0.002438600f,
    0.002309400f, 0.002196800f, 0.002100000f, 0.002017733f,
    0.001948200f, 0.001889800f, 0.001840933f, 0.001800000f,
    0.001766267f, 0.001737800f, 0.001711200f, 0.001683067f,
    0.001650001f, 0.001610133f, 0.001564400f, 0.001513600f,
    0.001458533f, 0.001400000f, 0.001336667f, 0.001270000f,
    0.001205000f, 0.001146667f, 0.001100000f, 0.001068800f,
    0.001049400f, 0.001035600f, 0.001021200f, 0.001000000f,
    0.0009686400f, 0.0009299200f, 0.0008868800f, 0.0008425600f,
    0.0008000000f, 0.0007609600f, 0.0007236800f, 0.0006859200f,
    0.0006454400f, 0.0006000000f, 0.0005478667f, 0.0004916000f,
    0.0004354000f, 0.0003834667f, 0.0003400000f, 0.0003072533f,
    0.0002831600f, 0.0002654400f, 0.0002518133f, 0.0002400000f,
    0.0002295467f, 0.0002206400f, 0.0002119600f, 0.0002021867f,
    0.0001900000f, 0.0001742133f, 0.0001556400f, 0.0001359600f,
    0.0001168533f, 0.0001000000f, 0.00008613333f, 0.00007460000f,
    0.00006500000f, 0.00005693333f, 0.00004999999f, 0.00004416000f,
    0.00003948000f, 0.00003572000f, 0.00003264000f, 0.00003000000f,
    0.00002765333f, 0.00002556000f, 0.00002364000f, 0.00002181333f,
    0.00002000000f, 0.00001813333f, 0.00001620000f, 0.00001420000f,
    0.00001213333f, 0.00001000000f, 0.000007733333f, 0.000005400000f,
    0.000003200000f, 0.000001333333f, 0.000000000000f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f
};

const float CIE_lambda[nCIESamples] =
{
    360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373,
    374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387,
    388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401,
    402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415,
    416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429,
    430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443,
    444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457,
    458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471,
    472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485,
    486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499,
    500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513,
    514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527,
    528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541,
    542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555,
    556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569,
    570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583,
    584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597,
    598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611,
    612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625,
    626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639,
    640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653,
    654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667,
    668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681,
    682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695,
    696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709,
    710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723,
    724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737,
    738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751,
    752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765,
    766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779,
    780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793,
    794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807,
    808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821,
    822, 823, 824, 825, 826, 827, 828, 829, 830
};

const float LambdaStart = CIE_lambda[0];
const float LambdaEnd = CIE_lambda[nCIESamples - 1];
const float wavelengthStep = CIE_lambda[1] - CIE_lambda[0];


// convert XYZ tristimulus values to RGB
Float3 XYZ2RGB(double X, double Y, double Z)
{
    // convert XYZ to sRGB
    Float3 val = Float3(
        float(X *  3.2406 + Y * -1.5372 + Z * -0.4986),
        float(X * -0.9689 + Y *  1.8758 + Z *  0.0415),
        float(X *  0.0557 + Y * -0.2040 + Z *  1.0570));

    val.x = val.x < 0 ? 0 : val.x;
    val.y = val.y < 0 ? 0 : val.y;
    val.z = val.z < 0 ? 0 : val.z;

    return val;
}

double Blackbody(double wl, double temp)
{
    if(temp < 0.0)
        return 0.0;

    const double C2 = 1.4388e7;
    double norm = pow(555.0, 5.0) * (exp(C2 / (555.0*temp)) - 1.);
    return norm / (pow(double(wl), 5.0)*(exp(C2 / (wl * temp)) - 1.));
}

Float3 ComputeBlackbody(double temperature)
{
    double X = 0, Y = 0, Z = 0;
    for(unsigned k = 0; k < nCIESamples; k++)
    {
        double lambda = CIE_lambda[k];
        double I = Blackbody(lambda, temperature);
        X += I * CIE_X[k];
        Y += I * CIE_Y[k];
        Z += I * CIE_Z[k];
    }
    X *= (LambdaEnd - LambdaStart) / double(nCIESamples);
    Y *= (LambdaEnd - LambdaStart) / double(nCIESamples);
    Z *= (LambdaEnd - LambdaStart) / double(nCIESamples);

    return XYZ2RGB(X, Y, Z);
}

void ConvertsRGBToSpectrum(float* spectrum, uint32 numSamples, Float3 sRGB)
{
    uint32 i = 0;
    for(uint32 lambda = 0; lambda < numSamples; ++lambda)
    {
        // -- compute percentage
        float percent = lambda / float(numSamples);
        if(percent < 0.33f)
            spectrum[i] = sRGB.z;
        else if(percent >= 0.33f && percent < 0.66f)
            spectrum[i] = sRGB.y;
        else
            spectrum[i] = sRGB.x;

        ++i;
    }
}

SampleFramework11::Float3 ConvertSpectrumTosRGB(float* spectrum, uint32 numSamples,
                                                uint32 lowerBound, uint32 upperBound,
                                                uint32 waveInc)
{
    // -- find the index to CIE first value
    uint32 cieOffset = lowerBound - uint32(LambdaStart);

    float X = 0.0f;
    float Y = 0.0f;
    float Z = 0.0f;
    for(uint32 k = 0; k < numSamples; ++k)
    {
        float I = spectrum[k];
        X += I * CIE_X[k + cieOffset];
        Y += I * CIE_Y[k + cieOffset];
        Z += I * CIE_Z[k + cieOffset];

    }

    X *= (upperBound - lowerBound) / float(numSamples);
    Y *= (upperBound - lowerBound) / float(numSamples);
    Z *= (upperBound - lowerBound) / float(numSamples);

    return XYZ2RGB(X, Y, Z);
}

<|start_filename|>SampleFramework11/v1.01/Graphics/Textures.h<|end_filename|>
//=================================================================================================
//
//  MJP's DX11 Sample Framework
//  http://mynameismjp.wordpress.com/
//
//  All code licensed under the MIT license
//
//=================================================================================================

#pragma once

#include "..\\PCH.h"

#include "..\\InterfacePointers.h"
#include "..\\Serialization.h"

namespace SampleFramework11
{

struct Float4;
struct Half4;
struct UByte4N;
class File;

// Texture loading
ID3D11ShaderResourceViewPtr LoadTexture(ID3D11Device* device, const wchar* filePath, bool forceSRGB = false);

template<typename T> struct TextureData
{
    std::vector<T> Texels;
    uint32 Width = 0;
    uint32 Height = 0;
    uint32 NumSlices = 0;

    void Init(uint32 width, uint32 height, uint32 numSlices)
    {
        Width = width;
        Height = height;
        NumSlices = numSlices;
        Texels.resize(width * height * numSlices);
    }

    template<typename TSerializer> void Serialize(TSerializer& serializer)
    {
        SerializeRawVector(serializer, Texels);
        SerializeItem(serializer, Width);
        SerializeItem(serializer, Height);
        SerializeItem(serializer, NumSlices);
    }
};

// Decode a texture and copies it to the CPU
void GetTextureData(ID3D11Device* device, ID3D11ShaderResourceView* textureSRV,
                    TextureData<UByte4N>& textureData);

void GetTextureData(ID3D11Device* device, ID3D11ShaderResourceView* textureSRV,
                    TextureData<Half4>& textureData);

void GetTextureData(ID3D11Device* device, ID3D11ShaderResourceView* textureSRV,
                    TextureData<Float4>& textureData);

ID3D11ShaderResourceViewPtr CreateSRVFromTextureData(ID3D11Device* device,
                                                     const TextureData<UByte4N>& textureData);

ID3D11ShaderResourceViewPtr CreateSRVFromTextureData(ID3D11Device* device,
                                                     const TextureData<Half4>& textureData);

ID3D11ShaderResourceViewPtr CreateSRVFromTextureData(ID3D11Device* device,
                                                     const TextureData<Float4>& textureData);

void SaveTextureAsDDS(ID3D11ShaderResourceView* srv, const wchar* filePath);
void SaveTextureAsDDS(ID3D11Resource* texture, const wchar* filePath);
void SaveTextureAsEXR(ID3D11ShaderResourceView* srv, const wchar* filePath);
void SaveTextureAsEXR(const TextureData<Float4>& texture, const wchar* filePath);

Float3 MapXYSToDirection(uint64 x, uint64 y, uint64 s, uint64 width, uint64 height);

// == Texture Sampling Functions ==================================================================

template<typename T> static XMVECTOR SampleTexture2D(Float2 uv, uint32 arraySlice, const std::vector<T>& texels,
                                                     uint32 texWidth, uint32 texHeight, uint32 numSlices)
{
    Float2 texSize = Float2(float(texWidth), float(texHeight));
    Float2 halfTexelSize(0.5f / texSize.x, 0.5f / texSize.y);
    Float2 samplePos = Frac(uv - halfTexelSize);
    if(samplePos.x < 0.0f)
        samplePos.x = 1.0f + samplePos.x;
    if(samplePos.y < 0.0f)
        samplePos.y = 1.0f + samplePos.y;
    samplePos *= texSize;
    uint32 samplePosX = std::min(uint32(samplePos.x), texWidth - 1);
    uint32 samplePosY = std::min(uint32(samplePos.y), texHeight - 1);
    uint32 samplePosXNext = std::min(samplePosX + 1, texWidth - 1);
    uint32 samplePosYNext = std::min(samplePosY + 1, texHeight - 1);

    Float2 lerpAmts = Float2(Frac(samplePos.x), Frac(samplePos.y));

    numSlices = std::max<uint32>(numSlices, 1);
    const uint32 sliceOffset = std::min(arraySlice, numSlices) * texWidth * texHeight;

    XMVECTOR samples[4];
    samples[0] = texels[sliceOffset + samplePosY * texWidth + samplePosX].ToSIMD();
    samples[1] = texels[sliceOffset + samplePosY * texWidth + samplePosXNext].ToSIMD();
    samples[2] = texels[sliceOffset + samplePosYNext * texWidth + samplePosX].ToSIMD();
    samples[3] = texels[sliceOffset + samplePosYNext * texWidth + samplePosXNext].ToSIMD();

    // lerp between the shadow values to calculate our light amount
    return XMVectorLerp(XMVectorLerp(samples[0], samples[1], lerpAmts.x),
                        XMVectorLerp(samples[2], samples[3], lerpAmts.x), lerpAmts.y);
}

template<typename T> static XMVECTOR SampleTexture2D(Float2 uv, uint32 arraySlice, const TextureData<T>& texData)
{
    return SampleTexture2D(uv, arraySlice, texData.Texels, texData.Width, texData.Height, texData.NumSlices);
}

template<typename T> static XMVECTOR SampleTexture2D(Float2 uv, const TextureData<T>& texData)
{
    return SampleTexture2D(uv, 0, texData.Texels, texData.Width, texData.Height, texData.NumSlices);
}

template<typename T> static XMVECTOR SampleCubemap(Float3 direction, const TextureData<T>& texData)
{
    Assert_(texData.NumSlices == 6);

    float maxComponent = std::max(std::max(std::abs(direction.x), std::abs(direction.y)), std::abs(direction.z));
    uint32 faceIdx = 0;
    Float2 uv = Float2(direction.y, direction.z);
    if(direction.x == maxComponent)
    {
        faceIdx = 0;
        uv = Float2(-direction.z, -direction.y) / direction.x;
    }
    else if(-direction.x == maxComponent)
    {
        faceIdx = 1;
        uv = Float2(direction.z, -direction.y) / -direction.x;
    }
    else if(direction.y == maxComponent)
    {
        faceIdx = 2;
        uv = Float2(direction.x, direction.z) / direction.y;
    }
    else if(-direction.y == maxComponent)
    {
        faceIdx = 3;
        uv = Float2(direction.x, -direction.z) / -direction.y;
    }
    else if(direction.z == maxComponent)
    {
        faceIdx = 4;
        uv = Float2(direction.x, -direction.y) / direction.z;
    }
    else if(-direction.z == maxComponent)
    {
        faceIdx = 5;
        uv = Float2(-direction.x, -direction.y) / -direction.z;
    }

    uv = uv * Float2(0.5f, 0.5f) + Float2(0.5f, 0.5f);
    return SampleTexture2D(uv, faceIdx, texData);
}

}

<|start_filename|>SampleFramework11/v1.01/Utility.cpp<|end_filename|>
//=================================================================================================
//
//  MJP's DX11 Sample Framework
//  http://mynameismjp.wordpress.com/
//
//  All code licensed under the MIT license
//
//=================================================================================================

#include "PCH.h"

#include "Utility.h"
#include "Exceptions.h"

namespace SampleFramework11
{


std::wstring SampleFrameworkDir()
{
    return std::wstring(SampleFrameworkDir_);
}

// Converts from cartesian to barycentric coordinates
XMFLOAT3 CartesianToBarycentric(float x, float y, const XMFLOAT2& pos1, const XMFLOAT2& pos2, const XMFLOAT2& pos3)
{
    float r1 = (pos2.y - pos3.y) * (x - pos3.x) + (pos3.x - pos2.x) * (y - pos3.y);
    r1 /= (pos2.y - pos3.y) * (pos1.x - pos3.x) + (pos3.x - pos2.x) * (pos1.y - pos3.y);

    float r2 = (pos3.y - pos1.y) * (x - pos3.x) + (pos1.x - pos3.x) * (y - pos3.y);
    r2 /= (pos3.y - pos1.y) * (pos2.x - pos3.x) + (pos1.x - pos3.x) * (pos2.y - pos3.y);

    float r3 = 1.0f - r1 - r2;

    return XMFLOAT3(r1, r2, r3);
}

// Converts from barycentric to cartesian coordinates
XMFLOAT2 BarycentricToCartesian(const XMFLOAT3& r, const XMFLOAT2& pos1, const XMFLOAT2& pos2, const XMFLOAT2& pos3)
{
    float x = r.x * pos1.x + r.y * pos2.x + r.z * pos3.x;
    float y = r.x * pos1.y + r.y * pos2.y + r.z * pos3.y;

    return XMFLOAT2(x, y);
}

// Converts from barycentric to cartesian coordinates
XMVECTOR BarycentricToCartesian(const XMFLOAT3& r, FXMVECTOR pos1, FXMVECTOR pos2, FXMVECTOR pos3)
{
    XMVECTOR rvec;
    rvec = XMVectorScale(pos1, r.x);
    rvec += XMVectorScale(pos2, r.y);
    rvec += XMVectorScale(pos3, r.z);

    return rvec;
}

// Returns true if the given barycentric coordinate is in the triangle
BOOL PointIsInTriangle(const XMFLOAT3& r, float epsilon)
{
    float minr = 0.0f - epsilon;
    float maxr = 1.0f + epsilon;

    if(r.x < minr || r.x > maxr)
        return false;

    if(r.y < minr || r.y > maxr)
        return false;

    if(r.z < minr || r.z > maxr)
        return false;

    float rsum = r.x + r.y + r.z;
    return rsum >= minr && rsum <= maxr;
}

// Computes a compute shader dispatch size given a thread group size, and number of elements to process
uint32 DispatchSize(uint32 tgSize, uint32 numElements)
{
    uint32 dispatchSize = numElements / tgSize;
    dispatchSize += numElements % tgSize > 0 ? 1 : 0;
    return dispatchSize;
}

void SetCSInputs(ID3D11DeviceContext* context, ID3D11ShaderResourceView* srv0, ID3D11ShaderResourceView* srv1,
                    ID3D11ShaderResourceView* srv2, ID3D11ShaderResourceView* srv3)
{
    ID3D11ShaderResourceView* srvs[4] = { srv0, srv1, srv2, srv3 };
    context->CSSetShaderResources(0, 4, srvs);
}

void ClearCSInputs(ID3D11DeviceContext* context)
{
    SetCSInputs(context, nullptr, nullptr, nullptr, nullptr);
}

void SetCSOutputs(ID3D11DeviceContext* context, ID3D11UnorderedAccessView* uav0, ID3D11UnorderedAccessView* uav1,
                    ID3D11UnorderedAccessView* uav2, ID3D11UnorderedAccessView* uav3, ID3D11UnorderedAccessView* uav4,
                    ID3D11UnorderedAccessView* uav5)
{
    ID3D11UnorderedAccessView* uavs[6] = { uav0, uav1, uav2, uav3, uav4, uav5 };
    context->CSSetUnorderedAccessViews(0, 6, uavs, nullptr);
}

void ClearCSOutputs(ID3D11DeviceContext* context)
{
    SetCSOutputs(context, nullptr, nullptr, nullptr, nullptr);
}

void SetCSSamplers(ID3D11DeviceContext* context, ID3D11SamplerState* sampler0, ID3D11SamplerState* sampler1,
                    ID3D11SamplerState* sampler2, ID3D11SamplerState* sampler3)
{
    ID3D11SamplerState* samplers[4] = { sampler0, sampler1, sampler2, sampler3 };
    context->CSSetSamplers(0, 4, samplers);
}

void SetCSShader(ID3D11DeviceContext* context, ID3D11ComputeShader* shader)
{
    context->CSSetShader(shader, nullptr, 0);
}

void SetCSConstants(ID3D11DeviceContext* context, ID3D11Buffer* constantBuffer, uint32 slot)
{
    ID3D11Buffer* constants[1] = { constantBuffer };
    context->CSSetConstantBuffers(slot, 1, constants);
}

}

<|start_filename|>MSAAFilter/MSAAFilter.h<|end_filename|>
//=================================================================================================
//
//  MSAA Filtering 2.0 Sample
//  by MJP
//  http://mynameismjp.wordpress.com/
//
//  All code licensed under the MIT license
//
//=================================================================================================

#pragma once

#include <PCH.h>

#include <App.h>
#include <InterfacePointers.h>
#include <Graphics\\Camera.h>
#include <Graphics\\Model.h>
#include <Graphics\\SpriteFont.h>
#include <Graphics\\SpriteRenderer.h>
#include <Graphics\\Skybox.h>
#include <Graphics\\GraphicsTypes.h>
#include <Graphics\\ShaderCompilation.h>

#include "PostProcessor.h"
#include "MeshRenderer.h"

using namespace SampleFramework11;

class MSAAFilter : public App
{

protected:

    FirstPersonCamera camera;

    SpriteFont font;
    SampleFramework11::SpriteRenderer spriteRenderer;
    Skybox skybox;

    PostProcessor postProcessor;
    DepthStencilBuffer depthBuffer;
    RenderTarget2D colorTarget;
    RenderTarget2D resolveTarget;
    RenderTarget2D prevFrameTarget;
    RenderTarget2D velocityTarget;
    uint64 frameCount = 0;

    // Model
    Model models[uint64(Scenes::NumValues)];
    MeshRenderer meshRenderer;

    Float4x4 modelTransform;
    Quaternion modelOrientations[uint64(Scenes::NumValues)];

    ID3D11ShaderResourceViewPtr envMap;
    SH9Color envMapSH;

    VertexShaderPtr resolveVS;
    PixelShaderPtr resolvePS[uint64(MSAAModes::NumValues)];

    VertexShaderPtr backgroundVelocityVS;
    PixelShaderPtr backgroundVelocityPS;
    Float4x4 prevViewProjection;

    Float2 jitterOffset;
    Float2 prevJitter;

    struct ResolveConstants
    {
        uint32 SampleRadius;
        Float2 TextureSize;
    };

    struct BackgroundVelocityConstants
    {
        Float4x4 InvViewProjection;
        Float4x4 PrevViewProjection;
        Float2 RTSize;
        Float2 JitterOffset;
    };

    ConstantBuffer<ResolveConstants> resolveConstants;
    ConstantBuffer<BackgroundVelocityConstants> backgroundVelocityConstants;

    virtual void Initialize() override;
    virtual void Render(const Timer& timer) override;
    virtual void Update(const Timer& timer) override;
    virtual void BeforeReset() override;
    virtual void AfterReset() override;

    void CreateRenderTargets();

    void RenderScene();
    void RenderBackgroundVelocity();
    void RenderAA();
    void RenderHUD();

public:

    MSAAFilter();
};


<|start_filename|>MSAAFilter/PostProcessor.h<|end_filename|>
//=================================================================================================
//
//  MSAA Filtering 2.0 Sample
//  by MJP
//  http://mynameismjp.wordpress.com/
//
//  All code licensed under the MIT license
//
//=================================================================================================

#pragma once

#include <PCH.h>
#include <Graphics\\GraphicsTypes.h>
#include <Graphics\\PostProcessorBase.h>
#include <Graphics\\DeviceStates.h>

#include "AppSettings.h"

using namespace SampleFramework11;

class PostProcessor : public PostProcessorBase
{

public:

    void Initialize(ID3D11Device* device);

    void Render(ID3D11DeviceContext* deviceContext, ID3D11ShaderResourceView* input,
                ID3D11RenderTargetView* output, float deltaSeconds);
    void AfterReset(UINT width, UINT height);

    ID3D11ShaderResourceView* AdaptedLuminance() { return adaptedLuminance; }

protected:

    void CalcAvgLuminance(ID3D11ShaderResourceView* input);
    TempRenderTarget* Bloom(ID3D11ShaderResourceView* input);
    void ToneMap(ID3D11ShaderResourceView* input,
                 ID3D11ShaderResourceView* bloom,
                 ID3D11RenderTargetView* output);

    ComputeShaderPtr reduceLuminanceInitial;
    ComputeShaderPtr reduceLuminance;
    ComputeShaderPtr reduceLuminanceFinal;
    PixelShaderPtr toneMap;
    PixelShaderPtr scale;
    PixelShaderPtr bloom;
    PixelShaderPtr blurH;
    PixelShaderPtr blurV;
    PixelShaderPtr sharpen;

    std::vector<RenderTarget2D> reductionTargets;
    ID3D11ShaderResourceView* adaptedLuminance;

    struct Constants
    {
        float TimeDelta;
        uint32 EnableAdaptation;
    };

    ConstantBuffer<Constants> constantBuffer;
};

<|start_filename|>SampleFramework11/v1.01/App.cpp<|end_filename|>

//
//  MJP's DX11 Sample Framework
//  http://mynameismjp.wordpress.com/
//
//  All code licensed under the MIT license
//
//=================================================================================================

#include "PCH.h"

#include "App.h"
#include "Exceptions.h"
#include "Graphics\\Profiler.h"
#include "SF11_Math.h"
#include "FileIO.h"
#include "Settings.h"
#include "TwHelper.h"

// AppSettings framework
namespace AppSettings
{
    void Initialize(ID3D11Device* device);
    void Update();
    void UpdateCBuffer(ID3D11DeviceContext* context);
}

namespace SampleFramework11
{

App* GlobalApp = nullptr;

App::App(const wchar* appName, const wchar* iconResource) :   window(NULL, appName, WS_OVERLAPPEDWINDOW,
                                                                     WS_EX_APPWINDOW, 1280, 720, iconResource, iconResource),
                                                              currentTimeDeltaSample(0),
                                                              fps(0), tweakBar(nullptr), applicationName(appName),
                                                              createConsole(true), showWindow(true), returnCode(0)
{
    GlobalApp = this;
    for(uint32 i = 0; i < NumTimeDeltaSamples; ++i)
        timeDeltaBuffer[i] = 0;
}

App::~App()
{

}

int32 App::Run()
{
    try
    {
        if(createConsole)
        {
            Win32Call(AllocConsole());
            Win32Call(SetConsoleTitle(applicationName.c_str()));
            FILE* consoleFile = nullptr;
            freopen_s(&consoleFile, "CONOUT$", "wb", stdout);
        }

        window.SetClientArea(deviceManager.BackBufferWidth(), deviceManager.BackBufferHeight());

        if(showWindow)
            window.ShowWindow();

        deviceManager.Initialize(window);

        blendStates.Initialize(deviceManager.Device());
        rasterizerStates.Initialize(deviceManager.Device());
        depthStencilStates.Initialize(deviceManager.Device());
        samplerStates.Initialize(deviceManager.Device());

        // Create a font + SpriteRenderer
        font.Initialize(L"Arial", 18, SpriteFont::Regular, true, deviceManager.Device());
        spriteRenderer.Initialize(deviceManager.Device());

        Profiler::GlobalProfiler.Initialize(deviceManager.Device(), deviceManager.ImmediateContext());

        window.RegisterMessageCallback(WM_SIZE, OnWindowResized, this);

        // Initialize AntTweakBar
        TwCall(TwInit(TW_DIRECT3D11, deviceManager.Device()));

        // Create a tweak bar
        tweakBar = TwNewBar("Settings");
        TwCall(TwDefine(" GLOBAL help='MJPs sample framework for DX11' "));
        TwCall(TwDefine(" GLOBAL fontsize=3 "));

        Settings.Initialize(tweakBar);

        TwHelper::SetValuesWidth(Settings.TweakBar(), 120, false);

        AppSettings::Initialize(deviceManager.Device());

        Initialize();

        AfterReset();

        while(window.IsAlive())
        {
            if(!window.IsMinimized())
            {
                timer.Update();
                Settings.Update();

                CalculateFPS();

                AppSettings::Update();

                Update(timer);

                UpdateShaders(deviceManager.Device());

                AppSettings::UpdateCBuffer(deviceManager.ImmediateContext());

                Render(timer);

                // Render the profiler text
                spriteRenderer.Begin(deviceManager.ImmediateContext(), SpriteRenderer::Point);
                Profiler::GlobalProfiler.EndFrame(spriteRenderer, font);
                spriteRenderer.End();

                {
                    PIXEvent pixEvent(L"Ant Tweak Bar");

                    // Render the TweakBar UI
                    TwCall(TwDraw());
                }

                deviceManager.Present();
            }

            window.MessageLoop();
        }
    }
    catch(SampleFramework11::Exception exception)
    {
        exception.ShowErrorMessage();
        return -1;
    }

    ShutdownShaders();

    TwCall(TwTerminate());

    if(createConsole)
    {
        fclose(stdout);
        FreeConsole();
    }

    return returnCode;
}

void App::CalculateFPS()
{
    timeDeltaBuffer[currentTimeDeltaSample] = timer.DeltaSecondsF();
    currentTimeDeltaSample = (currentTimeDeltaSample + 1) % NumTimeDeltaSamples;

    float averageDelta = 0;
    for(UINT i = 0; i < NumTimeDeltaSamples; ++i)
        averageDelta += timeDeltaBuffer[i];
    averageDelta /= NumTimeDeltaSamples;

    fps = static_cast<UINT>(std::floor((1.0f / averageDelta) + 0.5f));
}

LRESULT App::OnWindowResized(void* context, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    App* app = reinterpret_cast<App*>(context);

    if(!app->deviceManager.FullScreen() && wParam != SIZE_MINIMIZED)
    {
        int width, height;
        app->window.GetClientArea(width, height);

        if(width != app->deviceManager.BackBufferWidth() || height != app->deviceManager.BackBufferHeight())
        {
            app->BeforeReset();

            app->deviceManager.SetBackBufferWidth(width);
            app->deviceManager.SetBackBufferHeight(height);
            app->deviceManager.Reset();

            app->AfterReset();
        }
    }

    return 0;
}

void App::Exit()
{
    window.Destroy();
}

void App::Initialize()
{
}

void App::BeforeReset()
{
}

void App::AfterReset()
{
    const uint32 width = deviceManager.BackBufferWidth();
    const uint32 height = deviceManager.BackBufferHeight();

    TwHelper::SetSize(tweakBar, 375, deviceManager.BackBufferHeight());
    TwHelper::SetPosition(tweakBar, deviceManager.BackBufferWidth() - 375, 0);
}

void App::ToggleFullScreen(bool fullScreen)
{
    if(fullScreen != deviceManager.FullScreen())
    {
        BeforeReset();

        deviceManager.SetFullScreen(fullScreen);
        deviceManager.Reset();

        AfterReset();
    }
}

void App::RenderText(const std::wstring& text, Float2 pos)
{
    ID3D11DeviceContext* context = deviceManager.ImmediateContext();

    // Set the backbuffer and viewport
    ID3D11RenderTargetView* rtvs[1] = { deviceManager.BackBuffer() };
    context->OMSetRenderTargets(1, rtvs, NULL);

    float clearColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
    context->ClearRenderTargetView(rtvs[0], clearColor);

    SetViewport(context, deviceManager.BackBufferWidth(), deviceManager.BackBufferHeight());

    // Draw the text
    Float4x4 transform;
    transform.SetTranslation(Float3(pos.x, pos.y,0.0f));
    spriteRenderer.Begin(context, SpriteRenderer::Point);
    spriteRenderer.RenderText(font, text.c_str(), transform.ToSIMD());
    spriteRenderer.End();

    // Present
    deviceManager.SwapChain()->Present(0, 0);

    // Pump the message loop
    window.MessageLoop();
}

void App::RenderCenteredText(const std::wstring& text)
{

    // Measure the text
    Float2 textSize = font.MeasureText(text.c_str());

    // Position it in the middle
    Float2 textPos;
    textPos.x = Round((deviceManager.BackBufferWidth() / 2.0f) - (textSize.x / 2.0f));
    textPos.y = Round((deviceManager.BackBufferHeight() / 2.0f) - (textSize.y / 2.0f));

    RenderText(text, textPos);
}

}

<|start_filename|>MSAAFilter/AppSettings.cpp<|end_filename|>
#include <PCH.h>
#include <TwHelper.h>
#include "AppSettings.h"

using namespace SampleFramework11;

static const char* MSAAModesLabels[4] =
{
    "None",
    "2x",
    "4x",
    "8x",
};

static const char* FilterTypesLabels[10] =
{
    "Box",
    "Triangle",
    "Gaussian",
    "Blackman-Harris",
    "Smoothstep",
    "B-Spline",
    "Catmull-Rom",
    "Mitchell",
    "Generalized Cubic",
    "Sinc",
};

static const char* ClampModesLabels[4] =
{
    "Disabled",
    "RGB Clamp",
    "RGB Clip",
    "Variance Clip",
};

static const char* JitterModesLabels[5] =
{
    "None",
    "Uniform 2x",
    "Hammersley 4x",
    "Hammersley 8x",
    "Hammersley 16x",
};

static const char* DilationModesLabels[3] =
{
    "Center Average",
    "Dilate - Nearest Depth",
    "Dilate - Greatest Velocity",
};

static const char* ScenesLabels[5] =
{
    "RoboHand",
    "Plane (Bricks)",
    "Plane (UI)",
    "Soldier",
    "Tower",
};

namespace AppSettings
{
    MSAAModesSetting MSAAMode;
    FilterTypesSetting ResolveFilterType;
    FloatSetting ResolveFilterDiameter;
    FloatSetting GaussianSigma;
    FloatSetting CubicB;
    FloatSetting CubicC;
    BoolSetting UseStandardResolve;
    BoolSetting InverseLuminanceFiltering;
    BoolSetting UseExposureFiltering;
    FloatSetting ExposureFilterOffset;
    BoolSetting UseGradientMipLevel;
    BoolSetting CentroidSampling;
    BoolSetting EnableTemporalAA;
    FloatSetting TemporalAABlendFactor;
    BoolSetting UseTemporalColorWeighting;
    ClampModesSetting NeighborhoodClampMode;
    FloatSetting VarianceClipGamma;
    JitterModesSetting JitterMode;
    FloatSetting JitterScale;
    FloatSetting LowFreqWeight;
    FloatSetting HiFreqWeight;
    FloatSetting SharpeningAmount;
    DilationModesSetting DilationMode;
    FloatSetting MipBias;
    FilterTypesSetting ReprojectionFilter;
    BoolSetting UseStandardReprojection;
    ScenesSetting CurrentScene;
    DirectionSetting LightDirection;
    ColorSetting LightColor;
    BoolSetting EnableDirectLighting;
    BoolSetting EnableAmbientLighting;
    BoolSetting RenderBackground;
    BoolSetting EnableShadows;
    BoolSetting EnableNormalMaps;
    FloatSetting NormalMapIntensity;
    FloatSetting DiffuseIntensity;
    FloatSetting Roughness;
    FloatSetting SpecularIntensity;
    OrientationSetting ModelOrientation;
    FloatSetting ModelRotationSpeed;
    BoolSetting DoubleSyncInterval;
    FloatSetting ExposureScale;
    BoolSetting EnableZoom;
    FloatSetting BloomExposure;
    FloatSetting BloomMagnitude;
    FloatSetting BloomBlurSigma;
    FloatSetting ManualExposure;

    ConstantBuffer<AppSettingsCBuffer> CBuffer;

    void Initialize(ID3D11Device* device)
    {
        TwBar* tweakBar = Settings.TweakBar();

        MSAAMode.Initialize(tweakBar, "MSAAMode", "Anti Aliasing", "MSAAMode", "", MSAAModes::MSAA4x, 4, MSAAModesLabels);
        Settings.AddSetting(&MSAAMode);

        ResolveFilterType.Initialize(tweakBar, "ResolveFilterType", "Anti Aliasing", "Resolve Filter Type", "", FilterTypes::BSpline, 10, FilterTypesLabels);
        Settings.AddSetting(&ResolveFilterType);

        ResolveFilterDiameter.Initialize(tweakBar, "ResolveFilterDiameter", "Anti Aliasing", "Resolve Filter Diameter", "", 2.0000f, 0.0000f, 6.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&ResolveFilterDiameter);

        GaussianSigma.Initialize(tweakBar, "GaussianSigma", "Anti Aliasing", "Gaussian Sigma", "", 0.5000f, 0.0100f, 1.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&GaussianSigma);

        CubicB.Initialize(tweakBar, "CubicB", "Anti Aliasing", "Cubic B", "", 0.3300f, 0.0000f, 1.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&CubicB);

        CubicC.Initialize(tweakBar, "CubicC", "Anti Aliasing", "Cubic C", "", 0.3300f, 0.0000f, 1.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&CubicC);

        UseStandardResolve.Initialize(tweakBar, "UseStandardResolve", "Anti Aliasing", "Use Standard Resolve", "", false);
        Settings.AddSetting(&UseStandardResolve);

        InverseLuminanceFiltering.Initialize(tweakBar, "InverseLuminanceFiltering", "Anti Aliasing", "Inverse Luminance Filtering", "", true);
        Settings.AddSetting(&InverseLuminanceFiltering);

        UseExposureFiltering.Initialize(tweakBar, "UseExposureFiltering", "Anti Aliasing", "Use Exposure Filtering", "", true);
        Settings.AddSetting(&UseExposureFiltering);

        ExposureFilterOffset.Initialize(tweakBar, "ExposureFilterOffset", "Anti Aliasing", "Exposure Filter Offset", "", 2.0000f, -16.0000f, 16.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&ExposureFilterOffset);

        UseGradientMipLevel.Initialize(tweakBar, "UseGradientMipLevel", "Anti Aliasing", "Use Gradient Mip Level", "", false);
        Settings.AddSetting(&UseGradientMipLevel);

        CentroidSampling.Initialize(tweakBar, "CentroidSampling", "Anti Aliasing", "Centroid Sampling", "", true);
        Settings.AddSetting(&CentroidSampling);

        EnableTemporalAA.Initialize(tweakBar, "EnableTemporalAA", "Anti Aliasing", "Enable Temporal AA", "", true);
        Settings.AddSetting(&EnableTemporalAA);

        TemporalAABlendFactor.Initialize(tweakBar, "TemporalAABlendFactor", "Anti Aliasing", "Temporal AABlend Factor", "", 0.9000f, 0.0000f, 1.0000f, 0.0010f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&TemporalAABlendFactor);

        UseTemporalColorWeighting.Initialize(tweakBar, "UseTemporalColorWeighting", "Anti Aliasing", "Use Temporal Color Weighting", "", false);
        Settings.AddSetting(&UseTemporalColorWeighting);

        NeighborhoodClampMode.Initialize(tweakBar, "NeighborhoodClampMode", "Anti Aliasing", "Neighborhood Clamp Mode", "", ClampModes::Variance_Clip, 4, ClampModesLabels);
        Settings.AddSetting(&NeighborhoodClampMode);

        VarianceClipGamma.Initialize(tweakBar, "VarianceClipGamma", "Anti Aliasing", "Variance Clip Gamma", "", 1.5000f, 0.0000f, 2.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&VarianceClipGamma);

        JitterMode.Initialize(tweakBar, "JitterMode", "Anti Aliasing", "Jitter Mode", "", JitterModes::Hammersley4x, 5, JitterModesLabels);
        Settings.AddSetting(&JitterMode);

        JitterScale.Initialize(tweakBar, "JitterScale", "Anti Aliasing", "Jitter Scale", "", 1.0000f, 0.0000f, 340282300000000000000000000000000000000.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&JitterScale);

        LowFreqWeight.Initialize(tweakBar, "LowFreqWeight", "Anti Aliasing", "Low Freq Weight", "", 0.2500f, 0.0000f, 100.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&LowFreqWeight);

        HiFreqWeight.Initialize(tweakBar, "HiFreqWeight", "Anti Aliasing", "Hi Freq Weight", "", 0.8500f, 0.0000f, 100.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&HiFreqWeight);

        SharpeningAmount.Initialize(tweakBar, "SharpeningAmount", "Anti Aliasing", "Sharpening Amount", "", 0.0000f, 0.0000f, 1.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&SharpeningAmount);

        DilationMode.Initialize(tweakBar, "DilationMode", "Anti Aliasing", "Dilation Mode", "", DilationModes::DilateNearestDepth, 3, DilationModesLabels);
        Settings.AddSetting(&DilationMode);

        MipBias.Initialize(tweakBar, "MipBias", "Anti Aliasing", "Mip Bias", "", 0.0000f, -340282300000000000000000000000000000000.0000f, 0.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&MipBias);

        ReprojectionFilter.Initialize(tweakBar, "ReprojectionFilter", "Anti Aliasing", "Reprojection Filter", "", FilterTypes::CatmullRom, 10, FilterTypesLabels);
        Settings.AddSetting(&ReprojectionFilter);

        UseStandardReprojection.Initialize(tweakBar, "UseStandardReprojection", "Anti Aliasing", "Use Standard Reprojection", "", false);
        Settings.AddSetting(&UseStandardReprojection);

        CurrentScene.Initialize(tweakBar, "CurrentScene", "Scene Controls", "Current Scene", "", Scenes::RoboHand, 5, ScenesLabels);
        Settings.AddSetting(&CurrentScene);

        LightDirection.Initialize(tweakBar, "LightDirection", "Scene Controls", "Light Direction", "The direction of the light", Float3(-0.7500f, 0.9770f, -0.4000f));
        Settings.AddSetting(&LightDirection);

        LightColor.Initialize(tweakBar, "LightColor", "Scene Controls", "Light Color", "The color of the light", Float3(20.0000f, 16.0000f, 10.0000f), true, 0.0000f, 20.0000f, 0.1000f, ColorUnit::None);
        Settings.AddSetting(&LightColor);

        EnableDirectLighting.Initialize(tweakBar, "EnableDirectLighting", "Scene Controls", "Enable Direct Lighting", "Enables direct lighting", true);
        Settings.AddSetting(&EnableDirectLighting);

        EnableAmbientLighting.Initialize(tweakBar, "EnableAmbientLighting", "Scene Controls", "Enable Ambient Lighting", "Enables ambient lighting from the environment", true);
        Settings.AddSetting(&EnableAmbientLighting);

        RenderBackground.Initialize(tweakBar, "RenderBackground", "Scene Controls", "Render Background", "", true);
        Settings.AddSetting(&RenderBackground);

        EnableShadows.Initialize(tweakBar, "EnableShadows", "Scene Controls", "Enable Shadows", "", true);
        Settings.AddSetting(&EnableShadows);

        EnableNormalMaps.Initialize(tweakBar, "EnableNormalMaps", "Scene Controls", "Enable Normal Maps", "", true);
        Settings.AddSetting(&EnableNormalMaps);

        NormalMapIntensity.Initialize(tweakBar, "NormalMapIntensity", "Scene Controls", "Normal Map Intensity", "", 1.0000f, 0.0000f, 1.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&NormalMapIntensity);

        DiffuseIntensity.Initialize(tweakBar, "DiffuseIntensity", "Scene Controls", "Diffuse Intensity", "Diffuse albedo intensity parameter for the material", 0.5000f, 0.0000f, 1.0000f, 0.0010f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&DiffuseIntensity);

        Roughness.Initialize(tweakBar, "Roughness", "Scene Controls", "Roughness", "Specular roughness parameter for the material", 0.1000f, 0.0010f, 1.0000f, 0.0010f, ConversionMode::Square, 1.0000f);
        Settings.AddSetting(&Roughness);

        SpecularIntensity.Initialize(tweakBar, "SpecularIntensity", "Scene Controls", "Specular Intensity", "Specular intensity parameter for the material", 0.0500f, 0.0000f, 1.0000f, 0.0010f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&SpecularIntensity);

        ModelOrientation.Initialize(tweakBar, "ModelOrientation", "Scene Controls", "Model Orientation", "", Quaternion(0.4100f, -0.5500f, -0.2900f, 0.6700f));
        Settings.AddSetting(&ModelOrientation);

        ModelRotationSpeed.Initialize(tweakBar, "ModelRotationSpeed", "Scene Controls", "Model Rotation Speed", "", 0.0000f, 0.0000f, 10.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&ModelRotationSpeed);

        DoubleSyncInterval.Initialize(tweakBar, "DoubleSyncInterval", "Scene Controls", "Double Sync Interval", "", false);
        Settings.AddSetting(&DoubleSyncInterval);

        ExposureScale.Initialize(tweakBar, "ExposureScale", "Scene Controls", "Exposure Scale", "", 0.0000f, -16.0000f, 16.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&ExposureScale);

        EnableZoom.Initialize(tweakBar, "EnableZoom", "Scene Controls", "Enable Zoom", "", false);
        Settings.AddSetting(&EnableZoom);

        BloomExposure.Initialize(tweakBar, "BloomExposure", "Post Processing", "Bloom Exposure Offset", "Exposure offset applied to generate the input of the bloom pass", -4.0000f, -10.0000f, 0.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&BloomExposure);

        BloomMagnitude.Initialize(tweakBar, "BloomMagnitude", "Post Processing", "Bloom Magnitude", "Scale factor applied to the bloom results when combined with tone-mapped result", 1.0000f, 0.0000f, 2.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&BloomMagnitude);

        BloomBlurSigma.Initialize(tweakBar, "BloomBlurSigma", "Post Processing", "Bloom Blur Sigma", "Sigma parameter of the Gaussian filter used in the bloom pass", 5.0000f, 0.5000f, 5.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&BloomBlurSigma);

        ManualExposure.Initialize(tweakBar, "ManualExposure", "Post Processing", "Manual Exposure", "Manual exposure value when auto-exposure is disabled", -2.5000f, -10.0000f, 10.0000f, 0.0100f, ConversionMode::None, 1.0000f);
        Settings.AddSetting(&ManualExposure);

        TwHelper::SetOpened(tweakBar, "Anti Aliasing", true);

        TwHelper::SetOpened(tweakBar, "Scene Controls", true);

        TwHelper::SetOpened(tweakBar, "Post Processing", true);

        CBuffer.Initialize(device);
    }

    void Update()
    {
    }

    void UpdateCBuffer(ID3D11DeviceContext* context)
    {
        CBuffer.Data.MSAAMode = MSAAMode;
        CBuffer.Data.ResolveFilterType = ResolveFilterType;
        CBuffer.Data.ResolveFilterDiameter = ResolveFilterDiameter;
        CBuffer.Data.GaussianSigma = GaussianSigma;
        CBuffer.Data.CubicB = CubicB;
        CBuffer.Data.CubicC = CubicC;
        CBuffer.Data.UseStandardResolve = UseStandardResolve;
        CBuffer.Data.InverseLuminanceFiltering = InverseLuminanceFiltering;
        CBuffer.Data.UseExposureFiltering = UseExposureFiltering;
        CBuffer.Data.ExposureFilterOffset = ExposureFilterOffset;
        CBuffer.Data.UseGradientMipLevel = UseGradientMipLevel;
        CBuffer.Data.EnableTemporalAA = EnableTemporalAA;
        CBuffer.Data.TemporalAABlendFactor = TemporalAABlendFactor;
        CBuffer.Data.UseTemporalColorWeighting = UseTemporalColorWeighting;
        CBuffer.Data.NeighborhoodClampMode = NeighborhoodClampMode;
        CBuffer.Data.VarianceClipGamma = VarianceClipGamma;
        CBuffer.Data.LowFreqWeight = LowFreqWeight;
        CBuffer.Data.HiFreqWeight = HiFreqWeight;
        CBuffer.Data.SharpeningAmount = SharpeningAmount;
        CBuffer.Data.DilationMode = DilationMode;
        CBuffer.Data.MipBias = MipBias;
        CBuffer.Data.ReprojectionFilter = ReprojectionFilter;
        CBuffer.Data.UseStandardReprojection = UseStandardReprojection;
        CBuffer.Data.CurrentScene = CurrentScene;
        CBuffer.Data.LightDirection = LightDirection;
        CBuffer.Data.LightColor = LightColor;
        CBuffer.Data.EnableDirectLighting = EnableDirectLighting;
        CBuffer.Data.EnableAmbientLighting = EnableAmbientLighting;
        CBuffer.Data.RenderBackground = RenderBackground;
        CBuffer.Data.EnableShadows = EnableShadows;
        CBuffer.Data.EnableNormalMaps = EnableNormalMaps;
        CBuffer.Data.NormalMapIntensity = NormalMapIntensity;
        CBuffer.Data.DiffuseIntensity = DiffuseIntensity;
        CBuffer.Data.Roughness = Roughness;
        CBuffer.Data.SpecularIntensity = SpecularIntensity;
        CBuffer.Data.ModelOrientation = ModelOrientation;
        CBuffer.Data.ModelRotationSpeed = ModelRotationSpeed;
        CBuffer.Data.DoubleSyncInterval = DoubleSyncInterval;
        CBuffer.Data.ExposureScale = ExposureScale;
        CBuffer.Data.EnableZoom = EnableZoom;
        CBuffer.Data.BloomExposure = BloomExposure;
        CBuffer.Data.BloomMagnitude = BloomMagnitude;
        CBuffer.Data.BloomBlurSigma = BloomBlurSigma;
        CBuffer.Data.ManualExposure = ManualExposure;

        CBuffer.ApplyChanges(context);
        CBuffer.SetVS(context, 7);
        CBuffer.SetHS(context, 7);
        CBuffer.SetDS(context, 7);
        CBuffer.SetGS(context, 7);
        CBuffer.SetPS(context, 7);
        CBuffer.SetCS(context, 7);
    }
}

// ================================================================================================

namespace AppSettings
{
    void UpdateUI()
    {
        ExposureFilterOffset.SetEditable(UseExposureFiltering.Value() ? true : false);

        bool enableTemporal = EnableTemporalAA.Value() ? true : false;
        JitterMode.SetEditable(enableTemporal);
        UseTemporalColorWeighting.SetEditable(enableTemporal);
        NeighborhoodClampMode.SetEditable(enableTemporal);
        LowFreqWeight.SetEditable(enableTemporal);
        HiFreqWeight.SetEditable(enableTemporal);
        DilationMode.SetEditable(enableTemporal);

        bool generalCubic = ResolveFilterType == FilterTypes::GeneralizedCubic;
        CubicB.SetEditable(generalCubic);
        CubicC.SetEditable(generalCubic);
        GaussianSigma.SetEditable(ResolveFilterType == FilterTypes::Gaussian);
    }
}


<|start_filename|>MSAAFilter/PostProcessor.cpp<|end_filename|>
//=================================================================================================
//
//  MSAA Filtering 2.0 Sample
//  by MJP
//  http://mynameismjp.wordpress.com/
//
//  All code licensed under the MIT license
//
//=================================================================================================

#include <PCH.h>

#include <Graphics\\ShaderCompilation.h>
#include <Graphics\\Profiler.h>

#include "PostProcessor.h"
#include "SharedConstants.h"

// Constants
static const uint32 TGSize = 16;
static const uint32 LumMapSize = 1024;

void PostProcessor::Initialize(ID3D11Device* device)
{
    PostProcessorBase::Initialize(device);

    constantBuffer.Initialize(device);

    // Load the shaders
    toneMap = CompilePSFromFile(device, L"PostProcessing.hlsl", "ToneMap");
    scale = CompilePSFromFile(device, L"PostProcessing.hlsl", "Scale");
    blurH = CompilePSFromFile(device, L"PostProcessing.hlsl", "BlurH");
    blurV = CompilePSFromFile(device, L"PostProcessing.hlsl", "BlurV");
    bloom = CompilePSFromFile(device, L"PostProcessing.hlsl", "Bloom");
    sharpen = CompilePSFromFile(device, L"PostProcessing.hlsl", "Sharpen");

    reduceLuminanceInitial = CompileCSFromFile(device, L"LuminanceReduction.hlsl",
                                               "LuminanceReductionInitialCS", "cs_5_0");
    reduceLuminance = CompileCSFromFile(device, L"LuminanceReduction.hlsl", "LuminanceReductionCS");

    CompileOptions opts;
    opts.Add("FinalPass_", 1);
    reduceLuminanceFinal = CompileCSFromFile(device, L"LuminanceReduction.hlsl", "LuminanceReductionCS",
                                             "cs_5_0", opts);
}

void PostProcessor::AfterReset(uint32 width, uint32 height)
{
    PostProcessorBase::AfterReset(width, height);

    reductionTargets.clear();

    uint32 w = width;
    uint32 h = height;

    int number = 0;
    char buff[100];

    while(w > 1 || h > 1)
    {
        w = DispatchSize(ReductionTGSize, w);
        h = DispatchSize(ReductionTGSize, h);

        RenderTarget2D rt;
        rt.Name = "PostProcessorReduction-";
        sprintf_s(buff, 100, "%i", number);
        rt.Name += buff;
        rt.Initialize(device, w, h, DXGI_FORMAT_R32_FLOAT, 1, 1, 0, false, true);
        reductionTargets.push_back(rt);
        number++;
    }

    adaptedLuminance = reductionTargets[reductionTargets.size() - 1].SRView;

    constantBuffer.Data.EnableAdaptation = false;
}

void PostProcessor::Render(ID3D11DeviceContext* deviceContext, ID3D11ShaderResourceView* input,
                           ID3D11RenderTargetView* output, float deltaSeconds)
{
    PostProcessorBase::Render(deviceContext, input, output);

    constantBuffer.Data.TimeDelta = deltaSeconds;

    constantBuffer.ApplyChanges(deviceContext);
    constantBuffer.SetPS(deviceContext, 1);

    if(AppSettings::EnableAutoExposure)
        CalcAvgLuminance(input);

    TempRenderTarget* bloom = Bloom(input);

    const bool applySharpening = AppSettings::SharpeningAmount > 0.0f && AppSettings::UseStandardResolve == false;
    TempRenderTarget* toneMapTarget = nullptr;
    ID3D11RenderTargetView* toneMapOutput = output;
    if(applySharpening)
    {
        toneMapTarget = GetTempRenderTarget(inputWidth, inputHeight, DXGI_FORMAT_R10G10B10A2_UNORM);
        toneMapOutput = toneMapTarget->RTView;
    }

    // Apply tone mapping
    ToneMap(input, bloom->SRView, toneMapOutput);

    if(applySharpening)
    {
        PostProcess(toneMapTarget->SRView, output, sharpen, L"Sharpening");
        toneMapTarget->InUse = false;
    }

    bloom->InUse = false;
    constantBuffer.Data.EnableAdaptation = true;
}

void PostProcessor::CalcAvgLuminance(ID3D11ShaderResourceView* input)
{
    // Calculate the geometric mean of luminance through reduction
    PIXEvent pixEvent(L"Average Luminance Calculation");

    constantBuffer.SetCS(context, 0);

    ID3D11UnorderedAccessView* uavs[1] = { reductionTargets[0].UAView };
    context->CSSetUnorderedAccessViews(0, 1, uavs, NULL);

    ID3D11ShaderResourceView* srvs[1] = { input };
    context->CSSetShaderResources(0, 1, srvs);

    context->CSSetShader(reduceLuminanceInitial, NULL, 0);

    uint32 dispatchX = reductionTargets[0].Width;
    uint32 dispatchY = reductionTargets[0].Height;
    context->Dispatch(dispatchX, dispatchY, 1);

    uavs[0] = NULL;
    context->CSSetUnorderedAccessViews(0, 1, uavs, NULL);

    srvs[0] = NULL;
    context->CSSetShaderResources(0, 1, srvs);

    for(uint32 i = 1; i < reductionTargets.size(); ++i)
    {
        if(i == reductionTargets.size() - 1)
            context->CSSetShader(reduceLuminanceFinal, NULL, 0);
        else
            context->CSSetShader(reduceLuminance, NULL, 0);

        uavs[0] = reductionTargets[i].UAView;
        context->CSSetUnorderedAccessViews(0, 1, uavs, NULL);

        srvs[0] = reductionTargets[i - 1].SRView;
        context->CSSetShaderResources(0, 1, srvs);

        dispatchX = reductionTargets[i].Width;
        dispatchY = reductionTargets[i].Height;
        context->Dispatch(dispatchX, dispatchY, 1);

        uavs[0] = NULL;
        context->CSSetUnorderedAccessViews(0, 1, uavs, NULL);

        srvs[0] = NULL;
        context->CSSetShaderResources(0, 1, srvs);
    }
}

TempRenderTarget* PostProcessor::Bloom(ID3D11ShaderResourceView* input)
{
    PIXEvent pixEvent(L"Bloom");

    TempRenderTarget* bloomTarget = GetTempRenderTarget(inputWidth / 2, inputHeight / 2, DXGI_FORMAT_R11G11B10_FLOAT);
    inputs.push_back(input);
    inputs.push_back(adaptedLuminance);
    outputs.push_back(bloomTarget->RTView);
    PostProcess(bloom, L"Bloom Initial Pass");

    // Blur it
    for(uint64 i = 0; i < 2; ++i)
    {
        TempRenderTarget* blurTemp = GetTempRenderTarget(bloomTarget->Width, bloomTarget->Height, bloomTarget->Format);
        PostProcess(bloomTarget->SRView, blurTemp->RTView, blurH, L"Horizontal Bloom Blur");

        PostProcess(blurTemp->SRView, bloomTarget->RTView, blurV, L"Vertical Bloom Blur");
        blurTemp->InUse = false;
    }

    return bloomTarget;
}

void PostProcessor::ToneMap(ID3D11ShaderResourceView* input,
                            ID3D11ShaderResourceView* bloom,
                            ID3D11RenderTargetView* output)
{
    inputs.push_back(input);
    inputs.push_back(adaptedLuminance);
    inputs.push_back(bloom);
    outputs.push_back(output);

    PostProcess(toneMap, L"Tone Mapping");
}

<|start_filename|>MSAAFilter/AppSettings.h<|end_filename|>
#pragma once

#include <PCH.h>
#include <Settings.h>
#include <Graphics\GraphicsTypes.h>

using namespace SampleFramework11;

enum class MSAAModes
{
    MSAANone = 0,
    MSAA2x = 1,
    MSAA4x = 2,
    MSAA8x = 3,

    NumValues
};

typedef EnumSettingT<MSAAModes> MSAAModesSetting;

enum class FilterTypes
{
    Box = 0,
    Triangle = 1,
    Gaussian = 2,
    BlackmanHarris = 3,
    Smoothstep = 4,
    BSpline = 5,
    CatmullRom = 6,
    Mitchell = 7,
    GeneralizedCubic = 8,
    Sinc = 9,

    NumValues
};

typedef EnumSettingT<FilterTypes> FilterTypesSetting;

enum class ClampModes
{
    Disabled = 0,
    RGB_Clamp = 1,
    RGB_Clip = 2,
    Variance_Clip = 3,

    NumValues
};

typedef EnumSettingT<ClampModes> ClampModesSetting;

enum class JitterModes
{
    None = 0,
    Uniform2x = 1,
    Hammersley4x = 2,
    Hammersley8x = 3,
    Hammersley16x = 4,

    NumValues
};

typedef EnumSettingT<JitterModes> JitterModesSetting;

enum class DilationModes
{
    CenterAverage = 0,
    DilateNearestDepth = 1,
    DilateGreatestVelocity = 2,

    NumValues
};

typedef EnumSettingT<DilationModes> DilationModesSetting;

enum class Scenes
{
    RoboHand = 0,
    BrickPlane = 1,
    UIPlane = 2,
    Soldier = 3,
    Tower = 4,

    NumValues
};

typedef EnumSettingT<Scenes> ScenesSetting;

namespace AppSettings
{
    static const bool EnableAutoExposure = false;
    static const float KeyValue = 0.1150f;
    static const float AdaptationRate = 0.5000f;

    extern MSAAModesSetting MSAAMode;
    extern FilterTypesSetting ResolveFilterType;
    extern FloatSetting ResolveFilterDiameter;
    extern FloatSetting GaussianSigma;
    extern FloatSetting CubicB;
    extern FloatSetting CubicC;
    extern BoolSetting UseStandardResolve;
    extern BoolSetting InverseLuminanceFiltering;
    extern BoolSetting UseExposureFiltering;
    extern FloatSetting ExposureFilterOffset;
    extern BoolSetting UseGradientMipLevel;
    extern BoolSetting CentroidSampling;
    extern BoolSetting EnableTemporalAA;
    extern FloatSetting TemporalAABlendFactor;
    extern BoolSetting UseTemporalColorWeighting;
    extern ClampModesSetting NeighborhoodClampMode;
    extern FloatSetting VarianceClipGamma;
    extern JitterModesSetting JitterMode;
    extern FloatSetting JitterScale;
    extern FloatSetting LowFreqWeight;
    extern FloatSetting HiFreqWeight;
    extern FloatSetting SharpeningAmount;
    extern DilationModesSetting DilationMode;
    extern FloatSetting MipBias;
    extern FilterTypesSetting ReprojectionFilter;
    extern BoolSetting UseStandardReprojection;
    extern ScenesSetting CurrentScene;
    extern DirectionSetting LightDirection;
    extern ColorSetting LightColor;
    extern BoolSetting EnableDirectLighting;
    extern BoolSetting EnableAmbientLighting;
    extern BoolSetting RenderBackground;
    extern BoolSetting EnableShadows;
    extern BoolSetting EnableNormalMaps;
    extern FloatSetting NormalMapIntensity;
    extern FloatSetting DiffuseIntensity;
    extern FloatSetting Roughness;
    extern FloatSetting SpecularIntensity;
    extern OrientationSetting ModelOrientation;
    extern FloatSetting ModelRotationSpeed;
    extern BoolSetting DoubleSyncInterval;
    extern FloatSetting ExposureScale;
    extern BoolSetting EnableZoom;
    extern FloatSetting BloomExposure;
    extern FloatSetting BloomMagnitude;
    extern FloatSetting BloomBlurSigma;
    extern FloatSetting ManualExposure;

    struct AppSettingsCBuffer
    {
        int32 MSAAMode;
        int32 ResolveFilterType;
        float ResolveFilterDiameter;
        float GaussianSigma;
        float CubicB;
        float CubicC;
        bool32 UseStandardResolve;
        bool32 InverseLuminanceFiltering;
        bool32 UseExposureFiltering;
        float ExposureFilterOffset;
        bool32 UseGradientMipLevel;
        bool32 EnableTemporalAA;
        float TemporalAABlendFactor;
        bool32 UseTemporalColorWeighting;
        int32 NeighborhoodClampMode;
        float VarianceClipGamma;
        float LowFreqWeight;
        float HiFreqWeight;
        float SharpeningAmount;
        int32 DilationMode;
        float MipBias;
        int32 ReprojectionFilter;
        bool32 UseStandardReprojection;
        int32 CurrentScene;
        Float3 LightDirection;
        Float4Align Float3 LightColor;
        bool32 EnableDirectLighting;
        bool32 EnableAmbientLighting;
        bool32 RenderBackground;
        bool32 EnableShadows;
        bool32 EnableNormalMaps;
        float NormalMapIntensity;
        float DiffuseIntensity;
        float Roughness;
        float SpecularIntensity;
        Float4Align Quaternion ModelOrientation;
        float ModelRotationSpeed;
        bool32 DoubleSyncInterval;
        float ExposureScale;
        bool32 EnableZoom;
        float BloomExposure;
        float BloomMagnitude;
        float BloomBlurSigma;
        float ManualExposure;
    };

    extern ConstantBuffer<AppSettingsCBuffer> CBuffer;

    void Initialize(ID3D11Device* device);
    void Update();
    void UpdateCBuffer(ID3D11DeviceContext* context);
};

// ================================================================================================

namespace AppSettings
{
    inline uint32 NumMSAASamples(MSAAModes mode)
    {
        static const uint32 NumSamples[uint32(MSAAModes::NumValues)] = { 1, 2, 4, 8 };
        return NumSamples[uint32(mode)];
    }

    inline uint32 NumMSAASamples()
    {
        return NumMSAASamples(MSAAMode);
    }

    inline bool UseNormalMapping()
    {
        return CurrentScene != Scenes::RoboHand;
    }

    inline bool EnableJitter()
    {
        return JitterMode != JitterModes::None;
    }

    void UpdateUI();
}

<|start_filename|>SampleFramework11/v1.01/Graphics/Skybox.h<|end_filename|>
//=================================================================================================
//
//  MJP's DX11 Sample Framework
//  http://mynameismjp.wordpress.com/
//
//  All code licensed under the MIT license
//
//=================================================================================================

#pragma once

#include "..\\PCH.h"

#include "..\\InterfacePointers.h"
#include "..\\SF11_Math.h"
#include "ShaderCompilation.h"
#include "GraphicsTypes.h"

// HosekSky forward declares
struct ArHosekSkyModelState;

namespace SampleFramework11
{

// Cached data for the procedural sky model
struct SkyCache
{
    ArHosekSkyModelState* StateR = nullptr;
    ArHosekSkyModelState* StateG = nullptr;
    ArHosekSkyModelState* StateB = nullptr;
    Float3 SunDirection;
    float Turbidity = 0.0f;
    Float3 Albedo;
    float Elevation = 0.0f;
    ID3D11ShaderResourceViewPtr CubeMap;

    void Init(Float3 sunDirection, Float3 groundAlbedo, float turbidity);
    void Shutdown();
    ~SkyCache();
};

class Skybox
{

public:

    Skybox();
    ~Skybox();

    void Initialize(ID3D11Device* device);

    void RenderEnvironmentMap(ID3D11DeviceContext* context,
                              ID3D11ShaderResourceView* environmentMap,
                              const Float4x4& view,
                              const Float4x4& projection,
                              Float3 scale = Float3(1.0f, 1.0f, 1.0f));

    void RenderSky(ID3D11DeviceContext* context,
                   Float3 sunDirection,
                   Float3 groundAlbedo,
                   Float3 sunColor,
                   float sunSize,
                   float turbidity,
                   const Float4x4& view,
                   const Float4x4& projection,
                   Float3 scale = Float3(1.0f, 1.0f, 1.0f));

    void RenderSimpleSky(ID3D11DeviceContext* context,
                         Float3 skyColor,
                         Float3 sunDirection,
                         Float3 sunColor,
                         float sunSize,
                         const Float4x4& view,
                         const Float4x4& projection,
                         Float3 scake = Float3(1.0f, 1.0f, 1.0f));

    static void Save2DSkyAsEXR(ID3D11Device* device, const SkyCache& skyCache,
                               uint32 width, uint32 height, Float3 sunColor,
                               float sunSize, bool32 includeSun, bool32 normalizeIntensity,
                               const wchar* filePath);

    static Float3 SampleSky(const SkyCache& cache, Float3 sampleDir);

protected:

    void RenderCommon(ID3D11DeviceContext* context,
                      ID3D11ShaderResourceView* environmentMap,
                      ID3D11PixelShader* ps,
                      const Float4x4& view,
                      const Float4x4& projection,
                      Float3 scale);

    static const uint64 NumIndices = 36;
    static const uint64 NumVertices = 8;

    struct VSConstants
    {
        Float4x4 View;
        Float4x4 Projection;
    };

    struct PSConstants
    {
        Float3 SunDirection = Float3(0.0f, 1.0f, 0.0f);
        bool32 EnableSun = false;
        Float3 SkyColor = 1.0f;
        Float4Align Float3 SunColor = 1.0f;
        float CosSunAngularRadius = 0.0f;
        Float3 Scale = 1.0f;
    };

    ID3D11DevicePtr device;
    VertexShaderPtr vertexShader;
    PixelShaderPtr emPixelShader;
    PixelShaderPtr simpleSkyPS;
    ID3D11InputLayoutPtr inputLayout;
    ID3D11BufferPtr vertexBuffer;
    ID3D11BufferPtr indexBuffer;
    ConstantBuffer<VSConstants> vsConstantBuffer;
    ConstantBuffer<PSConstants> psConstantBuffer;
    ID3D11DepthStencilStatePtr dsState;
    ID3D11BlendStatePtr blendState;
    ID3D11RasterizerStatePtr rastState;
    ID3D11SamplerStatePtr samplerState;

    SkyCache skyCache;
};

}

<|start_filename|>MSAAFilter/AppPCH.h<|end_filename|>
//=================================================================================================
//
//  MSAA Filtering 2.0 Sample
//  by MJP
//  http://mynameismjp.wordpress.com/
//
//  All code licensed under the MIT license
//
//=================================================================================================

<|start_filename|>SampleFramework11/v1.01/Graphics/SH.cpp<|end_filename|>
//=================================================================================================
//
//  MJP's DX11 Sample Framework
//  http://mynameismjp.wordpress.com/
//
//  All code licensed under the MIT license
//
//=================================================================================================

#include "PCH.h"
#include "SH.h"
#include "..\\Utility.h"
#include "ShaderCompilation.h"
#include "Textures.h"

namespace SampleFramework11
{

SH9 ProjectOntoSH9(const Float3& dir)
{
    SH9 sh;

    // Band 0
    sh.Coefficients[0] = 0.282095f;

    // Band 1
    sh.Coefficients[1] = 0.488603f * dir.y;
    sh.Coefficients[2] = 0.488603f * dir.z;
    sh.Coefficients[3] = 0.488603f * dir.x;

    // Band 2
    sh.Coefficients[4] = 1.092548f * dir.x * dir.y;
    sh.Coefficients[5] = 1.092548f * dir.y * dir.z;
    sh.Coefficients[6] = 0.315392f * (3.0f * dir.z * dir.z - 1.0f);
    sh.Coefficients[7] = 1.092548f * dir.x * dir.z;
    sh.Coefficients[8] = 0.546274f * (dir.x * dir.x - dir.y * dir.y);

    return sh;
}

SH9Color ProjectOntoSH9Color(const Float3& dir, const Float3& color)
{
    SH9 sh = ProjectOntoSH9(dir);
    SH9Color shColor;
    for(uint64 i = 0; i < 9; ++i)
        shColor.Coefficients[i] = color * sh.Coefficients[i];
    return shColor;
}

Float3 EvalSH9Cosine(const Float3& dir, const SH9Color& sh)
{
    SH9 dirSH = ProjectOntoSH9(dir);
    dirSH.Coefficients[0] *= CosineA0;
    dirSH.Coefficients[1] *= CosineA1;
    dirSH.Coefficients[2] *= CosineA1;
    dirSH.Coefficients[3] *= CosineA1;
    dirSH.Coefficients[4] *= CosineA2;
    dirSH.Coefficients[5] *= CosineA2;
    dirSH.Coefficients[6] *= CosineA2;
    dirSH.Coefficients[7] *= CosineA2;
    dirSH.Coefficients[8] *= CosineA2;

    Float3 result;
    for(uint64 i = 0; i < 9; ++i)
        result += dirSH.Coefficients[i] * sh.Coefficients[i];

    return result;
}

H4 ProjectOntoH4(const Float3& dir)
{
    H4 result;

    result[0] = (1.0f / std::sqrt(2.0f * 3.14159f));

    // Band 1
    result[1] = std::sqrt(1.5f / 3.14159f) * dir.y;
    result[2] = std::sqrt(1.5f / 3.14159f) * (2 * dir.z - 1.0f);
    result[3] = std::sqrt(1.5f / 3.14159f) * dir.x;

    return result;
}

float EvalH4(const H4& h, const Float3& dir)
{
    H4 b = ProjectOntoH4(dir);
    return H4::Dot(h, b);
}

H4 ConvertToH4(const SH9& sh)
{
    const float rt2 = sqrt(2.0f);
    const float rt32 = sqrt(3.0f / 2.0f);
    const float rt52 = sqrt(5.0f / 2.0f);
    const float rt152 = sqrt(15.0f / 2.0f);
    const float convMatrix[4][9] =
    {
        { 1.0f / rt2, 0, 0.5f * rt32, 0, 0, 0, 0, 0, 0 },
        { 0, 1.0f / rt2, 0, 0, 0, (3.0f / 8.0f) * rt52, 0, 0, 0 },
        { 0, 0, 1.0f / (2.0f * rt2), 0, 0, 0, 0.25f * rt152, 0, 0 },
        { 0, 0, 0, 1.0f / rt2, 0, 0, 0, (3.0f / 8.0f) * rt52, 0 }
    };

    H4 hBasis;

    for(uint64 row = 0; row < 4; ++row)
    {
        hBasis.Coefficients[row] = 0.0f;

        for(uint64 col = 0; col < 9; ++col)
            hBasis.Coefficients[row] += convMatrix[row][col] * sh.Coefficients[col];
    }

    return hBasis;
}


SH9Color ProjectCubemapToSH(ID3D11Device* device, ID3D11ShaderResourceView* cubeMap)
{
    TextureData<Float4> textureData;
    GetTextureData(device, cubeMap, textureData);
    Assert_(textureData.NumSlices == 6);
    const uint32 width = textureData.Width;
    const uint32 height = textureData.Height;

    SH9Color result;
    float weightSum = 0.0f;
    for(uint32 face = 0; face < 6; ++face)
    {
        for(uint32 y = 0; y < height; ++y)
        {
            for(uint32 x = 0; x < width; ++x)
            {
                const uint32 idx = face * (width * height) + y * (width) + x;
                Float3 sample = textureData.Texels[idx].To3D();

                float u = (x + 0.5f) / width;
                float v = (y + 0.5f) / height;

                // Account for cubemap texel distribution
                u = u * 2.0f - 1.0f;
                v = v * 2.0f - 1.0f;
                const float temp = 1.0f + u * u + v * v;
                const float weight = 4.0f / (sqrt(temp) * temp);

                Float3 dir = MapXYSToDirection(x, y, face, width, height);
                result += ProjectOntoSH9Color(dir, sample) * weight;
                weightSum += weight;
            }
        }
    }

    result *= (4.0f * 3.14159f) / weightSum;
    return result;
}

}

<|start_filename|>MSAAFilter/SharedConstants.h<|end_filename|>
//=================================================================================================
//
//  MSAA Filtering 2.0 Sample
//  by MJP
//  http://mynameismjp.wordpress.com/
//
//  All code licensed under the MIT license
//
//=================================================================================================

#if _WINDOWS

#pragma once

typedef SampleFramework11::Float2 float2;
typedef SampleFramework11::Float3 float3;
typedef SampleFramework11::Float4 float4;

typedef uint32 uint;
typedef SampleFramework11::Uint2 uint2;
typedef SampleFramework11::Uint3 uint3;
typedef SampleFramework11::Uint4 uint4;

#endif

static const uint ReductionTGSize = 16;
static const uint ConvolveTGSize = 16;

// Info about a active sample point on the light map
struct SamplePoint
{
    float3 Position;
    float3 Normal;
    float3 Tangent;
    float3 Bitangent;
    uint Coverage;
    uint2 TexelPos;
};

// Single vertex in the mesh vertex buffer
struct Vertex
{
    float3 Position;
    float3 Normal;
    float2 TexCoord;
    float2 LightMapUV;
	float3 Tangent;
	float3 Bitangent;
};

#if _WINDOWS

// Operators for Vertex structure
// operators
inline Vertex operator+(const Vertex& a, const Vertex& b)
{
    Vertex c;
    c.Position = a.Position + b.Position;
    c.Normal = a.Normal + b.Normal;
    c.TexCoord = a.TexCoord + b.TexCoord;
    c.LightMapUV = a.LightMapUV + b.LightMapUV;
    c.Tangent = a.Tangent + b.Tangent;
    c.Bitangent = a.Bitangent + b.Bitangent;
    return c;
}

inline Vertex operator-(const Vertex& a, const Vertex& b)
{
    Vertex c;
    c.Position = a.Position - b.Position;
    c.Normal = a.Normal - b.Normal;
    c.TexCoord = a.TexCoord - b.TexCoord;
    c.LightMapUV = a.LightMapUV - b.LightMapUV;
    c.Tangent = a.Tangent - b.Tangent;
    c.Bitangent = a.Bitangent - b.Bitangent;
    return c;
}

inline Vertex operator*(const Vertex& a, float b)
{
    Vertex c;
    c.Position = a.Position * b;
    c.Normal = a.Normal * b;
    c.TexCoord = a.TexCoord * b;
    c.LightMapUV = a.LightMapUV * b;
    c.Tangent = a.Tangent * b;
    c.Bitangent = a.Bitangent * b;
    return c;
}

#endif

<|start_filename|>MSAAFilter/MeshRenderer.h<|end_filename|>
//=================================================================================================
//
//  MSAA Filtering 2.0 Sample
//  by MJP
//  http://mynameismjp.wordpress.com/
//
//  All code licensed under the MIT license
//
//=================================================================================================

#pragma once

#include <PCH.h>

#include <Graphics\\Model.h>
#include <Graphics\\GraphicsTypes.h>
#include <Graphics\\DeviceStates.h>
#include <Graphics\\Camera.h>
#include <Graphics\\SH.h>
#include <Graphics\\ShaderCompilation.h>

#include "AppSettings.h"

using namespace SampleFramework11;

struct BakeData;

class MeshRenderer
{

protected:

    // Constants
    static const uint32 NumCascades = 4;
    static const uint32 ReadbackLatency = 1;

public:

    void Initialize(ID3D11Device* device, ID3D11DeviceContext* context);
    void SetModel(const Model* model);

    void RenderDepth(ID3D11DeviceContext* context, const Camera& camera, const Float4x4& world,
                     bool shadowRendering);
    void Render(ID3D11DeviceContext* context, const Camera& camera, const Float4x4& world,
                ID3D11ShaderResourceView* envMap, const SH9Color& envMapSH,
                Float2 JitterOffset);

    void Update();

    void CreateReductionTargets(uint32 width, uint32 height);

    void ReduceDepth(ID3D11DeviceContext* context, DepthStencilBuffer& depthBuffer,
                     const Camera& camera);

    void ComputeShadowDepthBounds(const Camera& camera);

    void RenderShadowMap(ID3D11DeviceContext* context, const Camera& camera,
                         const Float4x4& world);

protected:

    void LoadShaders();
    void CreateShadowMaps();
    void ConvertToEVSM(ID3D11DeviceContext* context, uint32 cascadeIdx, Float3 cascadeScale);

    ID3D11DevicePtr device;

    BlendStates blendStates;
    RasterizerStates rasterizerStates;
    DepthStencilStates depthStencilStates;
    SamplerStates samplerStates;

    const Model* model = nullptr;

    DepthStencilBuffer shadowMap;
    RenderTarget2D  varianceShadowMap;
    RenderTarget2D tempVSM;

    ID3D11RasterizerStatePtr shadowRSState;
    ID3D11SamplerStatePtr evsmSampler;

    std::vector<ID3D11InputLayoutPtr> meshInputLayouts;
    VertexShaderPtr meshVS[2];
    PixelShaderPtr meshPS[2][2];

    std::vector<ID3D11InputLayoutPtr> meshDepthInputLayouts;
    VertexShaderPtr meshDepthVS;

    VertexShaderPtr fullScreenVS;
    PixelShaderPtr evsmConvertPS;
    PixelShaderPtr evsmBlurH;
    PixelShaderPtr evsmBlurV;

    ComputeShaderPtr depthReductionInitialCS[2];
    ComputeShaderPtr depthReductionCS;
    std::vector<RenderTarget2D> depthReductionTargets;
    StagingTexture2D reductionStagingTextures[ReadbackLatency];
    uint32 currFrame = 0;

    Float2 shadowDepthBounds = Float2(0.0f, 1.0f);

    ID3D11ShaderResourceViewPtr specularLookupTexture;

    Float4x4 prevWVP;

    ID3D11SamplerStatePtr mipBiasSampler;
    float currMipBias = 0.0f;

    // Constant buffers
    struct MeshVSConstants
    {
        Float4Align Float4x4 World;
        Float4Align Float4x4 View;
        Float4Align Float4x4 WorldViewProjection;
        Float4Align Float4x4 PrevWorldViewProjection;
    };

    struct MeshPSConstants
    {
        Float4Align Float3 CameraPosWS;

        Float4Align Float4x4 ShadowMatrix;
        Float4Align float CascadeSplits[NumCascades];

        Float4Align Float4 CascadeOffsets[NumCascades];
        Float4Align Float4 CascadeScales[NumCascades];

        float OffsetScale;
        float PositiveExponent;
        float NegativeExponent;
        float LightBleedingReduction;

        Float4Align Float4x4 Projection;

        Float4Align ShaderSH9Color EnvironmentSH;

        Float2 RTSize;
        Float2 JitterOffset;
    };

    struct EVSMConstants
    {
        Float3 CascadeScale;
        float PositiveExponent;
        float NegativeExponent;
        float FilterSize;
        Float2 ShadowMapSize;
    };

    struct ReductionConstants
    {
        Float4x4 Projection;
        float NearClip;
        float FarClip;
        Uint2 TextureSize;
        uint32 NumSamples;
    };

    ConstantBuffer<MeshVSConstants> meshVSConstants;
    ConstantBuffer<MeshPSConstants> meshPSConstants;
    ConstantBuffer<EVSMConstants> evsmConstants;
    ConstantBuffer<ReductionConstants> reductionConstants;
};

<|start_filename|>MSAAFilter/AppSettings.cs<|end_filename|>
//=================================================================================================
//
//  MSAA Filtering 2.0 Sample
//  by MJP
//  http://mynameismjp.wordpress.com/
//
//  All code licensed under the MIT license
//
//=================================================================================================

public class Settings
{
    enum MSAAModes
    {
        [EnumLabel("None")]
        MSAANone = 0,

        [EnumLabel("2x")]
        MSAA2x,

        [EnumLabel("4x")]
        MSAA4x,

        [EnumLabel("8x")]
        MSAA8x,
    }

    enum FilterTypes
    {
        Box = 0,
        Triangle,
        Gaussian,

        [EnumLabel("Blackman-Harris")]
        BlackmanHarris,
        Smoothstep,

        [EnumLabel("B-Spline")]
        BSpline,

        [EnumLabel("Catmull-Rom")]
        CatmullRom,
        Mitchell,

        [EnumLabel("Generalized Cubic")]
        GeneralizedCubic,
        Sinc,
    }

    enum Scenes
    {
        RoboHand,

        [EnumLabel("Plane (Bricks)")]
        BrickPlane,

        [EnumLabel("Plane (UI)")]
        UIPlane,

        Soldier,
        Tower,
    }

    enum JitterModes
    {
        None,

        [EnumLabel("Uniform 2x")]
        Uniform2x,

        [EnumLabel("Hammersley 4x")]
        Hammersley4x,

        [EnumLabel("Hammersley 8x")]
        Hammersley8x,

        [EnumLabel("Hammersley 16x")]
        Hammersley16x,
    }

    enum DilationModes
    {
        [EnumLabel("Center Average")]
        CenterAverage,

        [EnumLabel("Dilate - Nearest Depth")]
        DilateNearestDepth,

        [EnumLabel("Dilate - Greatest Velocity")]
        DilateGreatestVelocity,
    }

    enum ClampModes
    {
        Disabled,

        [EnumLabel("RGB Clamp")]
        RGB_Clamp,

        [EnumLabel("RGB Clip")]
        RGB_Clip,

        [EnumLabel("Variance Clip")]
        Variance_Clip,
    }

    public class AntiAliasing
    {
        MSAAModes MSAAMode = MSAAModes.MSAA4x;

        FilterTypes ResolveFilterType = FilterTypes.BSpline;

        [MinValue(0.0f)]
        [MaxValue(6.0f)]
        [StepSize(0.01f)]
        float ResolveFilterDiameter = 2.0f;

        [MinValue(0.01f)]
        [MaxValue(1.0f)]
        [StepSize(0.01f)]
        float GaussianSigma = 0.5f;

        [MinValue(0.0f)]
        [MaxValue(1.0f)]
        [StepSize(0.01f)]
        float CubicB = 0.33f;

        [MinValue(0.0f)]
        [MaxValue(1.0f)]
        [StepSize(0.01f)]
        float CubicC = 0.33f;

        bool UseStandardResolve = false;

        bool InverseLuminanceFiltering = true;

        bool UseExposureFiltering = true;

        [MinValue(-16.0f)]
        [MaxValue(16.0f)]
        float ExposureFilterOffset = 2.0f;

        bool UseGradientMipLevel = false;

        [UseAsShaderConstant(false)]
        bool CentroidSampling = true;

        bool EnableTemporalAA = true;

        [MinValue(0.0f)]
        [MaxValue(1.0f)]
        [StepSize(0.001f)]
        float TemporalAABlendFactor = 0.9f;

        bool UseTemporalColorWeighting = false;

        ClampModes NeighborhoodClampMode = ClampModes.Variance_Clip;

        [MinValue(0.0f)]
        [MaxValue(2.0f)]
        float VarianceClipGamma = 1.5f;

        [UseAsShaderConstant(false)]
        JitterModes JitterMode = JitterModes.Hammersley4x;

        [MinValue(0.0f)]
        [UseAsShaderConstant(false)]
        float JitterScale = 1.0f;

        [MinValue(0.0f)]
        [MaxValue(100.0f)]
        float LowFreqWeight = 0.25f;

        [MinValue(0.0f)]
        [MaxValue(100.0f)]
        float HiFreqWeight = 0.85f;

        [MinValue(0.0f)]
        [MaxValue(1.0f)]
        float SharpeningAmount = 0.0f;

        DilationModes DilationMode = DilationModes.DilateNearestDepth;

        [MaxValue(0.0f)]
        float MipBias = 0.0f;

        FilterTypes ReprojectionFilter = FilterTypes.CatmullRom;

        bool UseStandardReprojection = false;
    }

    public class SceneControls
    {
        Scenes CurrentScene = Scenes.RoboHand;

        [DisplayName("Light Direction")]
        [HelpText("The direction of the light")]
        Direction LightDirection = new Direction(-0.75f, 0.977f, -0.4f);

        [DisplayName("Light Color")]
        [HelpText("The color of the light")]
        [MinValue(0.0f)]
        [MaxValue(20.0f)]
        [StepSize(0.1f)]
        [HDR(true)]
        Color LightColor = new Color(20.0f, 16.0f, 10.0f);

        [HelpText("Enables direct lighting")]
        bool EnableDirectLighting = true;

        [HelpText("Enables ambient lighting from the environment")]
        bool EnableAmbientLighting = true;

        bool RenderBackground = true;

        bool EnableShadows = true;

        bool EnableNormalMaps = true;

        [MinValue(0.0f)]
        [MaxValue(1.0f)]
        float NormalMapIntensity = 1.0f;

        [DisplayName("Diffuse Intensity")]
        [MinValue(0.0f)]
        [MaxValue(1.0f)]
        [StepSize(0.001f)]
        [HelpText("Diffuse albedo intensity parameter for the material")]
        float DiffuseIntensity = 0.5f;

        [MinValue(0.001f)]
        [MaxValue(1.0f)]
        [StepSize(0.001f)]
        [HelpText("Specular roughness parameter for the material")]
        [ConversionMode(ConversionMode.Square)]
        float Roughness = 0.1f;

        [DisplayName("Specular Intensity")]
        [MinValue(0.0f)]
        [MaxValue(1.0f)]
        [StepSize(0.001f)]
        [HelpText("Specular intensity parameter for the material")]
        float SpecularIntensity = 0.05f;

        Orientation ModelOrientation = new Orientation(0.41f, -0.55f, -0.29f, 0.67f);

        [MinValue(0.0f)]
        [MaxValue(10.0f)]
        [StepSize(0.01f)]
        float ModelRotationSpeed = 0.0f;

        bool DoubleSyncInterval = false;

        [MinValue(-16.0f)]
        [MaxValue(16.0f)]
        float ExposureScale = 0.0f;

        bool EnableZoom = false;
    }

    public class PostProcessing
    {
        [DisplayName("Bloom Exposure Offset")]
        [MinValue(-10.0f)]
        [MaxValue(0.0f)]
        [StepSize(0.01f)]
        [HelpText("Exposure offset applied to generate the input of the bloom pass")]
        float BloomExposure = -4.0f;

        [DisplayName("Bloom Magnitude")]
        [MinValue(0.0f)]
        [MaxValue(2.0f)]
        [StepSize(0.01f)]
        [HelpText("Scale factor applied to the bloom results when combined with tone-mapped result")]
        float BloomMagnitude = 1.0f;

        [DisplayName("Bloom Blur Sigma")]
        [MinValue(0.5f)]
        [MaxValue(5.0f)]
        [StepSize(0.01f)]
        [HelpText("Sigma parameter of the Gaussian filter used in the bloom pass")]
        float BloomBlurSigma = 5.0f;

        [MinValue(-10.0f)]
        [MaxValue(10.0f)]
        [StepSize(0.01f)]
        [HelpText("Manual exposure value when auto-exposure is disabled")]
        float ManualExposure = -2.5f;
    }

    // No auto-exposure for this sample
    const bool EnableAutoExposure = false;
    const float KeyValue = 0.115f;
    const float AdaptationRate = 0.5f;
}

<|start_filename|>SampleFramework11/v1.01/ColorConversions.h<|end_filename|>
#pragma once

#include "SF11_Math.h"

// -- color functions
double Blackbody(double wl, double temp);
SampleFramework11::Float3 XYZ2RGB(double X, double Y, double Z);
SampleFramework11::Float3 ComputeBlackbody(double temperature);

void ConvertsRGBToSpectrum(float* spectrum, uint32 numsamples, 
                           SampleFramework11::Float3 sRGB);
SampleFramework11::Float3 ConvertSpectrumTosRGB(float* spectrum, uint32 numsamples,
                                                uint32 lowerBound, uint32 upperBound,
                                                uint32 waveInc);