diff options
Diffstat (limited to 'NvBlast/samples/SampleBase/renderer')
25 files changed, 3511 insertions, 0 deletions
diff --git a/NvBlast/samples/SampleBase/renderer/ConvexRenderMesh.cpp b/NvBlast/samples/SampleBase/renderer/ConvexRenderMesh.cpp new file mode 100644 index 0000000..074cc2d --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/ConvexRenderMesh.cpp @@ -0,0 +1,82 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#include "ConvexRenderMesh.h" +#include "Renderer.h" +#include "PxConvexMesh.h" + + +struct Vertex +{ + PxVec3 position; + PxVec3 normal; +}; + +ConvexRenderMesh::ConvexRenderMesh(const PxConvexMesh* mesh) +{ + const uint32_t nbPolygons = mesh->getNbPolygons(); + const uint8_t* indexBuffer = mesh->getIndexBuffer(); + const PxVec3* meshVertices = mesh->getVertices(); + + uint32_t nbVerts = 0; + uint32_t nbFaces = 0; + + for (uint32_t i = 0; i < nbPolygons; i++) + { + PxHullPolygon data; + mesh->getPolygonData(i, data); + uint32_t nbPolyVerts = data.mNbVerts; + nbVerts += nbPolyVerts; + nbFaces += (nbPolyVerts - 2) * 3; + } + + std::vector<Vertex> vertices; + std::vector<uint16_t> faces; + + vertices.resize(nbVerts); + faces.resize(nbFaces); + + uint32_t vertCounter = 0; + uint32_t facesCounter = 0; + for (uint32_t i = 0; i < nbPolygons; i++) + { + PxHullPolygon data; + mesh->getPolygonData(i, data); + + PxVec3 normal(data.mPlane[0], data.mPlane[1], data.mPlane[2]); + + uint32_t vI0 = vertCounter; + for (uint32_t vI = 0; vI < data.mNbVerts; vI++) + { + vertices[vertCounter].position = meshVertices[indexBuffer[data.mIndexBase + vI]]; + vertices[vertCounter].normal = normal; + vertCounter++; + } + + for (uint32_t vI = 1; vI < uint32_t(data.mNbVerts) - 1; vI++) + { + faces[facesCounter++] = uint16_t(vI0); + faces[facesCounter++] = uint16_t(vI0 + vI + 1); + faces[facesCounter++] = uint16_t(vI0 + vI); + } + } + + std::vector<D3D11_INPUT_ELEMENT_DESC> layout; + layout.push_back({ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }); + layout.push_back({ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }); + + initialize(vertices.data(), (uint32_t)vertices.size(), sizeof(Vertex), layout, faces.data(), nbFaces); +} + + +ConvexRenderMesh::~ConvexRenderMesh() +{ +} + diff --git a/NvBlast/samples/SampleBase/renderer/ConvexRenderMesh.h b/NvBlast/samples/SampleBase/renderer/ConvexRenderMesh.h new file mode 100644 index 0000000..dfe8d8f --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/ConvexRenderMesh.h @@ -0,0 +1,34 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#ifndef CONVEX_RENDER_MESH_H +#define CONVEX_RENDER_MESH_H + +#include "CustomRenderMesh.h" + +namespace physx +{ +class PxConvexMesh; +} + + +/** +PxConvexMesh render mesh +(this class relates to PhysX more then to Renderer) +*/ +class ConvexRenderMesh : public CustomRenderMesh +{ +public: + ConvexRenderMesh(const PxConvexMesh* mesh); + virtual ~ConvexRenderMesh(); +}; + + +#endif //CONVEX_RENDER_MESH_H
\ No newline at end of file diff --git a/NvBlast/samples/SampleBase/renderer/CustomRenderMesh.cpp b/NvBlast/samples/SampleBase/renderer/CustomRenderMesh.cpp new file mode 100644 index 0000000..61ae9e0 --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/CustomRenderMesh.cpp @@ -0,0 +1,96 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#include "CustomRenderMesh.h" + + +CustomRenderMesh::CustomRenderMesh() + : m_indexBuffer(nullptr) +{ +} + +CustomRenderMesh::CustomRenderMesh(const void* vertices, uint32_t numVertices, uint32_t vertexSize, std::vector<D3D11_INPUT_ELEMENT_DESC>& inputDesc, const uint16_t* faces, uint32_t numFaces) + : m_indexBuffer(nullptr) +{ + initialize(vertices, numVertices, vertexSize, inputDesc, faces, numFaces); +} + +void CustomRenderMesh::initialize(const void* vertices, uint32_t numVertices, uint32_t vertexSize, std::vector<D3D11_INPUT_ELEMENT_DESC>& inputDesc, const uint16_t* faces, uint32_t numFaces) +{ + ID3D11Device* device = GetDeviceManager()->GetDevice(); + + m_inputDesc = inputDesc; + m_numVertices = numVertices; + m_vertexSize = vertexSize; + m_numFaces = numFaces; + + // VB + { + D3D11_SUBRESOURCE_DATA vertexBufferData; + + ZeroMemory(&vertexBufferData, sizeof(vertexBufferData)); + vertexBufferData.pSysMem = vertices; + + D3D11_BUFFER_DESC bufferDesc; + + memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.ByteWidth = vertexSize * numVertices; + bufferDesc.CPUAccessFlags = 0; + bufferDesc.MiscFlags = 0; + bufferDesc.Usage = D3D11_USAGE_IMMUTABLE; + + V(device->CreateBuffer(&bufferDesc, &vertexBufferData, &m_vertexBuffer)); + } + + // IB + if (faces != nullptr) + { + D3D11_SUBRESOURCE_DATA indexBufferData; + + ZeroMemory(&indexBufferData, sizeof(indexBufferData)); + indexBufferData.pSysMem = faces; + + D3D11_BUFFER_DESC bufferDesc; + + memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); + bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc.ByteWidth = sizeof(uint16_t) * numFaces; + bufferDesc.CPUAccessFlags = 0; + bufferDesc.MiscFlags = 0; + bufferDesc.Usage = D3D11_USAGE_IMMUTABLE; + + V(device->CreateBuffer(&bufferDesc, &indexBufferData, &m_indexBuffer)); + } +} + +CustomRenderMesh::~CustomRenderMesh() +{ + SAFE_RELEASE(m_vertexBuffer); + SAFE_RELEASE(m_indexBuffer); +} + + +void CustomRenderMesh::render(ID3D11DeviceContext& context) const +{ + context.IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + UINT strides[1] = { m_vertexSize }; + UINT offsets[1] = { 0 }; + context.IASetVertexBuffers(0, 1, &m_vertexBuffer, strides, offsets); + + context.IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R16_UINT, 0); + + if (m_indexBuffer) + context.DrawIndexed(m_numFaces, 0, 0); + else + context.Draw(m_numVertices, 0); +} + diff --git a/NvBlast/samples/SampleBase/renderer/CustomRenderMesh.h b/NvBlast/samples/SampleBase/renderer/CustomRenderMesh.h new file mode 100644 index 0000000..b0ddea1 --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/CustomRenderMesh.h @@ -0,0 +1,41 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#ifndef CUSTOM_RENDER_MESH_H +#define CUSTOM_RENDER_MESH_H + +#include "Renderable.h" + + +class CustomRenderMesh : public IRenderMesh +{ +public: + const std::vector<D3D11_INPUT_ELEMENT_DESC>& getInputElementDesc() const { return m_inputDesc; } + void render(ID3D11DeviceContext& context) const; + + CustomRenderMesh(const void* vertices, uint32_t numVertices, uint32_t vertexSize, std::vector<D3D11_INPUT_ELEMENT_DESC>& inputDesc, const uint16_t* faces = nullptr, uint32_t numFaces = 0); + virtual ~CustomRenderMesh(); + +protected: + CustomRenderMesh(); + void initialize(const void* vertices, uint32_t numVertices, uint32_t vertexSize, std::vector<D3D11_INPUT_ELEMENT_DESC>& inputDesc, const uint16_t* faces, uint32_t numFaces); + +private: + ID3D11Buffer* m_vertexBuffer; + ID3D11Buffer* m_indexBuffer; + uint32_t m_numFaces; + uint32_t m_numVertices; + uint32_t m_vertexSize; + + std::vector<D3D11_INPUT_ELEMENT_DESC> m_inputDesc; +}; + + +#endif //CUSTOM_RENDER_MESH_H
\ No newline at end of file diff --git a/NvBlast/samples/SampleBase/renderer/DebugRenderBuffer.h b/NvBlast/samples/SampleBase/renderer/DebugRenderBuffer.h new file mode 100644 index 0000000..7810733 --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/DebugRenderBuffer.h @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#ifndef DEBUGRENDERBUFFER_H +#define DEBUGRENDERBUFFER_H + +#include "PxRenderBuffer.h" +#include <vector> + +using namespace physx; + + +/** +Simple PxRenderBuffer implementation for easy debug primitives adding +*/ +class DebugRenderBuffer : public PxRenderBuffer +{ +public: + ~DebugRenderBuffer() {} + + virtual PxU32 getNbPoints() const { return 0; } + virtual const PxDebugPoint* getPoints() const { return nullptr; } + + virtual PxU32 getNbLines() const { return static_cast<PxU32>(m_lines.size()); } + virtual const PxDebugLine* getLines() const { return m_lines.data(); } + + virtual PxU32 getNbTriangles() const { return 0; } + virtual const PxDebugTriangle* getTriangles() const { return nullptr; } + + virtual PxU32 getNbTexts() const { return 0; } + virtual const PxDebugText* getTexts() const { return nullptr; } + + virtual void append(const PxRenderBuffer& other) {} + virtual void clear() + { + m_lines.clear(); + } + + std::vector<PxDebugLine> m_lines; +}; + + +#endif //DEBUGRENDERBUFFER_H
\ No newline at end of file diff --git a/NvBlast/samples/SampleBase/renderer/Mesh.cpp b/NvBlast/samples/SampleBase/renderer/Mesh.cpp new file mode 100644 index 0000000..cdf63f2 --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/Mesh.cpp @@ -0,0 +1,13 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + + +#include "Mesh.h" + diff --git a/NvBlast/samples/SampleBase/renderer/Mesh.h b/NvBlast/samples/SampleBase/renderer/Mesh.h new file mode 100644 index 0000000..6951198 --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/Mesh.h @@ -0,0 +1,51 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#ifndef MESH_H +#define MESH_H + +#include <vector> +#include "PxVec2.h" +#include "PxVec3.h" + + +class Mesh +{ + virtual uint32_t getVertexStride() = 0; + // ... TBD +}; + +/** +SimpleMesh: position + normal + uv +We use only this type everywhere, once other versions will be required we should generalize Mesh and refactor code. +*/ +class SimpleMesh : public Mesh +{ +public: + + class Vertex + { + public: + physx::PxVec3 position; + physx::PxVec3 normal; + physx::PxVec2 uv; + }; + + virtual uint32_t getVertexStride() { return sizeof(Vertex); } + + std::vector<Vertex> vertices; + std::vector<uint16_t> indices; + + physx::PxVec3 extents; + physx::PxVec3 center; +}; + + +#endif //MESH_H
\ No newline at end of file diff --git a/NvBlast/samples/SampleBase/renderer/PrimitiveRenderMesh.cpp b/NvBlast/samples/SampleBase/renderer/PrimitiveRenderMesh.cpp new file mode 100644 index 0000000..329f47b --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/PrimitiveRenderMesh.cpp @@ -0,0 +1,205 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + + +#include "PrimitiveRenderMesh.h" +#include "Renderer.h" + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Base Mesh internal class +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +PrimitiveRenderMesh::PrimitiveRenderMesh(const float v[], UINT numVertices) +{ + std::vector<D3D11_INPUT_ELEMENT_DESC> layout; + layout.push_back({ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }); + layout.push_back({ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }); + + initialize(v, numVertices, sizeof(float) * 6, layout, nullptr, 0); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Box Mesh +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +const float boxVertices[] = +{ + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, + + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, + -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, + + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, + + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, + 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, + -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, + + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f +}; + +BoxRenderMesh::BoxRenderMesh() : PrimitiveRenderMesh(boxVertices, sizeof(boxVertices) / (6 * sizeof(boxVertices[0]))) {} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Plane Mesh +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +const float planeSize = 1.0f; // we use scaling instead +const float planeTilesCount = 1000.0f; + +const float planeVertices[] = +{ + 0, planeSize, planeSize, 1.0f, 0.0f, 0.0f, planeTilesCount, planeTilesCount, + 0, planeSize, -planeSize, 1.0f, 0.0f, 0.0f, planeTilesCount, -planeTilesCount, + 0, -planeSize, -planeSize, 1.0f, 0.0f, 0.0f, -planeTilesCount, -planeTilesCount, + 0, -planeSize, -planeSize, 1.0f, 0.0f, 0.0f, -planeTilesCount, -planeTilesCount, + 0, -planeSize, planeSize, 1.0f, 0.0f, 0.0f, -planeTilesCount, planeTilesCount, + 0, planeSize, planeSize, 1.0f, 0.0f, 0.0f, planeTilesCount, planeTilesCount +}; + +PlaneRenderMesh::PlaneRenderMesh() +{ + std::vector<D3D11_INPUT_ELEMENT_DESC> layout; + layout.push_back({ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }); + layout.push_back({ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }); + layout.push_back({ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }); + + initialize(planeVertices, sizeof(planeVertices) / (8 * sizeof(planeVertices[0])), sizeof(float) * 8, layout, nullptr, 0); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Sphere Mesh +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +const uint32_t g_numSlices = 8; // along lines of longitude +const uint32_t g_numStacks = 16; // along lines of latitude + +const uint32_t g_numSphereVertices = (g_numSlices * 2 + 1)*(g_numStacks + 1); +const uint32_t g_numSphereIndices = g_numSlices * 2 * g_numStacks * 6; + +const uint32_t g_numConeVertices = (g_numSlices * 2 + 1) * 2; +const uint32_t g_numConeIndices = g_numSlices * 2 * 6; + +PxVec3 g_spherePositions[g_numSphereVertices]; +uint16_t g_sphereIndices[g_numSphereIndices]; + +void generateSphereMesh(uint16_t slices, uint16_t stacks, PxVec3* positions, uint16_t* indices) +{ + const PxF32 thetaStep = PxPi / stacks; + const PxF32 phiStep = PxTwoPi / (slices * 2); + + PxF32 theta = 0.0f; + + // generate vertices + for (uint16_t y = 0; y <= stacks; ++y) + { + PxF32 phi = 0.0f; + + PxF32 cosTheta = PxCos(theta); + PxF32 sinTheta = PxSin(theta); + + for (uint16_t x = 0; x <= slices * 2; ++x) + { + PxF32 cosPhi = PxCos(phi); + PxF32 sinPhi = PxSin(phi); + + PxVec3 p(cosPhi*sinTheta, cosTheta, sinPhi*sinTheta); + + // write vertex + *(positions++) = p; + + phi += phiStep; + } + + theta += thetaStep; + } + + const uint16_t numRingQuads = 2 * slices; + const uint16_t numRingVerts = 2 * slices + 1; + + // add faces + for (uint16_t y = 0; y < stacks; ++y) + { + for (uint16_t i = 0; i < numRingQuads; ++i) + { + // add a quad + *(indices++) = (y + 0)*numRingVerts + i; + *(indices++) = (y + 1)*numRingVerts + i; + *(indices++) = (y + 1)*numRingVerts + i + 1; + + *(indices++) = (y + 1)*numRingVerts + i + 1; + *(indices++) = (y + 0)*numRingVerts + i + 1; + *(indices++) = (y + 0)*numRingVerts + i; + } + } +} + + +struct SphereVertex +{ + PxVec3 position; + PxVec3 normal; +}; + +SphereRenderMesh::SphereRenderMesh() +{ + generateSphereMesh(g_numSlices, g_numStacks, g_spherePositions, g_sphereIndices); + + std::vector<SphereVertex> vertices; + for (uint32_t i = 0; i < g_numSphereVertices; i++) + { + vertices.push_back({ g_spherePositions[i], g_spherePositions[i] }); + } + + std::vector<D3D11_INPUT_ELEMENT_DESC> layout; + layout.push_back({ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }); + layout.push_back({ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }); + + initialize(vertices.data(), (uint32_t)vertices.size(), sizeof(SphereVertex), layout, g_sphereIndices, g_numSphereIndices); +} + + +SphereRenderMesh::~SphereRenderMesh() +{ +} diff --git a/NvBlast/samples/SampleBase/renderer/PrimitiveRenderMesh.h b/NvBlast/samples/SampleBase/renderer/PrimitiveRenderMesh.h new file mode 100644 index 0000000..f72c191 --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/PrimitiveRenderMesh.h @@ -0,0 +1,61 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#ifndef PRIMITIVE_RENDER_MESH_H +#define PRIMITIVE_RENDER_MESH_H + +#include "Utils.h" +#include <DirectXMath.h> + +#include <vector> +#include "Renderable.h" +#include "CustomRenderMesh.h" + + +class PrimitiveRenderMesh : public CustomRenderMesh +{ +protected: + PrimitiveRenderMesh(const float v[], UINT numVertices); +}; + +class BoxRenderMesh : public PrimitiveRenderMesh +{ +public: + BoxRenderMesh(); +}; + + +class PlaneRenderMesh : public CustomRenderMesh +{ +public: + PlaneRenderMesh(); +}; + + +class SphereRenderMesh : public CustomRenderMesh +{ +public: + SphereRenderMesh(); + virtual ~SphereRenderMesh(); +}; + + +struct PrimitiveRenderMeshType +{ + enum Enum + { + Box, + Plane, + Sphere, + Count + }; +}; + +#endif //PRIMITIVE_RENDER_MESH_H
\ No newline at end of file diff --git a/NvBlast/samples/SampleBase/renderer/RenderMaterial.cpp b/NvBlast/samples/SampleBase/renderer/RenderMaterial.cpp new file mode 100644 index 0000000..cb40ec7 --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/RenderMaterial.cpp @@ -0,0 +1,206 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#include "RenderMaterial.h" +#include <DirectXMath.h> +#include "ShaderUtils.h" +#include "Renderer.h" + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// RenderMaterial +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +RenderMaterial::RenderMaterial(ResourceManager& resourceCallback, const char* shaderFileName, + const char* textureFileName, BlendMode blendMode) +{ + this->initialize(resourceCallback, shaderFileName, textureFileName, blendMode); +} + +void RenderMaterial::initialize(ResourceManager& resourceCallback, const char* shaderFileName, const char* textureFileName, BlendMode blendMode) +{ + std::vector<std::string> v; + v.push_back(shaderFileName); + initialize(resourceCallback, v, textureFileName, blendMode); +} + +void RenderMaterial::initialize(ResourceManager& resourceCallback, std::vector<std::string> shaderFileNames, const char* textureFileName, BlendMode blendMode) +{ + mTextureSRV = nullptr; + mTexture = nullptr; + mBlendState = nullptr; + mTextureFileName = textureFileName; + + for (uint32_t i = 0; i < shaderFileNames.size(); i++) + { + const ShaderFileResource* resource = resourceCallback.requestShaderFile(shaderFileNames[i].c_str()); + if (resource) + { + std::string shaderFilePath = resource->path; + mShaderFilePathes.push_back(shaderFilePath); + } + } + mShaderGroups.reserve(mShaderFilePathes.size()); + + if (!mTextureFileName.empty()) + { + mTexture = resourceCallback.requestTexture(mTextureFileName.c_str()); + } + + setBlending(blendMode); + + reload(); +} + +void RenderMaterial::releaseReloadableResources() +{ + for (std::vector<ShaderGroup*>::iterator it = mShaderGroups.begin(); it != mShaderGroups.end(); it++) + { + delete *it; + } + mShaderGroups.clear(); + + SAFE_RELEASE(mTextureSRV); +} + +RenderMaterial::~RenderMaterial() +{ + releaseReloadableResources(); + SAFE_RELEASE(mBlendState); +} + +void RenderMaterial::setBlending(BlendMode blendMode) +{ + mBlendMode = blendMode; + + SAFE_RELEASE(mBlendState); + + D3D11_BLEND_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + + switch (blendMode) + { + case BLEND_NONE: + desc.RenderTarget[0].BlendEnable = FALSE; + desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; + break; + case BLEND_ALPHA_BLENDING: + desc.AlphaToCoverageEnable = FALSE; + desc.IndependentBlendEnable = TRUE; + desc.RenderTarget[0].BlendEnable = TRUE; + desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; + desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; + desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA; + desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; + break; + case BLEND_ADDITIVE: // actually, is's additive by alpha + desc.AlphaToCoverageEnable = FALSE; + desc.IndependentBlendEnable = TRUE; + desc.RenderTarget[0].BlendEnable = TRUE; + desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].DestBlend = D3D11_BLEND_ONE; + desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE; + desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; + desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA; + desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; + break; + default: + PX_ALWAYS_ASSERT_MESSAGE("Unknown blend mode"); + } + + ID3D11Device* device = GetDeviceManager()->GetDevice(); + V(device->CreateBlendState(&desc, &mBlendState)); +} + +void RenderMaterial::reload() +{ + releaseReloadableResources(); + + // load shaders + ID3D11Device* device = GetDeviceManager()->GetDevice(); + + for (std::vector<std::string>::iterator it = mShaderFilePathes.begin(); it != mShaderFilePathes.end(); it++) + { + const char* shaderFilePath = (*it).c_str(); + ShaderGroup* shaderGroup = new ShaderGroup(); + V(createShaderFromFile(device, shaderFilePath, "VS", &(shaderGroup->vs), shaderGroup->buffer)); + createShaderFromFile(device, shaderFilePath, "PS", &shaderGroup->ps); + createShaderFromFile(device, shaderFilePath, "GS", &shaderGroup->gs); + mShaderGroups.push_back(shaderGroup); + } + + // load texture + if (mTexture) + { + V(DirectX::CreateShaderResourceView(device, mTexture->image.GetImages(), mTexture->image.GetImageCount(), + mTexture->metaData, &mTextureSRV)); + } +} + + + +RenderMaterial::InstancePtr RenderMaterial::getMaterialInstance(const IRenderMesh* mesh) +{ + // look in cache + auto it = mRenderMeshToInstanceMap.find(mesh); + if (it != mRenderMeshToInstanceMap.end()) + { + if (!(*it).second.expired()) + { + return (*it).second.lock(); + } + } + + // create new + const std::vector<D3D11_INPUT_ELEMENT_DESC>& descs = mesh->getInputElementDesc(); + RenderMaterial::InstancePtr instance = getMaterialInstance(&descs[0], (uint32_t)descs.size()); + mRenderMeshToInstanceMap[mesh] = instance; + return instance; +} + +RenderMaterial::InstancePtr RenderMaterial::getMaterialInstance(const D3D11_INPUT_ELEMENT_DESC* elementDescs, uint32_t numElements) +{ + ID3D11Device* device = GetDeviceManager()->GetDevice(); + + for (uint32_t i = 0; i < mShaderGroups.size(); i++) + { + if (mShaderGroups[i]->buffer == NULL) + continue; + + ID3D11InputLayout* inputLayout = NULL; + device->CreateInputLayout(elementDescs, numElements, mShaderGroups[i]->buffer->GetBufferPointer(), mShaderGroups[i]->buffer->GetBufferSize(), &inputLayout); + + if (inputLayout) + { + RenderMaterial::InstancePtr materialInstance(new Instance(*this, inputLayout, i)); + return materialInstance; + } + } + PX_ALWAYS_ASSERT(); + return NULL; +} + +void RenderMaterial::Instance::bind(ID3D11DeviceContext& context, uint32_t slot, bool depthStencilOnly) +{ + mMaterial.mShaderGroups[mShaderNum]->Set(&context, !depthStencilOnly); + + context.OMSetBlendState(mMaterial.mBlendState, nullptr, 0xFFFFFFFF); + context.PSSetShaderResources(slot, 1, &(mMaterial.mTextureSRV)); + context.IASetInputLayout(mInputLayout); +} + +bool RenderMaterial::Instance::isValid() +{ + return mMaterial.mShaderGroups.size() > 0 && mMaterial.mShaderGroups[mShaderNum]->IsValid(); +} diff --git a/NvBlast/samples/SampleBase/renderer/RenderMaterial.h b/NvBlast/samples/SampleBase/renderer/RenderMaterial.h new file mode 100644 index 0000000..a342459 --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/RenderMaterial.h @@ -0,0 +1,118 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#ifndef RENDER_MATERIAL_H +#define RENDER_MATERIAL_H + +#include "Utils.h" +#include "DirectXTex.h" + +#include <string> +#include <vector> +#include <list> +#include <map> +#include <memory> + + +class IRenderMesh; +class ResourceManager; +struct TextureResource; + + +class RenderMaterial +{ + public: + + enum BlendMode + { + BLEND_NONE, + BLEND_ALPHA_BLENDING, + BLEND_ADDITIVE + }; + + RenderMaterial(ResourceManager& resourceProvider, const char* shaderFileName, const char* textureFileName = "", BlendMode blendMode = BLEND_NONE); + ~RenderMaterial(); + + void setBlending(BlendMode blendMode); + BlendMode getBlending() const { return mBlendMode; } + + void reload(); + + class Instance + { + public: + Instance(RenderMaterial& material, ID3D11InputLayout* inputLayout, uint32_t shaderNum = 0) : mMaterial(material), mInputLayout(inputLayout), mShaderNum(shaderNum) {} + ~Instance() { SAFE_RELEASE(mInputLayout); } + + bool isValid(); + void bind(ID3D11DeviceContext& context, uint32_t slot, bool depthStencilOnly = false); + RenderMaterial& getMaterial() const { return mMaterial; } + private: + RenderMaterial& mMaterial; + ID3D11InputLayout* mInputLayout; + uint32_t mShaderNum; + }; + + typedef std::shared_ptr<Instance> InstancePtr; + + InstancePtr getMaterialInstance(const IRenderMesh* mesh); + InstancePtr getMaterialInstance(const D3D11_INPUT_ELEMENT_DESC* elementDescs, uint32_t numElements); + + private: + void initialize(ResourceManager& resourceCallback, const char* shaderFileName, const char* textureFileName, BlendMode blendMode); + void initialize(ResourceManager&resourceProvider, std::vector<std::string> shaderFileNames, const char* textureFileName, BlendMode blendMode); + + void releaseReloadableResources(); + + std::string mShaderFileName; + std::string mTextureFileName; + + struct ShaderGroup + { + ShaderGroup() : vs(nullptr), gs(nullptr), ps(nullptr), buffer(nullptr) + { + } + ~ShaderGroup() + { + Release(); + } + void Release() + { + SAFE_RELEASE(vs); + SAFE_RELEASE(gs); + SAFE_RELEASE(ps); + SAFE_RELEASE(buffer); + } + void Set(ID3D11DeviceContext* c, bool setPixelShader = true) + { + c->VSSetShader(vs, nullptr, 0); + c->GSSetShader(gs, nullptr, 0); + c->PSSetShader(setPixelShader ? ps : nullptr, nullptr, 0); + } + bool IsValid() + { + return vs != nullptr; + } + ID3D11VertexShader* vs; + ID3D11GeometryShader* gs; + ID3D11PixelShader* ps; + ID3DBlob* buffer; + }; + + std::map<const IRenderMesh*, std::weak_ptr<Instance>> mRenderMeshToInstanceMap; + const TextureResource* mTexture; + ID3D11ShaderResourceView* mTextureSRV; + std::vector<std::string> mShaderFilePathes; + std::vector<ShaderGroup*> mShaderGroups; + ID3D11BlendState* mBlendState; + BlendMode mBlendMode; +}; + +#endif
\ No newline at end of file diff --git a/NvBlast/samples/SampleBase/renderer/RenderUtils.h b/NvBlast/samples/SampleBase/renderer/RenderUtils.h new file mode 100644 index 0000000..12df9f2 --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/RenderUtils.h @@ -0,0 +1,78 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#ifndef RENDER_UTILS_H +#define RENDER_UTILS_H + +#include "DirectXTex.h" +#include <DirectXMath.h> +#include "PxMat44.h" +#include "PxVec3.h" +#include "PxVec4.h" + +static DirectX::XMFLOAT4 getRandomPastelColor() +{ + float r = ((double)rand() / (RAND_MAX)) * 0.5f + 0.5f; + float g = ((double)rand() / (RAND_MAX)) * 0.5f + 0.5f; + float b = ((double)rand() / (RAND_MAX)) * 0.5f + 0.5f; + return DirectX::XMFLOAT4(r, g, b, 1.0f); +} + +static physx::PxMat44 XMMATRIXToPxMat44(const DirectX::XMMATRIX& mat) +{ + physx::PxMat44 m; + memcpy(const_cast<float*>(m.front()), &mat.r[0], 4 * 4 * sizeof(float)); + return m; +} + +static DirectX::XMMATRIX PxMat44ToXMMATRIX(const physx::PxMat44& mat) +{ + return DirectX::XMMATRIX(mat.front()); +} + +static physx::PxVec4 XMVECTORToPxVec4(const DirectX::XMVECTOR& vec) +{ + DirectX::XMFLOAT4 f; + DirectX::XMStoreFloat4(&f, vec); + return physx::PxVec4(f.x, f.y, f.z, f.w); +} + +static physx::PxVec3 XMFLOAT3ToPxVec3(const DirectX::XMFLOAT3& vec) +{ + return physx::PxVec3(vec.x, vec.y, vec.z); +} + +static physx::PxVec4 XMFLOAT4ToPxVec4(const DirectX::XMFLOAT4& vec) +{ + return physx::PxVec4(vec.x, vec.y, vec.z, vec.w); +} + +static uint32_t XMFLOAT4ToU32Color(const DirectX::XMFLOAT4& color) +{ + uint32_t c = 0; + c |= (int)(color.w * 255); c <<= 8; + c |= (int)(color.z * 255); c <<= 8; + c |= (int)(color.y * 255); c <<= 8; + c |= (int)(color.x * 255); + return c; +} + +static DirectX::XMFLOAT4 XMFLOAT4Lerp(const DirectX::XMFLOAT4 v0, const DirectX::XMFLOAT4 v1, float val) +{ + DirectX::XMFLOAT4 v( + v0.x * (1 - val) + v1.x * val, + v0.y * (1 - val) + v1.y * val, + v0.z * (1 - val) + v1.z * val, + v0.w * (1 - val) + v1.w * val + ); + return v; +} + +#endif //RENDER_UTILS_H
\ No newline at end of file diff --git a/NvBlast/samples/SampleBase/renderer/Renderable.cpp b/NvBlast/samples/SampleBase/renderer/Renderable.cpp new file mode 100644 index 0000000..340874b --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/Renderable.cpp @@ -0,0 +1,48 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#include "Renderable.h" +#include "Renderer.h" +#include "RenderUtils.h" + +const DirectX::XMFLOAT4 DEFAULT_COLOR(0.5f, 0.5f, 0.5f, 1.0f); + +Renderable::Renderable(IRenderMesh& mesh, RenderMaterial& material) : m_mesh(mesh), m_scale(1, 1, 1), m_color(DEFAULT_COLOR), m_hidden(false), m_transform(PxIdentity) +{ + setMaterial(material); +} + +void Renderable::setMaterial(RenderMaterial& material) +{ + m_materialInstance = material.getMaterialInstance(&m_mesh); +} + +void Renderable::render(Renderer& renderer, bool depthStencilOnly) const +{ + if (!m_materialInstance->isValid()) + { + PX_ALWAYS_ASSERT(); + return; + } + + m_materialInstance->bind(*renderer.m_context, 0, depthStencilOnly); + + // setup object CB + { + D3D11_MAPPED_SUBRESOURCE mappedResource; + renderer.m_context->Map(renderer.m_objectCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + Renderer::CBObject* objectBuffer = (Renderer::CBObject*)mappedResource.pData; + objectBuffer->world = PxMat44ToXMMATRIX(getModelMatrix()); + objectBuffer->color = getColor(); + renderer.m_context->Unmap(renderer.m_objectCB, 0); + } + + m_mesh.render(*renderer.m_context); +} diff --git a/NvBlast/samples/SampleBase/renderer/Renderable.h b/NvBlast/samples/SampleBase/renderer/Renderable.h new file mode 100644 index 0000000..f1faa52 --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/Renderable.h @@ -0,0 +1,128 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#ifndef RENDERABLE_H +#define RENDERABLE_H + +#include "RenderMaterial.h" +#include <DirectXMath.h> +#include "PxMat44.h" +#include "PxVec3.h" +#include "PxVec4.h" + +using namespace physx; + +class Renderer; + +/** +RenderMesh interface, used by Renderable +*/ +class IRenderMesh +{ +public: + virtual ~IRenderMesh() {} + virtual const std::vector<D3D11_INPUT_ELEMENT_DESC>& getInputElementDesc() const = 0; + virtual void render(ID3D11DeviceContext& context) const = 0; +}; + +/** +Renderable, represents single object renderer by Renderer. +Basically Renderable = RenderMaterial + RenderMesh +*/ +class Renderable +{ +public: + //////// public API //////// + + void setMaterial(RenderMaterial& material); + + PxMat44 getModelMatrix() const + { + return PxMat44(m_transform) * PxMat44(PxVec4(m_scale, 1)); + } + + void setTransform(PxTransform& transform) + { + m_transform = transform; + } + + const PxTransform& getTransform() const + { + return m_transform; + } + + void setScale(PxVec3 scale) + { + m_scale = scale; + } + + const PxVec3& getScale() const + { + return m_scale; + } + + void setColor(DirectX::XMFLOAT4 color) + { + m_color = color; + } + DirectX::XMFLOAT4 getColor() const + { + return m_color; + } + + void setHidden(bool hidden) + { + m_hidden = hidden; + } + + bool isHidden() const + { + return m_hidden; + } + + bool isTransparent() const + { + return !(m_materialInstance->getMaterial().getBlending() == RenderMaterial::BLEND_NONE); + } + + RenderMaterial& getMaterial() const { return m_materialInstance->getMaterial(); } + +private: + //////// methods used by Renderer //////// + + friend class Renderer; + + void render(Renderer& renderer) const + { + render(renderer, false); + } + + void renderDepthStencilOnly(Renderer& renderer) const + { + render(renderer, true); + } + + Renderable(IRenderMesh& mesh, RenderMaterial& material); + + void render(Renderer& renderer, bool depthStencilOnly) const; + + + //////// internal data //////// + + DirectX::XMFLOAT4 m_color; + PxTransform m_transform; + PxVec3 m_scale; + + RenderMaterial::InstancePtr m_materialInstance; + IRenderMesh& m_mesh; + bool m_hidden; +}; + +#endif //RENDERABLE_H
\ No newline at end of file diff --git a/NvBlast/samples/SampleBase/renderer/Renderer.cpp b/NvBlast/samples/SampleBase/renderer/Renderer.cpp new file mode 100644 index 0000000..94ea3c3 --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/Renderer.cpp @@ -0,0 +1,729 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#include "Renderer.h" +#include "RenderUtils.h" +#include "UIHelpers.h" +#include "SampleProfiler.h" + +#include "PxRenderBuffer.h" + +#include <set> + + +const float CAMERA_CLIP_NEAR = 1.0f; +const float CAMERA_CLIP_FAR = 1000.00f; + +const float CLEAR_SCENE_COLOR[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Renderer +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +Renderer::Renderer() +: m_cameraCB(nullptr) +, m_worldCB(nullptr) +, m_objectCB(nullptr) +, m_RSState(nullptr) +, m_opaqueRenderDSState(nullptr) +, m_transparencyRenderDSState(nullptr) +, m_DSTexture(nullptr) +, m_DSView(nullptr) +, m_DSTextureSRV(nullptr) +, m_pointSampler(nullptr) +, m_linearSampler(nullptr) +, m_wireframeMode(false) +, m_debugPrimitiveVB(nullptr) +, m_debugPrimitiveVBVerticesCount(0) +, m_shadowEnabled(true) +, m_HBAOEnabled(true) +, m_visibleOpaqueRenderablesCount(0) +, m_visibleTransparentRenderablesCount(0) +{ + m_worldCBData.ambientColor = DirectX::XMFLOAT3(0.21f, 0.21f, 0.22f); + m_worldCBData.pointLightColor = DirectX::XMFLOAT3(1.0f, 1.0f, 1.0f); + m_worldCBData.pointLightPos = DirectX::XMFLOAT3(0.0f, 30.0f, 12.0f); + m_worldCBData.dirLightColor = DirectX::XMFLOAT3(0.0f, 0.0f, 0.0f); + m_worldCBData.dirLightDir = DirectX::XMFLOAT3(-0.08f, -0.34f, -0.91f); + m_worldCBData.specularPower = 140.0f; + m_worldCBData.specularIntensity = 0.4f; + + toggleCameraSpeed(false); +} + +Renderer::~Renderer() +{ +} + +void Renderer::initializeDefaultRSState() +{ + SAFE_RELEASE(m_RSState); + D3D11_RASTERIZER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.CullMode = D3D11_CULL_FRONT; + desc.FillMode = m_wireframeMode ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID; + desc.AntialiasedLineEnable = FALSE; + desc.DepthBias = 0; + desc.DepthBiasClamp = 0; + desc.DepthClipEnable = TRUE; + desc.FrontCounterClockwise = FALSE; + desc.MultisampleEnable = TRUE; + desc.ScissorEnable = FALSE; + desc.SlopeScaledDepthBias = 0; + + V(m_device->CreateRasterizerState(&desc, &m_RSState)); +} + +HRESULT Renderer::DeviceCreated(ID3D11Device* device) +{ + m_device = device; + + // Camera constant buffer + { + D3D11_BUFFER_DESC buffer_desc; + ZeroMemory(&buffer_desc, sizeof(buffer_desc)); + buffer_desc.Usage = D3D11_USAGE_DYNAMIC; + buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + buffer_desc.ByteWidth = sizeof(CBCamera); + _ASSERT((buffer_desc.ByteWidth % 16) == 0); + + V(device->CreateBuffer(&buffer_desc, nullptr, &m_cameraCB)); + } + + // World constant buffer + { + D3D11_BUFFER_DESC buffer_desc; + ZeroMemory(&buffer_desc, sizeof(buffer_desc)); + buffer_desc.Usage = D3D11_USAGE_DYNAMIC; + buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + buffer_desc.ByteWidth = sizeof(CBWorld); + _ASSERT((buffer_desc.ByteWidth % 16) == 0); + + V(device->CreateBuffer(&buffer_desc, nullptr, &m_worldCB)); + } + + // Object constant buffer + { + D3D11_BUFFER_DESC buffer_desc; + ZeroMemory(&buffer_desc, sizeof(buffer_desc)); + buffer_desc.Usage = D3D11_USAGE_DYNAMIC; + buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + buffer_desc.ByteWidth = sizeof(CBObject); + _ASSERT((buffer_desc.ByteWidth % 16) == 0); + + V(device->CreateBuffer(&buffer_desc, nullptr, &m_objectCB)); + } + + // Opaque Render Depth-Stencil state + { + D3D11_DEPTH_STENCIL_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.StencilEnable = FALSE; + desc.DepthEnable = TRUE; + desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + desc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; + + V(device->CreateDepthStencilState(&desc, &m_opaqueRenderDSState)); + } + + // Transparency Render Depth-Stencil state + { + D3D11_DEPTH_STENCIL_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.StencilEnable = FALSE; + desc.DepthEnable = TRUE; + desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; + desc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; + + V(device->CreateDepthStencilState(&desc, &m_transparencyRenderDSState)); + } + + // Linear sampler + { + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + desc.MaxAnisotropy = 1; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0; + desc.MaxLOD = D3D11_FLOAT32_MAX; + V(device->CreateSamplerState(&desc, &m_linearSampler)); + } + + // Point sampler + { + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + desc.MaxAnisotropy = 1; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0; + desc.MaxLOD = D3D11_FLOAT32_MAX; + V(device->CreateSamplerState(&desc, &m_pointSampler)); + } + + // Rasterizer state + initializeDefaultRSState(); + + // init primitive render meshes + for (uint32_t i = 0; i < PrimitiveRenderMeshType::Count; i++) + { + m_primitiveRenderMeshes[i] = nullptr; + } + + // init shadows + ID3D11DeviceContext* pd3dDeviceContext; + m_device->GetImmediateContext(&pd3dDeviceContext); + m_shadow.createResources(m_device, pd3dDeviceContext, &m_camera); + + // init hbao + m_HBAO.createResources(m_device); + + return S_OK; +} + +void Renderer::DeviceDestroyed() +{ + SAFE_RELEASE(m_cameraCB); + SAFE_RELEASE(m_worldCB); + SAFE_RELEASE(m_objectCB); + SAFE_RELEASE(m_RSState); + SAFE_RELEASE(m_opaqueRenderDSState); + SAFE_RELEASE(m_transparencyRenderDSState); + SAFE_RELEASE(m_pointSampler); + SAFE_RELEASE(m_linearSampler); + SAFE_RELEASE(m_debugPrimitiveVB); + SAFE_RELEASE(m_DSTexture); + SAFE_RELEASE(m_DSView); + SAFE_RELEASE(m_DSTextureSRV); + + for (uint32_t i = 0; i < PrimitiveRenderMeshType::Count; i++) + { + SAFE_DELETE(m_primitiveRenderMeshes[i]); + } +} + +void Renderer::onInitialize() +{ + // search paths + m_resourceManager.addSearchDir("..\\..\\samples\\resources"); + m_resourceManager.addSearchDir("..\\..\\..\\samples\\resources"); + for (const std::string& d : getManager()->getConfig().additionalResourcesDir) + { + m_resourceManager.addSearchDir(d.c_str()); + } + + // debug primitive render material and input layout + { + m_debugPrimitiveRenderMaterial = new RenderMaterial(m_resourceManager, "debug_primitive", ""); + + D3D11_INPUT_ELEMENT_DESC layout[] = { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 } + }; + + m_debugPrimitiveRenderMaterialInstance = m_debugPrimitiveRenderMaterial->getMaterialInstance(layout, ARRAYSIZE(layout)); + } +} + +void Renderer::onTerminate() +{ + SAFE_DELETE(m_debugPrimitiveRenderMaterial); +} + +void Renderer::BackBufferResized(ID3D11Device* /*device*/, const DXGI_SURFACE_DESC* sd) +{ + // Setup the camera's projection parameters + m_screenWidth = sd->Width; + m_screenHeight = sd->Height; + float fAspectRatio = m_screenWidth / m_screenHeight; + m_camera.SetProjParams(DirectX::XM_PIDIV4, fAspectRatio, CAMERA_CLIP_NEAR, CAMERA_CLIP_FAR); + + SAFE_RELEASE(m_DSTexture); + SAFE_RELEASE(m_DSView); + SAFE_RELEASE(m_DSTextureSRV); + + // create a new Depth-Stencil texture + { + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = sd->Width; + desc.Height = sd->Height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R32_TYPELESS; // Use a typeless type here so that it can be both depth-stencil and shader resource. + desc.SampleDesc.Count = sd->SampleDesc.Count; + desc.SampleDesc.Quality = sd->SampleDesc.Quality; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + V(m_device->CreateTexture2D(&desc, NULL, &m_DSTexture)); + } + + // create Depth-Stencil view + { + D3D11_DEPTH_STENCIL_VIEW_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.ViewDimension = sd->SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D; + desc.Format = DXGI_FORMAT_D32_FLOAT; // Make the view see this as D32_FLOAT instead of typeless + desc.Texture2D.MipSlice = 0; + V(m_device->CreateDepthStencilView(m_DSTexture, &desc, &m_DSView)); + } + + // create Depth-Stencil shader resource view + { + D3D11_SHADER_RESOURCE_VIEW_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Format = DXGI_FORMAT_R32_FLOAT; // Make the shaders see this as R32_FLOAT instead of typeless + desc.ViewDimension = sd->SampleDesc.Count > 1 ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D; + desc.Texture2D.MipLevels = 1; + desc.Texture2D.MostDetailedMip = 0; + V(m_device->CreateShaderResourceView(m_DSTexture, &desc, &m_DSTextureSRV)); + } + + // setup viewport + m_viewport.Width = (FLOAT)sd->Width; + m_viewport.Height = (FLOAT)sd->Height; + m_viewport.MinDepth = 0; + m_viewport.MaxDepth = 1; + m_viewport.TopLeftX = 0; + m_viewport.TopLeftY = 0; + + // setup shadows + m_shadow.setScreenResolution(0, sd->Width, sd->Height, sd->SampleDesc.Count, nullptr); +} + +void Renderer::setAllConstantBuffers(ID3D11DeviceContext* ctx) +{ + ID3D11Buffer* cbs[3] = { m_cameraCB, m_worldCB, m_objectCB }; + ctx->VSSetConstantBuffers(0, 3, cbs); + ctx->GSSetConstantBuffers(0, 3, cbs); + ctx->PSSetConstantBuffers(0, 3, cbs); +} + +void Renderer::Render(ID3D11Device* /*device*/, ID3D11DeviceContext* ctx, ID3D11RenderTargetView* pRTV, + ID3D11DepthStencilView*) +{ + PROFILER_SCOPED_FUNCTION(); + + m_context = ctx; + + ctx->ClearRenderTargetView(pRTV, CLEAR_SCENE_COLOR); + ctx->ClearDepthStencilView(m_DSView, D3D11_CLEAR_DEPTH, 1.0, 0); + ctx->RSSetViewports(1, &m_viewport); + + // needed matrices + DirectX::XMMATRIX viewMatrix = m_camera.GetViewMatrix(); + DirectX::XMMATRIX projMatrix = m_camera.GetProjMatrix(); + DirectX::XMMATRIX projMatrixInv = DirectX::XMMatrixInverse(NULL, projMatrix); + DirectX::XMMATRIX viewProjMatrix = viewMatrix * projMatrix; + + // Fill Camera constant buffer + { + D3D11_MAPPED_SUBRESOURCE mappedResource; + ctx->Map(m_cameraCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + CBCamera* cameraBuffer = (CBCamera*)mappedResource.pData; + cameraBuffer->viewProjection = viewProjMatrix; + cameraBuffer->projectionInv = projMatrixInv; + DirectX::XMStoreFloat3(&(cameraBuffer->viewPos), m_camera.GetEyePt()); + ctx->Unmap(m_cameraCB, 0); + } + + // Fill World constant buffer + { + D3D11_MAPPED_SUBRESOURCE mappedResource; + ctx->Map(m_worldCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + CBWorld* worldBuffer = (CBWorld*)mappedResource.pData; + memcpy(worldBuffer, &m_worldCBData, sizeof(m_worldCBData)); + //worldBuffer->ambientColor = m_CBWorldData.ambientColor; + //worldBuffer->pointLightPos = m_CBWorldData.pointLightPos; + //worldBuffer->pointLightColor = m_CBWorldData.pointLightColor; + //worldBuffer->dirLightDir = m_CBWorldData.dirLightDir; + //worldBuffer->specularPower = m_CBWorldData.specularPower; + //worldBuffer->dirLightColor = m_CBWorldData.dirLightColor; + //worldBuffer->specularIntensity = m_CBWorldData.specularIntensity; + ctx->Unmap(m_worldCB, 0); + } + + ctx->RSSetState(m_RSState); + ctx->PSSetSamplers(0, 1, &m_linearSampler); + ctx->PSSetSamplers(1, 1, &m_pointSampler); + + + if (m_shadowEnabled) + { + // render depth only + { + ctx->OMSetRenderTargets(0, nullptr, m_DSView); + ctx->OMSetDepthStencilState(m_opaqueRenderDSState, 0xFF); + + // set constants buffers + setAllConstantBuffers(ctx); + + for (auto it = m_renderables.begin(); it != m_renderables.end(); it++) + { + if (!(*it)->isTransparent() && !(*it)->isHidden()) + (*it)->renderDepthStencilOnly(*this); + } + } + + // render shadow map + m_shadow.renderShadowMaps(this); + + // render shadow buffer + ctx->OMSetRenderTargets(0, nullptr, nullptr); + m_shadow.renderShadowBuffer(m_DSTextureSRV, nullptr); + } + + // Opaque render + { + ctx->RSSetViewports(1, &m_viewport); + ctx->RSSetState(m_RSState); + ctx->OMSetRenderTargets(1, &pRTV, m_DSView); + ctx->OMSetDepthStencilState(m_opaqueRenderDSState, 0xFF); + + // set constants buffers + setAllConstantBuffers(ctx); + + // Fill Camera constant buffer + { + D3D11_MAPPED_SUBRESOURCE mappedResource; + ctx->Map(m_cameraCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + CBCamera* cameraBuffer = (CBCamera*)mappedResource.pData; + cameraBuffer->viewProjection = viewProjMatrix; + cameraBuffer->projectionInv = projMatrixInv; + DirectX::XMStoreFloat3(&(cameraBuffer->viewPos), m_camera.GetEyePt()); + ctx->Unmap(m_cameraCB, 0); + } + + // Render opaque renderables + m_visibleOpaqueRenderablesCount = 0; + for (auto it = m_renderables.begin(); it != m_renderables.end(); it++) + { + if (!(*it)->isTransparent() && !(*it)->isHidden()) + { + (*it)->render(*this); + m_visibleOpaqueRenderablesCount++; + } + } + } + + // modulate shadows + if (m_shadowEnabled) + { + m_shadow.modulateShadowBuffer(pRTV); + } + + // render AO + if (m_HBAOEnabled) + { + m_HBAO.renderAO(m_context, pRTV, m_DSTextureSRV, projMatrix); + } + + ctx->RSSetViewports(1, &m_viewport); + + // render debug render buffers + while (m_queuedRenderBuffers.size() > 0) + { + render(m_queuedRenderBuffers.back()); + m_queuedRenderBuffers.pop_back(); + } + + // Transparency render + ctx->OMSetRenderTargets(1, &pRTV, m_DSView); + ctx->OMSetDepthStencilState(m_transparencyRenderDSState, 0xFF); + + // depth as SRV isn't used now (uncommenting will produce a warning, probably need readonly depth?) + //ctx->PSSetShaderResources(1, 1, &mDSTextureSRV); + + // Render transparent renderables + m_visibleTransparentRenderablesCount = 0; + for (auto it = m_renderables.begin(); it != m_renderables.end(); it++) + { + if ((*it)->isTransparent() && !(*it)->isHidden()) + { + (*it)->render(*this); + m_visibleTransparentRenderablesCount++; + } + } + + // shadows debug render + if (0) + { + m_shadow.displayMapFrustums(pRTV, m_DSView); + } + + // Reset RT and SRV state + ID3D11ShaderResourceView* nullAttach[16] = { nullptr }; + ctx->PSSetShaderResources(0, 16, nullAttach); + ctx->OMSetRenderTargets(0, nullptr, nullptr); +} + +LRESULT Renderer::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + PX_UNUSED(hWnd); + PX_UNUSED(wParam); + PX_UNUSED(lParam); + + if (uMsg == WM_KEYDOWN || uMsg == WM_KEYUP) + { + // Camera overspeed event + int iKeyPressed = static_cast<int>(wParam); + if (iKeyPressed == VK_SHIFT) + { + toggleCameraSpeed(uMsg == WM_KEYDOWN); + } + } + + // Camera events + return m_camera.HandleMessages(hWnd, uMsg, wParam, lParam); +} + +void Renderer::Animate(double fElapsedTimeSeconds) +{ + PROFILER_SCOPED_FUNCTION(); + + m_camera.FrameMove((float)fElapsedTimeSeconds); +} + +void Renderer::renderDepthOnly(DirectX::XMMATRIX* viewProjectionSubstitute) +{ + // Fill Camera constant buffer + if (viewProjectionSubstitute) + { + D3D11_MAPPED_SUBRESOURCE mappedResource; + m_context->Map(m_cameraCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + CBCamera* cameraBuffer = (CBCamera*)mappedResource.pData; + cameraBuffer->viewProjection = *viewProjectionSubstitute; + m_context->Unmap(m_cameraCB, 0); + } + + // set constants buffers + setAllConstantBuffers(m_context); + + // render + for (auto it = m_renderables.begin(); it != m_renderables.end(); it++) + { + if (!(*it)->isTransparent() && !(*it)->isHidden()) + (*it)->renderDepthStencilOnly(*this); + } +} + +void Renderer::render(const PxRenderBuffer* renderBuffer) +{ + // points + uint32_t pointsCount = renderBuffer->getNbPoints(); + if (pointsCount > 0) + { + RenderDebugVertex* verts = new RenderDebugVertex[pointsCount]; + const PxDebugPoint* points = renderBuffer->getPoints(); + for (uint32_t i = 0; i < pointsCount; i++) + { + verts[i].mPos = points[i].pos; + verts[i].mColor = points[i].color; + } + + renderDebugPrimitive(verts, pointsCount, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); + delete[] verts; + } + + // lines + uint32_t linesCount = renderBuffer->getNbLines(); + if (linesCount > 0) + { + RenderDebugVertex* verts = new RenderDebugVertex[linesCount * 2]; + const PxDebugLine* lines = renderBuffer->getLines(); + for (uint32_t i = 0; i < linesCount; i++) + { + verts[i * 2].mPos = lines[i].pos0; + verts[i * 2].mColor = lines[i].color0; + verts[i * 2 + 1].mPos = lines[i].pos1; + verts[i * 2 + 1].mColor = lines[i].color1; + } + + renderDebugPrimitive(verts, linesCount * 2, D3D11_PRIMITIVE_TOPOLOGY_LINELIST); + delete[] verts; + } + + // triangles + uint32_t trianglesCount = renderBuffer->getNbTriangles(); + if (trianglesCount > 0) + { + RenderDebugVertex* verts = new RenderDebugVertex[trianglesCount * 3]; + const PxDebugTriangle* triangles = renderBuffer->getTriangles(); + for (uint32_t i = 0; i < trianglesCount; i++) + { + verts[i * 3].mPos = triangles[i].pos0; + verts[i * 3].mColor = triangles[i].color0; + verts[i * 3 + 1].mPos = triangles[i].pos1; + verts[i * 3 + 1].mColor = triangles[i].color1; + verts[i * 3 + 2].mPos = triangles[i].pos2; + verts[i * 3 + 2].mColor = triangles[i].color2; + } + + renderDebugPrimitive(verts, trianglesCount * 3, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + delete[] verts; + } + + // texts? + // .... +} + +void Renderer::renderDebugPrimitive(const Renderer::RenderDebugVertex *vertices, uint32_t verticesCount, D3D11_PRIMITIVE_TOPOLOGY topology) +{ + m_context->IASetPrimitiveTopology(topology); + + m_debugPrimitiveRenderMaterialInstance->bind(*m_context, 0); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + m_context->Map(m_objectCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + CBObject* objectBuffer = (CBObject*)mappedResource.pData; + + objectBuffer->world = PxMat44ToXMMATRIX(PxMat44(PxIdentity)); + + m_context->Unmap(m_objectCB, 0); + + if (m_debugPrimitiveVBVerticesCount < verticesCount) + { + m_debugPrimitiveVBVerticesCount = verticesCount; + SAFE_RELEASE(m_debugPrimitiveVB); + + D3D11_BUFFER_DESC bufferDesc; + + memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.ByteWidth = sizeof(Renderer::RenderDebugVertex) * m_debugPrimitiveVBVerticesCount; + bufferDesc.CPUAccessFlags = 0; + bufferDesc.MiscFlags = 0; + bufferDesc.Usage = D3D11_USAGE_DEFAULT; + + V(m_device->CreateBuffer(&bufferDesc, NULL, &m_debugPrimitiveVB)); + } + + CD3D11_BOX box(0, 0, 0, (LONG)(sizeof(Renderer::RenderDebugVertex) * verticesCount), 1, 1); + m_context->UpdateSubresource(m_debugPrimitiveVB, 0, &box, vertices, 0, 0); + + ID3D11Buffer* pBuffers[1] = { m_debugPrimitiveVB }; + UINT strides[1] = { sizeof(RenderDebugVertex) }; + UINT offsets[1] = { 0 }; + m_context->IASetVertexBuffers(0, 1, pBuffers, strides, offsets); + + m_context->Draw(verticesCount, 0); +} + +IRenderMesh* Renderer::getPrimitiveRenderMesh(PrimitiveRenderMeshType::Enum type) +{ + if (m_primitiveRenderMeshes[type] == NULL) + { + switch (type) + { + case PrimitiveRenderMeshType::Box: + m_primitiveRenderMeshes[type] = new BoxRenderMesh(); + break; + case PrimitiveRenderMeshType::Plane: + m_primitiveRenderMeshes[type] = new PlaneRenderMesh(); + break; + case PrimitiveRenderMeshType::Sphere: + m_primitiveRenderMeshes[type] = new SphereRenderMesh(); + break; + default: + PX_ALWAYS_ASSERT_MESSAGE("Unsupported PxGeometryType"); + return NULL; + } + } + + return m_primitiveRenderMeshes[type]; +} + + +Renderable* Renderer::createRenderable(IRenderMesh& mesh, RenderMaterial& material) +{ + Renderable* renderable = new Renderable(mesh, material); + m_renderables.emplace(renderable); + return renderable; +} + +void Renderer::removeRenderable(Renderable* r) +{ + m_renderables.erase(m_renderables.find(r)); + delete r; +} + +void Renderer::toggleCameraSpeed(bool overspeed) +{ + m_camera.SetScalers(0.002f, overspeed ? 150.f : 25.f); +} + +void Renderer::reloadShaders() +{ + // iterate Renderables materials and call reload() + std::set<RenderMaterial*> materials; + for (auto it = m_renderables.begin(); it != m_renderables.end(); it++) + { + materials.emplace(&((*it)->getMaterial())); + } + for (std::set<RenderMaterial*>::iterator it = materials.begin(); it != materials.end(); it++) + { + (*it)->reload(); + } +} + +void Renderer::drawUI() +{ + // Lighting + if (ImGui::TreeNode("Lighting")) + { + ImGui::ColorEdit3("Ambient Color", &(m_worldCBData.ambientColor.x)); + ImGui::ColorEdit3("Point Light Color", &(m_worldCBData.pointLightColor.x)); + ImGui::DragFloat3("Point Light Pos", &(m_worldCBData.pointLightPos.x)); + ImGui::ColorEdit3("Dir Light Color", &(m_worldCBData.dirLightColor.x)); + ImGui_DragFloat3Dir("Dir Light Dir", &(m_worldCBData.dirLightDir.x)); + ImGui::DragFloat("Specular Power", &(m_worldCBData.specularPower), 1.0f, 1.0f, 500.0f); + ImGui::DragFloat("Specular Intensity", &(m_worldCBData.specularIntensity), 0.01f, 0.0f, 2.0f); + + ImGui::TreePop(); + } + + // Shadow + if (ImGui::TreeNode("Shadow")) + { + ImGui::Checkbox("Shadows Enabled", &m_shadowEnabled); + if (m_shadowEnabled) + { + m_shadow.drawUI(); + } + + ImGui::TreePop(); + } + + // HBAO+ + if (ImGui::TreeNode("HBAO+")) + { + ImGui::Checkbox("HBAO Enabled", &(m_HBAOEnabled)); + if (m_HBAOEnabled) + { + m_HBAO.drawUI(); + } + + ImGui::TreePop(); + } +}
\ No newline at end of file diff --git a/NvBlast/samples/SampleBase/renderer/Renderer.h b/NvBlast/samples/SampleBase/renderer/Renderer.h new file mode 100644 index 0000000..56e6e4a --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/Renderer.h @@ -0,0 +1,248 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#ifndef RENDERER_H +#define RENDERER_H + +#include "RenderMaterial.h" +#include <DirectXMath.h> +#include "XInput.h" +#include "DXUTMisc.h" +#include "DXUTCamera.h" +#include "SampleManager.h" +#include "Utils.h" +#include "ResourceManager.h" +#include "PrimitiveRenderMesh.h" +#include "RendererShadow.h" +#include "RendererHBAO.h" +#include <unordered_set> + +class CFirstPersonCamera; +class PhysXPrimitive; +class RenderDebugImpl; + +namespace physx +{ +class PxRenderBuffer; +} + + +/** +3D World Renderer +- use createRenderable() to add objects to render. +- use queueRenderBuffer() every frame to render debug primitives. +- contains ResourceManager to search for file and load resources. +- contains RendererShadow and RendererHBAO, use them through getters to control shadows. +*/ +class Renderer : public ISampleController +{ + friend class Renderable; + + public: + //////// ctor //////// + + Renderer(); + ~Renderer(); + + + //////// public API //////// + + void reloadShaders(); + + bool getWireframeMode() + { + return m_wireframeMode; + } + + void setWireframeMode(bool enabled) + { + if(m_wireframeMode != enabled) + { + m_wireframeMode = enabled; + initializeDefaultRSState(); + } + } + + IRenderMesh* getPrimitiveRenderMesh(PrimitiveRenderMeshType::Enum type); + + Renderable* createRenderable(IRenderMesh& mesh, RenderMaterial& material); + void removeRenderable(Renderable* r); + + void drawUI(); + + + //////// public getters //////// + + float getScreenWidth() const + { + return m_screenWidth; + } + + float getScreenHeight() const + { + return m_screenHeight; + } + + void queueRenderBuffer(const PxRenderBuffer* buffer) + { + m_queuedRenderBuffers.push_back(buffer); + } + + ResourceManager& getResourceManager() + { + return m_resourceManager; + } + + uint32_t getVisibleOpaqueRenderablesCount() + { + return m_visibleOpaqueRenderablesCount; + } + + uint32_t getVisibleTransparentRenderablesCount() + { + return m_visibleTransparentRenderablesCount; + } + + CFirstPersonCamera& getCamera() + { + return m_camera; + } + + + //////// public 'internal' methods //////// + + // for internal usage (used by RenderShadows) + void renderDepthOnly(DirectX::XMMATRIX* viewProjectionSubstitute); + + protected: + + //////// controller callbacks //////// + + virtual HRESULT DeviceCreated(ID3D11Device* pDevice); + virtual void DeviceDestroyed(); + virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + virtual void Animate(double fElapsedTimeSeconds); + virtual void onInitialize(); + virtual void onTerminate(); + virtual void BackBufferResized(ID3D11Device* pDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc); + virtual void Render(ID3D11Device* /*device*/, ID3D11DeviceContext* ctx, ID3D11RenderTargetView* pRTV, + ID3D11DepthStencilView* pDSV); + + private: + + //////// internal methods //////// + + struct RenderDebugVertex + { + PxVec3 mPos; + uint32_t mColor; + }; + + void render(const PxRenderBuffer* renderBuffer); + void render(Renderable* renderable); + void renderDebugPrimitive(const RenderDebugVertex *vertices, uint32_t verticesCount, D3D11_PRIMITIVE_TOPOLOGY topology); + void initializeDefaultRSState(); + void setAllConstantBuffers(ID3D11DeviceContext* ctx); + void toggleCameraSpeed(bool overspeed); + + + //////// constant buffers //////// + + struct CBCamera + { + DirectX::XMMATRIX viewProjection; + DirectX::XMMATRIX projectionInv; + DirectX::XMFLOAT3 viewPos; + float unusedPad; + }; + struct CBWorld + { + DirectX::XMFLOAT3 ambientColor; + float unusedPad1; + DirectX::XMFLOAT3 pointLightPos; + float unusedPad2; + DirectX::XMFLOAT3 pointLightColor; + float unusedPad3; + DirectX::XMFLOAT3 dirLightDir; + float specularPower; + DirectX::XMFLOAT3 dirLightColor; + float specularIntensity; // TODO: actually it's per object property + }; + struct CBObject + { + DirectX::XMMATRIX world; + DirectX::XMFLOAT4 color; + }; + + + //////// internal data //////// + + // camera + CFirstPersonCamera m_camera; + float m_screenWidth; + float m_screenHeight; + + // resources + ResourceManager m_resourceManager; + + // additional render modules(libs) + RendererShadow m_shadow; + bool m_shadowEnabled; + RendererHBAO m_HBAO; + bool m_HBAOEnabled; + + // DX11 common + ID3D11Device* m_device; + ID3D11DeviceContext* m_context; + D3D11_VIEWPORT m_viewport; + + // DX11 states + ID3D11RasterizerState* m_RSState; + ID3D11DepthStencilState* m_opaqueRenderDSState; + ID3D11DepthStencilState* m_transparencyRenderDSState; + + // DX11 samplers + ID3D11SamplerState* m_pointSampler; + ID3D11SamplerState* m_linearSampler; + + // Depth Buffer + ID3D11Texture2D* m_DSTexture; + ID3D11DepthStencilView* m_DSView; + ID3D11ShaderResourceView* m_DSTextureSRV; + + // Constant Buffers + ID3D11Buffer* m_cameraCB; + ID3D11Buffer* m_worldCB; + CBWorld m_worldCBData; + ID3D11Buffer* m_objectCB; + + // toggles (options) + bool m_wireframeMode; + + // renderables + std::unordered_set<Renderable*> m_renderables; + + // primitive meshes cache + IRenderMesh* m_primitiveRenderMeshes[PrimitiveRenderMeshType::Count]; + + // stats + uint32_t m_visibleOpaqueRenderablesCount; + uint32_t m_visibleTransparentRenderablesCount; + + // Debug Render + RenderMaterial* m_debugPrimitiveRenderMaterial; + RenderMaterial::InstancePtr m_debugPrimitiveRenderMaterialInstance; + ID3D11Buffer* m_debugPrimitiveVB; + uint32_t m_debugPrimitiveVBVerticesCount; + std::vector<const PxRenderBuffer*> m_queuedRenderBuffers; +}; + + +#endif
\ No newline at end of file diff --git a/NvBlast/samples/SampleBase/renderer/RendererHBAO.cpp b/NvBlast/samples/SampleBase/renderer/RendererHBAO.cpp new file mode 100644 index 0000000..5e20a49 --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/RendererHBAO.cpp @@ -0,0 +1,81 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + + +#include "RendererHBAO.h" +#include "Renderer.h" +#include "imgui.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Renderer HBAO (wrapper for hbao+) +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +RendererHBAO::RendererHBAO() +{ + m_SSAOContext = NULL; + + // default parameters + m_SSAOParameters.Radius = 2.0f; +} + + +RendererHBAO::~RendererHBAO() +{ + releaseResources(); +} + + +void RendererHBAO::createResources(ID3D11Device *pd3dDevice) +{ + GFSDK_SSAO_Status status; + status = GFSDK_SSAO_CreateContext_D3D11(pd3dDevice, &m_SSAOContext, nullptr); + assert(status == GFSDK_SSAO_OK); +} + + +void RendererHBAO::releaseResources() +{ + if (m_SSAOContext != NULL) + { + m_SSAOContext->Release(); + } +} + + +void RendererHBAO::renderAO(ID3D11DeviceContext *pd3dDeviceContext, ID3D11RenderTargetView* pRTV, ID3D11ShaderResourceView* pDepthSRV, DirectX::XMMATRIX& projMatrix) +{ + GFSDK_SSAO_InputData_D3D11 InputData; + InputData.DepthData.pFullResDepthTextureSRV = pDepthSRV; + InputData.DepthData.DepthTextureType = GFSDK_SSAO_HARDWARE_DEPTHS; + InputData.DepthData.MetersToViewSpaceUnits = 1.0f; + InputData.DepthData.ProjectionMatrix.Data = GFSDK_SSAO_Float4x4(reinterpret_cast<const GFSDK_SSAO_FLOAT*>(&(projMatrix.r[0]))); + InputData.DepthData.ProjectionMatrix.Layout = GFSDK_SSAO_ROW_MAJOR_ORDER; + + GFSDK_SSAO_Output_D3D11 Output; + Output.pRenderTargetView = pRTV;// m_pSceneRTs->ColorRTV; + Output.Blend.Mode = GFSDK_SSAO_MULTIPLY_RGB; + + m_SSAOContext->RenderAO(pd3dDeviceContext, InputData, m_SSAOParameters, Output); +} + + +void RendererHBAO::drawUI() +{ + ImGui::DragFloat("Radius", &(m_SSAOParameters.Radius), 0.05f, 0.0f, 100.0f); + ImGui::DragFloat("Bias", &(m_SSAOParameters.Bias), 0.01f, 0.0f, 0.5f); + ImGui::DragFloat("NearAO", &(m_SSAOParameters.NearAO), 0.01f, 1.0f, 4.0f); + ImGui::DragFloat("FarAO", &(m_SSAOParameters.FarAO), 0.01, 1.0f, 4.0f); + ImGui::DragFloat("PowerExponent", &(m_SSAOParameters.PowerExponent), 0.01f, 1.0f, 8.0f); + ImGui::Checkbox("ForegroundAO Enabled", (bool*)&(m_SSAOParameters.ForegroundAO.Enable)); + ImGui::DragFloat("ForegroundAO ViewDepth", &(m_SSAOParameters.ForegroundAO.ForegroundViewDepth), 0.01f, 0.0f, 100.0f); + ImGui::Checkbox("BackgroundAO Enabled", (bool*)&(m_SSAOParameters.BackgroundAO.Enable)); + ImGui::DragFloat("BackgroundAO ViewDepth", &(m_SSAOParameters.BackgroundAO.BackgroundViewDepth), 0.01f, 0.0f, 100.0f); +}
\ No newline at end of file diff --git a/NvBlast/samples/SampleBase/renderer/RendererHBAO.h b/NvBlast/samples/SampleBase/renderer/RendererHBAO.h new file mode 100644 index 0000000..2478628 --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/RendererHBAO.h @@ -0,0 +1,40 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#ifndef RENDERER_HBAO_H +#define RENDERER_HBAO_H + +#include <DirectXMath.h> +#include "GFSDK_SSAO.h" + + +class Renderer; + +class RendererHBAO +{ +public: + RendererHBAO(); + ~RendererHBAO(); + + void createResources(ID3D11Device *pd3dDevice); + void renderAO(ID3D11DeviceContext *pd3dDeviceContext, ID3D11RenderTargetView* pRTV, ID3D11ShaderResourceView* pDepthSRV, DirectX::XMMATRIX& projMatrix); + + void drawUI(); + +private: + void releaseResources(); + + GFSDK_SSAO_Parameters m_SSAOParameters; + + GFSDK_SSAO_Context_D3D11* m_SSAOContext; +}; + + +#endif
\ No newline at end of file diff --git a/NvBlast/samples/SampleBase/renderer/RendererShadow.cpp b/NvBlast/samples/SampleBase/renderer/RendererShadow.cpp new file mode 100644 index 0000000..28a79e5 --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/RendererShadow.cpp @@ -0,0 +1,417 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + + +#include "RendererShadow.h" + +#include "XInput.h" +#include "DXUTMisc.h" +#include "DXUTCamera.h" +#include "Renderer.h" +#include "UIHelpers.h" + +#define CASCADES 1 + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Renderer Shadows (wrapper for shadow_lib) +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +const float DEFAULT_LIGHT_SIZE = 3.0f; +const DirectX::XMFLOAT3 DEFAULT_LIGHT_POS(-25, 25, 25); +const DirectX::XMFLOAT3 DEFAULT_LIGHT_LOOK_AT(0, 0, 0); +const DirectX::XMFLOAT3 DEFAULT_SHADOW_COLOR(0.25f, 0.25f, 0.25f); + +RendererShadow::RendererShadow() +{ + m_shadowLibContext = NULL; + + m_PCSSEnabled = false; + m_lightSize = DEFAULT_LIGHT_SIZE; + m_lightPos = DEFAULT_LIGHT_POS; + m_lightLookAt = DEFAULT_LIGHT_LOOK_AT; + m_shadowColor = DEFAULT_SHADOW_COLOR; + + m_worldSpaceBBox0.x = m_worldSpaceBBox0.y = m_worldSpaceBBox0.z = -100; + m_worldSpaceBBox1.x = m_worldSpaceBBox1.y = m_worldSpaceBBox1.z = 100; + + // Penumbra params + m_PCSSParams.fMaxThreshold = 80.0f; + m_PCSSParams.fMaxClamp = 40.0f; + m_PCSSParams.fMinSizePercent = 3.0f; + m_PCSSParams.fMinWeightExponent = 5.0f; + m_PCSSParams.fMinWeightThresholdPercent = 20.0f; + + m_softShadowTestScale = 0.002f; + + memset(&m_shadowBufferSRV, 0, sizeof(m_shadowBufferSRV)); + + m_shadowMapHandle = NULL; + m_shadowBufferHandle = NULL; +} + + +RendererShadow::~RendererShadow() +{ + ReleaseResources(); +} + + +void RendererShadow::createResources(ID3D11Device *pd3dDevice, ID3D11DeviceContext* context, CFirstPersonCamera* camera) +{ + m_camera = camera; + +#if !CASCADES + uint32_t shadowMapScale = 5; + uint32_t shadowMapWidth = 1024; + uint32_t shadowMapHeight = 1024; + + // SM Desc + m_SMDesc.eViewType = GFSDK_ShadowLib_ViewType_Single; + m_SMDesc.eMapType = GFSDK_ShadowLib_MapType_Texture; +#else + + uint32_t shadowMapScale = 5; + uint32_t shadowMapWidth = 1024; + uint32_t shadowMapHeight = 1024; + + // SM Desc + m_SMDesc.eViewType = GFSDK_ShadowLib_ViewType_Cascades_2; + m_SMDesc.eMapType = GFSDK_ShadowLib_MapType_TextureArray; +#endif + + m_SMDesc.uResolutionWidth = shadowMapWidth * shadowMapScale; + m_SMDesc.uResolutionHeight = shadowMapHeight * shadowMapScale; + m_SMDesc.uArraySize = m_SMDesc.eViewType; + + for (int j = 0; j < GFSDK_ShadowLib_ViewType_Cascades_4; j++) + { + m_SMDesc.ViewLocation[j].uMapID = j; + m_SMDesc.ViewLocation[j].v2Origin.x = 0; + m_SMDesc.ViewLocation[j].v2Origin.y = 0; + m_SMDesc.ViewLocation[j].v2Dimension.x = shadowMapWidth * shadowMapScale; + m_SMDesc.ViewLocation[j].v2Dimension.y = shadowMapHeight * shadowMapScale; + } + + + // SM Render Params + m_SMRenderParams.iDepthBias = 1000; + m_SMRenderParams.fSlopeScaledDepthBias = 8; + + // SB Render Params + m_SBRenderParams.eTechniqueType = GFSDK_ShadowLib_TechniqueType_PCSS; + m_SBRenderParams.eQualityType = GFSDK_ShadowLib_QualityType_High; + + // DLL version + GFSDK_ShadowLib_Version DLLVersion; + GFSDK_ShadowLib_Status retCode = GFSDK_ShadowLib_GetDLLVersion(&DLLVersion); + + // Header version + GFSDK_ShadowLib_Version headerVersion; + headerVersion.uMajor = GFSDK_SHADOWLIB_MAJOR_VERSION; + headerVersion.uMinor = GFSDK_SHADOWLIB_MINOR_VERSION; + + // Do they match? + if (DLLVersion.uMajor == headerVersion.uMajor && DLLVersion.uMinor == headerVersion.uMinor) + { + GFSDK_ShadowLib_DeviceContext deviceAndContext; + deviceAndContext.pD3DDevice = pd3dDevice; + deviceAndContext.pDeviceContext = context; + + retCode = GFSDK_ShadowLib_Create(&headerVersion, &m_shadowLibContext, &deviceAndContext, NULL); + + if (retCode != GFSDK_ShadowLib_Status_Ok) assert(false); + } + else + { + assert(false); + } +} + + +void RendererShadow::ReleaseResources() +{ + SAFE_RELEASE(m_downsampledShadowMap.pTexture); + SAFE_RELEASE(m_downsampledShadowMap.pSRV); + SAFE_RELEASE(m_downsampledShadowMap.pRTV); + + if (m_shadowLibContext != NULL) + { + m_shadowLibContext->Destroy(); + m_shadowLibContext = NULL; + } +} + + +void RendererShadow::setScreenResolution(float FovyRad, UINT Width, UINT Height, UINT uSampleCount, ID3D11DepthStencilView* pReadOnlyDSV) +{ + changeShadowSettings(Width, Height, uSampleCount, pReadOnlyDSV); +} + + +void RendererShadow::changeShadowSettings(UINT Width, UINT Height, UINT uSampleCount, ID3D11DepthStencilView* pReadOnlyDSV) +{ + m_SBDesc.uResolutionWidth = Width; + m_SBDesc.uResolutionHeight = Height; + m_SBDesc.uSampleCount = uSampleCount; + m_SBDesc.ReadOnlyDSV.pDSV = pReadOnlyDSV; + + reloadBuffers(); +} + +void RendererShadow::reloadBuffers() +{ + { + m_shadowLibContext->RemoveMap(&m_shadowMapHandle); + + if (m_SMDesc.eMapType == GFSDK_ShadowLib_MapType_Texture && + m_SMDesc.eViewType == GFSDK_ShadowLib_ViewType_Single && + m_SBRenderParams.eTechniqueType == GFSDK_ShadowLib_TechniqueType_PCSS) + { + m_SMDesc.bDownsample = true; + } + + m_shadowLibContext->AddMap(&m_SMDesc, &m_shadowMapHandle); + } + + if (m_SMDesc.eMapType == GFSDK_ShadowLib_MapType_Texture && m_SMDesc.eViewType == GFSDK_ShadowLib_ViewType_Single) + { + m_downsampledShadowMap.uWidth = m_SMDesc.uResolutionWidth >> 1; + m_downsampledShadowMap.uHeight = m_SMDesc.uResolutionHeight >> 1; + m_downsampledShadowMap.uSampleCount = 1; + m_downsampledShadowMap.Format = DXGI_FORMAT_R32_FLOAT; + SAFE_RELEASE(m_downsampledShadowMap.pTexture); + SAFE_RELEASE(m_downsampledShadowMap.pSRV); + SAFE_RELEASE(m_downsampledShadowMap.pRTV); + m_shadowLibContext->DevModeCreateTexture2D(&m_downsampledShadowMap); + } + + m_shadowLibContext->RemoveBuffer(&m_shadowBufferHandle); + m_shadowLibContext->AddBuffer(&m_SBDesc, &m_shadowBufferHandle); +} + + + +//-------------------------------------------------------------------------------------- +// Data passed to the shadow map render function +//-------------------------------------------------------------------------------------- +struct ShadowMapRenderFunctionParams +{ + Renderer* renderer; +}; +static ShadowMapRenderFunctionParams s_RenderParams; + +//-------------------------------------------------------------------------------------- +// Shadow map render function +//-------------------------------------------------------------------------------------- +static void ShadowMapRenderFunction(void* pParams, gfsdk_float4x4* pViewProj) +{ + ShadowMapRenderFunctionParams* pRP = (ShadowMapRenderFunctionParams*)pParams; + + DirectX::XMMATRIX viewProjection; + memcpy(&viewProjection, &pViewProj->_11, sizeof(gfsdk_float4x4)); + + pRP->renderer->renderDepthOnly(&viewProjection); +} + +void RendererShadow::renderShadowMaps(Renderer* renderer) +{ + // select technique + GFSDK_ShadowLib_TechniqueType technique = m_SBRenderParams.eTechniqueType; + m_SBRenderParams.eTechniqueType = m_PCSSEnabled ? GFSDK_ShadowLib_TechniqueType_PCSS : GFSDK_ShadowLib_TechniqueType_PCF; + if (technique != m_SBRenderParams.eTechniqueType) + reloadBuffers(); + + + DirectX::XMMATRIX viewMatrix = m_camera->GetViewMatrix(); + DirectX::XMMATRIX projMatrix = m_camera->GetProjMatrix(); + + memcpy(&m_SMRenderParams.m4x4EyeViewMatrix, &viewMatrix.r[0], sizeof(gfsdk_float4x4)); + memcpy(&m_SMRenderParams.m4x4EyeProjectionMatrix, &projMatrix.r[0], sizeof(gfsdk_float4x4)); + + // TODO: (better world space bbox needed) + m_SMRenderParams.v3WorldSpaceBBox[0] = m_worldSpaceBBox0; + m_SMRenderParams.v3WorldSpaceBBox[1] = m_worldSpaceBBox1; + + m_SMRenderParams.LightDesc.eLightType = GFSDK_ShadowLib_LightType_Directional; + memcpy(&m_SMRenderParams.LightDesc.v3LightPos, &m_lightPos.x, sizeof(gfsdk_float3)); + memcpy(&m_SMRenderParams.LightDesc.v3LightLookAt, &m_lightLookAt.x, sizeof(gfsdk_float3)); + m_SMRenderParams.LightDesc.fLightSize = m_lightSize; + m_SMRenderParams.LightDesc.bLightFalloff = false; + + // Scene specific setup for the shadow map phase that follows + s_RenderParams.renderer = renderer; + m_SMRenderParams.fnpDrawFunction = GFSDK_ShadowLib_FunctionPointer(ShadowMapRenderFunction); + m_SMRenderParams.pDrawFunctionParams = &s_RenderParams; + + // render shadow map + m_shadowLibContext->RenderMap(m_shadowMapHandle, &m_SMRenderParams); +} + + +void RendererShadow::renderShadowBuffer(ID3D11ShaderResourceView* pDepthStencilSRV, ID3D11ShaderResourceView* pResolvedDepthStencilSRV) +{ + if (m_SBRenderParams.eTechniqueType == GFSDK_ShadowLib_TechniqueType_PCSS && + m_SMDesc.eMapType == GFSDK_ShadowLib_MapType_Texture && + m_SMDesc.eViewType == GFSDK_ShadowLib_ViewType_Single) + { + m_tempResources.pDownsampledShadowMap = &m_downsampledShadowMap; + m_shadowLibContext->SetTempResources(&m_tempResources); + } + + m_SBRenderParams.PCSSPenumbraParams = m_PCSSParams; + m_SBRenderParams.fSoftShadowTestScale = m_softShadowTestScale; + + m_shadowLibContext->ClearBuffer(m_shadowBufferHandle); + + m_SBRenderParams.DepthBufferDesc.DepthStencilSRV.pSRV = pDepthStencilSRV; + + m_shadowLibContext->RenderBuffer(m_shadowMapHandle, m_shadowBufferHandle, &m_SBRenderParams); + + m_shadowLibContext->FinalizeBuffer(m_shadowBufferHandle, &m_shadowBufferSRV); +} + + +void RendererShadow::modulateShadowBuffer(ID3D11RenderTargetView* pOutputRTV) +{ + GFSDK_ShadowLib_RenderTargetView ColorRTV; + ColorRTV.pRTV = pOutputRTV; + + gfsdk_float3 v3ShadowColor = { m_shadowColor.x, m_shadowColor.y, m_shadowColor.z }; + m_shadowLibContext->ModulateBuffer(m_shadowBufferHandle, &ColorRTV, v3ShadowColor, GFSDK_ShadowLib_ModulateBufferMask_RGB); +} + + +void RendererShadow::displayShadowMaps(ID3D11RenderTargetView* pOutputRTV, UINT Width, UINT Height) +{ + GFSDK_ShadowLib_RenderTargetView ColorRTV; + ColorRTV.pRTV = pOutputRTV; + + float fMapResW = (float)m_SMDesc.uResolutionWidth; + float fMapResH = (float)m_SMDesc.uResolutionHeight; + + float fWidthScale = Width / ((float)m_SMDesc.uArraySize * fMapResW); + fWidthScale = (fWidthScale > 1.0f) ? (1.0f) : (fWidthScale); + + float fOneFifth = (float)Height / (5.0f); + float fHeightScale = fOneFifth / fMapResH; + fHeightScale = (fHeightScale > 1.0f) ? (1.0f) : (fHeightScale); + + float fScale = (fHeightScale < fWidthScale) ? (fHeightScale) : (fWidthScale); + + fMapResW = floorf(fMapResW * fScale); + fMapResH = floorf(fMapResH * fScale); + + for (unsigned int j = 0; j < (unsigned int)m_SMDesc.uArraySize; j++) + { + m_shadowLibContext->DevModeDisplayMap(m_shadowBufferHandle, + &ColorRTV, + m_shadowMapHandle, + j, + j * (unsigned int)fMapResW + j, + Height - (unsigned int)fMapResH, + fScale); + } +} + + +void RendererShadow::displayMapFrustums(ID3D11RenderTargetView* pOutputRTV, ID3D11DepthStencilView* pDSV) +{ + gfsdk_float3 v3Color; + v3Color.x = 1.0f; + v3Color.y = 0.0f; + v3Color.z = 0.0f; + + GFSDK_ShadowLib_RenderTargetView ColorRTV; + ColorRTV.pRTV = pOutputRTV; + + GFSDK_ShadowLib_DepthStencilView DSV; + DSV.pDSV = pDSV; + + unsigned int NumViews; + NumViews = m_SMDesc.eViewType; + + for (unsigned int j = 0; j < NumViews; j++) + { + switch (j) + { + case 0: + v3Color.x = 1.0f; + v3Color.y = 0.0f; + v3Color.z = 0.0f; + break; + case 1: + v3Color.x = 0.0f; + v3Color.y = 1.0f; + v3Color.z = 0.0f; + break; + case 2: + v3Color.x = 0.0f; + v3Color.y = 0.0f; + v3Color.z = 1.0f; + break; + case 3: + v3Color.x = 1.0f; + v3Color.y = 1.0f; + v3Color.z = 0.0f; + break; + } + + m_shadowLibContext->DevModeDisplayMapFrustum(m_shadowBufferHandle, + &ColorRTV, + &DSV, + m_shadowMapHandle, + j, + v3Color); + } +} + + +void RendererShadow::displayShadowBuffer(ID3D11RenderTargetView* pOutputRTV) +{ + gfsdk_float2 v2Scale; + v2Scale.x = 1.0f; + v2Scale.y = 1.0f; + + GFSDK_ShadowLib_RenderTargetView ColorRTV; + ColorRTV.pRTV = pOutputRTV; + + m_shadowLibContext->DevModeDisplayBuffer(m_shadowBufferHandle, + &ColorRTV, + v2Scale, + NULL); +} + + +void RendererShadow::toggleDisplayCascades(bool bToggle) +{ + m_shadowLibContext->DevModeToggleDebugCascadeShader(m_shadowBufferHandle, + bToggle); +} + + +void RendererShadow::drawUI() +{ + ImGui::Checkbox("PCSS", &m_PCSSEnabled); + ImGui::ColorEdit3("Shadow Color", &(m_shadowColor.x)); + ImGui::DragFloat("Light Size", &m_lightSize, 0.05f, 0.0f, 100.0f); + ImGui::DragFloat3("Light Position", &(m_lightPos.x)); + ImGui_DragFloat3Dir("Light LookAt", &(m_lightLookAt.x)); + ImGui::DragFloat("SoftShadowTestScale", &(m_softShadowTestScale), 0.0001f, 0.0f, 10.0f); + if (m_PCSSEnabled) + { + ImGui::DragFloat("PCSS: fMaxClamp", &(m_PCSSParams.fMaxClamp), 0.001f, 0.0f, 100.0f); + ImGui::DragFloat("PCSS: fMaxThreshold", &(m_PCSSParams.fMaxThreshold), 0.001f, 0.0f, 100.0f); + ImGui::DragFloat("PCSS: fMinSizePercent", &(m_PCSSParams.fMinSizePercent), 0.001f, 0.0f, 100.0f); + ImGui::DragFloat("PCSS: fMinWeightExponent", &(m_PCSSParams.fMinWeightExponent), 0.001f, 0.0f, 100.0f); + ImGui::DragFloat("PCSS: fMinWeightThresholdPercent", &(m_PCSSParams.fMinWeightThresholdPercent), 0.001f, 0.0f, 100.0f); + ImGui::DragFloat("PCSS: fBlockerSearchDitherPercent", &(m_PCSSParams.fBlockerSearchDitherPercent), 0.001f, 0.0f, 100.0f); + ImGui::DragFloat("PCSS: fFilterDitherPercent", &(m_PCSSParams.fFilterDitherPercent), 0.001f, 0.0f, 100.0f); + } +}
\ No newline at end of file diff --git a/NvBlast/samples/SampleBase/renderer/RendererShadow.h b/NvBlast/samples/SampleBase/renderer/RendererShadow.h new file mode 100644 index 0000000..cc81c67 --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/RendererShadow.h @@ -0,0 +1,82 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#ifndef RENDERER_SHADOW_H +#define RENDERER_SHADOW_H + +#include <DirectXMath.h> +#include "Utils.h" +#include "gfsdk_shadowlib.h" + +#include <string> + + +class CFirstPersonCamera; +class Renderer; + +class RendererShadow +{ +public: + RendererShadow(); + ~RendererShadow(); + + void createResources(ID3D11Device *pd3dDevice, ID3D11DeviceContext* context, CFirstPersonCamera* camera); + + void setScreenResolution(float FovyRad, UINT Width, UINT Height, UINT uSampleCount, ID3D11DepthStencilView* pReadOnlyDSV); + void changeShadowSettings(UINT Width, UINT Height, UINT uSampleCount, ID3D11DepthStencilView* pReadOnlyDSV); + void renderShadowMaps(Renderer* renderer); + void renderShadowBuffer(ID3D11ShaderResourceView* pDepthStencilSRV, ID3D11ShaderResourceView* pResolvedDepthStencilSRV); + void modulateShadowBuffer(ID3D11RenderTargetView* pOutputRTV); + void displayShadowMaps(ID3D11RenderTargetView* pOutputRTV, UINT Width, UINT Height); + void displayMapFrustums(ID3D11RenderTargetView* pOutputRTV, ID3D11DepthStencilView* pDSV); + void displayShadowBuffer(ID3D11RenderTargetView* pOutputRTV); + void toggleDisplayCascades(bool bToggle); + + + void drawUI(); + +private: + void reloadBuffers(); + void ReleaseResources(); + + + GFSDK_ShadowLib_Context* m_shadowLibContext; + + GFSDK_ShadowLib_ShaderResourceView m_shadowBufferSRV; + + GFSDK_ShadowLib_Map* m_shadowMapHandle; + GFSDK_ShadowLib_MapDesc m_SMDesc; + GFSDK_ShadowLib_BufferDesc m_SBDesc; + GFSDK_ShadowLib_MapRenderParams m_SMRenderParams; + + GFSDK_ShadowLib_Buffer* m_shadowBufferHandle; + GFSDK_ShadowLib_BufferRenderParams m_SBRenderParams; + + GFSDK_ShadowLib_TempResources m_tempResources; + GFSDK_ShadowLib_Texture2D m_downsampledShadowMap; + + CFirstPersonCamera* m_camera; + + // params + bool m_PCSSEnabled; + float m_lightSize; + DirectX::XMFLOAT3 m_lightPos; + DirectX::XMFLOAT3 m_lightLookAt; + DirectX::XMFLOAT3 m_shadowColor; + GFSDK_ShadowLib_PCSSPenumbraParams m_PCSSParams; + float m_softShadowTestScale; + + gfsdk_float3 m_worldSpaceBBox0; + gfsdk_float3 m_worldSpaceBBox1; + +}; + + +#endif
\ No newline at end of file diff --git a/NvBlast/samples/SampleBase/renderer/ResourceManager.cpp b/NvBlast/samples/SampleBase/renderer/ResourceManager.cpp new file mode 100644 index 0000000..f8a4b7b --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/ResourceManager.cpp @@ -0,0 +1,212 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#include "ResourceManager.h" +#include "PxAssert.h" +#include "PsString.h" +#include "Utils.h" + +#include <windows.h> + + +using namespace physx; + +#define PATH_MAX_LEN 512 + + +ResourceManager::ResourceManager() +{ + // search for root folder by default + addSearchDir("."); +} + +const ShaderFileResource* ResourceManager::requestShaderFile(const char* name) +{ + const Resource* resource = requestResource(eSHADER_FILE, name); + return resource != nullptr ? static_cast<const ShaderFileResource*>(resource) : nullptr; +} + +const TextureResource* ResourceManager::requestTexture(const char* name) +{ + const Resource* resource = requestResource(eTEXTURE, name); + return resource != nullptr ? static_cast<const TextureResource*>(resource) : nullptr; +} + +const Resource* ResourceManager::requestResource(ResourceType type, const char* name) +{ + // search in loaded + std::pair<ResourceType, std::string> key(type, name); + auto val = m_loadedResources.find(key); + if (val != m_loadedResources.end()) + { + return val->second.get(); + } + + std::shared_ptr<Resource> resource; + if (type == eSHADER_FILE) + { + char path[PATH_MAX_LEN]; + const char* exts[] = { "hlsl" }; + if (findFile(name, std::vector<const char*>(exts, exts + sizeof(exts) / sizeof(exts[0])), path)) + { + resource = std::shared_ptr<Resource>(new ShaderFileResource(path)); + } + else + { + PX_ALWAYS_ASSERT_MESSAGE(name); + } + } + else if (type == eTEXTURE) + { + char path[PATH_MAX_LEN]; + const char* exts[] = { "dds", "tga" }; + if (findFile(name, std::vector<const char*>(exts, exts + sizeof(exts) / sizeof(exts[0])), path)) + { + std::shared_ptr<TextureResource> textureResource(new TextureResource()); + WCHAR wPath[MAX_PATH]; + MultiByteToWideChar(CP_ACP, 0, path, -1, wPath, MAX_PATH); + wPath[MAX_PATH - 1] = 0; + + const char* ext = strext(path); + if (::strcmp(ext, "dds") == 0) + { + V(DirectX::LoadFromDDSFile(wPath, DirectX::DDS_FLAGS_NONE, &textureResource->metaData, + textureResource->image)); + } + else if (::strcmp(ext, "tga") == 0) + { + V(DirectX::LoadFromTGAFile(wPath, &textureResource->metaData, + textureResource->image)); + } + else + { + PX_ALWAYS_ASSERT_MESSAGE("Unsupported texture extension"); + } + resource = textureResource; + } + } + + if (resource.get()) + { + m_loadedResources.emplace(key, resource); + return resource.get(); + } + else + { + PX_ALWAYS_ASSERT_MESSAGE(name); + return nullptr; + } +} + +bool dirExists(const char* dir) +{ + DWORD ftyp = GetFileAttributesA(dir); + if (ftyp == INVALID_FILE_ATTRIBUTES) + return false; // something is wrong with path! + + if (ftyp & FILE_ATTRIBUTE_DIRECTORY) + return true; // this is a directory! + + return false; // this is not a directory! +} + +bool ResourceManager::addSearchDir(const char* dir, bool recursive) +{ + if (dirExists(dir)) + { + m_searchDirs.push_back(SearchDir(dir, recursive)); + return true; + } + return false; +} + + +ResourceManager::~ResourceManager() +{ +} + + +bool ResourceManager::findFileInDir(std::string fileNameFull, const char* path, bool recursive, char* foundPath) +{ + WIN32_FIND_DATAA ffd; + char tmp[PATH_MAX_LEN]; + shdfnd::snprintf(tmp, sizeof(tmp), "%s\\*", path); + HANDLE hFind = FindFirstFileA(tmp, &ffd); + + if(INVALID_HANDLE_VALUE == hFind) + { + return NULL; + } + + do + { + if (0 == shdfnd::strcmp(".", ffd.cFileName) || 0 == shdfnd::strcmp("..", ffd.cFileName)) + continue; + + if(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + shdfnd::snprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName); + if(findFileInDir(fileNameFull, tmp, recursive, foundPath)) + return true; + } + else if (shdfnd::stricmp(ffd.cFileName, fileNameFull.c_str()) == 0) + { + shdfnd::snprintf(foundPath, PATH_MAX_LEN, "%s\\%s", path, ffd.cFileName); + return true; + } + } while(FindNextFileA(hFind, &ffd) != 0); + // release handle + FindClose(hFind); + return false; +} + +bool ResourceManager::findFile(std::string fileName, const std::vector<const char*>& exts, char* foundPath) +{ + std::string fileNameOnly = fileName; + size_t ind = fileNameOnly.find_last_of('/'); + if (ind > 0) + fileNameOnly = fileNameOnly.substr(ind + 1); + + for(size_t i = 0; i < m_searchDirs.size(); i++) + { + const SearchDir& searchDir = m_searchDirs[i]; + + for(size_t j = 0; j < exts.size(); j++) + { + const char* ext = exts[j]; + const uint32_t fileMaxLen = 128; + char fileNameFull[fileMaxLen] = { 0 }; + + physx::shdfnd::snprintf(fileNameFull, fileMaxLen, "%s.%s", fileNameOnly.c_str(), ext); + if(findFileInDir(fileNameFull, searchDir.path.c_str(), searchDir.recursive, foundPath)) + return true; + } + + if (findFileInDir(fileNameOnly.c_str(), searchDir.path.c_str(), searchDir.recursive, foundPath)) + return true; + } + return false; +} + +bool ResourceManager::findFile(std::string fileName, std::string& foundPath) +{ + std::vector<const char*> exts; + char path[PATH_MAX_LEN]; + if (findFile(fileName, exts, path)) + { + foundPath = path; + return true; + } + else + { + return false; + } +} + diff --git a/NvBlast/samples/SampleBase/renderer/ResourceManager.h b/NvBlast/samples/SampleBase/renderer/ResourceManager.h new file mode 100644 index 0000000..6a9b8cd --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/ResourceManager.h @@ -0,0 +1,93 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#ifndef RESOURCE_MANAGER_H +#define RESOURCE_MANAGER_H + +#include <vector> +#include <string> +#include <map> +#include <memory> +#include "DirectXTex.h" + + +struct Resource +{ +private: + Resource& operator = (const Resource&); +}; + + +struct ShaderFileResource : public Resource +{ + ShaderFileResource(const std::string& p) : path(p) {} + std::string path; +}; + + +struct TextureResource : public Resource +{ + DirectX::TexMetadata metaData; + DirectX::ScratchImage image; +}; + + +/** +ResourceManager used to look for files in provided dirs (see addSearchDir). Also it loads resources and caches them. +*/ +class ResourceManager +{ +public: + //////// ctor //////// + + ResourceManager(); + ~ResourceManager(); + + //////// public API //////// + + bool addSearchDir(const char* dir, bool recursive = true); + + const ShaderFileResource* requestShaderFile(const char* name); + + const TextureResource* requestTexture(const char* name); + + bool findFile(std::string fileName, std::string& foundPath); + + bool findFile(std::string fileName, const std::vector<const char*>& exts, char* foundPath); + + +private: + //////// internal methods //////// + + enum ResourceType + { + eSHADER_FILE, + eTEXTURE + }; + + const Resource* requestResource(ResourceType type, const char* name); + + bool findFileInDir(std::string fileNameFull, const char* path, bool recursive, char* foundPath); + + struct SearchDir + { + SearchDir(std::string path_, bool recursive_) : path(path_), recursive(recursive_) {} + + std::string path; + bool recursive; + }; + + + //////// internal data //////// + + std::vector<SearchDir> m_searchDirs; + std::map<std::pair<ResourceType, std::string>, std::shared_ptr<Resource>> m_loadedResources; +}; +#endif
\ No newline at end of file diff --git a/NvBlast/samples/SampleBase/renderer/ShaderUtils.h b/NvBlast/samples/SampleBase/renderer/ShaderUtils.h new file mode 100644 index 0000000..778c811 --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/ShaderUtils.h @@ -0,0 +1,99 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#ifndef SHADER_UTILS_H +#define SHADER_UTILS_H + +#include "Utils.h" +#include <d3dcompiler.h> + + +static HRESULT CompileShaderFromFile(const char* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, + ID3DBlob** ppBlobOut) +{ + HRESULT hr = S_OK; + ID3DBlob* pErrorBlob = NULL; + + WCHAR wFileName[MAX_PATH]; + MultiByteToWideChar(CP_ACP, 0, szFileName, -1, wFileName, MAX_PATH); + wFileName[MAX_PATH - 1] = 0; + hr = D3DCompileFromFile(wFileName, NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE, szEntryPoint, szShaderModel, D3D10_SHADER_ENABLE_STRICTNESS, 0, + ppBlobOut, &pErrorBlob); + if(FAILED(hr)) + { + OutputDebugStringA((char*)pErrorBlob->GetBufferPointer()); + SAFE_RELEASE(pErrorBlob); + return hr; + } + SAFE_RELEASE(pErrorBlob); + + return S_OK; +} + +static HRESULT createShader(ID3D11Device* pDev, const void* pData, size_t len, ID3D11VertexShader** ppShd, bool) +{ + return pDev->CreateVertexShader(pData, len, nullptr, ppShd); +} + +static HRESULT createShader(ID3D11Device* pDev, const void* pData, size_t len, ID3D11GeometryShader** ppShd, + bool forceFast) +{ + PX_UNUSED(forceFast); + return pDev->CreateGeometryShader(pData, len, nullptr, ppShd); +} + +static HRESULT createShader(ID3D11Device* pDev, const void* pData, size_t len, ID3D11PixelShader** ppShd, bool) +{ + return pDev->CreatePixelShader(pData, len, nullptr, ppShd); +} + +static const char* shaderModel(ID3D11VertexShader**) +{ + return "vs_5_0"; +} + +static const char* shaderModel(ID3D11GeometryShader**) +{ + return "gs_5_0"; +} + +static const char* shaderModel(ID3D11PixelShader**) +{ + return "ps_5_0"; +} + +// Give back the shader buffer blob for use in CreateVertexLayout. Caller must release the blob. +template <class S> +static HRESULT createShaderFromFile(ID3D11Device* pDev, const char* szFileName, LPCSTR szEntryPoint, S** ppShd, + ID3DBlob*& pShaderBuffer, bool forceFast = false) +{ + HRESULT hr = CompileShaderFromFile(szFileName, szEntryPoint, shaderModel(ppShd), &pShaderBuffer); + if(SUCCEEDED(hr) && pShaderBuffer) + { + const void* shaderBufferData = pShaderBuffer->GetBufferPointer(); + const UINT shaderBufferSize = pShaderBuffer->GetBufferSize(); + createShader(pDev, shaderBufferData, shaderBufferSize, ppShd, forceFast); + } + return hr; +} + +// Overloaded, same as above but don't give back the shader buffer blob. +template <class S> +static HRESULT createShaderFromFile(ID3D11Device* pDev, const char* szFileName, LPCSTR szEntryPoint, S** ppShd, + bool forceFast = false) +{ + ID3DBlob* pShaderBuffer = NULL; + HRESULT hr = createShaderFromFile(pDev, szFileName, szEntryPoint, ppShd, pShaderBuffer, forceFast); + SAFE_RELEASE(pShaderBuffer); + return hr; +} + + +#endif //SHADER_UTILS_H
\ No newline at end of file diff --git a/NvBlast/samples/SampleBase/renderer/SkinnedRenderMesh.cpp b/NvBlast/samples/SampleBase/renderer/SkinnedRenderMesh.cpp new file mode 100644 index 0000000..c575d6c --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/SkinnedRenderMesh.cpp @@ -0,0 +1,217 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + + +#include "SkinnedRenderMesh.h" +#include "Renderer.h" + +SkinnedRenderMesh::SkinnedRenderMesh(const std::vector<const SimpleMesh*>& meshes) +{ + PX_ASSERT_WITH_MESSAGE(meshes.size() <= MeshesCountMax, "meshes.size() have to be <= SkinnedRenderMesh::MeshesCountMax"); + + m_device = GetDeviceManager()->GetDevice(); + + // input element desc setup + m_inputDesc.push_back({ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }); + m_inputDesc.push_back({ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }); + m_inputDesc.push_back({ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }); + m_inputDesc.push_back({ "TEXCOORD", 1, DXGI_FORMAT_R32_UINT, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }); + + // reserve VB + uint32_t verticesTotal = 0; + std::for_each(meshes.begin(), meshes.end(), [&](const SimpleMesh* c) { verticesTotal += (uint32_t)c->vertices.size(); }); + std::vector<SimpleMesh::Vertex> vertexBuffer; + vertexBuffer.reserve(verticesTotal); + + // reserve IB + uint32_t indicesTotal = 0; + std::for_each(meshes.begin(), meshes.end(), [&](const SimpleMesh* c) { indicesTotal += (uint32_t)c->indices.size(); }); + m_indices.reserve(indicesTotal); + + // fill VB, IB, MeshInfo + m_meshesInfo.resize(meshes.size()); + for (uint32_t meshIndex = 0; meshIndex < meshes.size(); ++meshIndex) + { + const SimpleMesh* mesh = meshes[meshIndex]; + MeshInfo& meshInfo = m_meshesInfo[meshIndex]; + + meshInfo.firstVertex = (uint32_t)vertexBuffer.size(); + vertexBuffer.insert(vertexBuffer.end(), mesh->vertices.begin(), mesh->vertices.end()); + meshInfo.verticesCount = (uint32_t)mesh->vertices.size(); + + meshInfo.firstIndex = (uint32_t)m_indices.size(); + uint32_t indexOffset = meshInfo.firstVertex; + for (uint32_t index : mesh->indices) + { + m_indices.push_back((uint32_t)index + indexOffset); + } + meshInfo.indicesCount = (uint32_t)mesh->indices.size(); + } + + // vertex buffer + { + D3D11_SUBRESOURCE_DATA vertexBufferData; + + ZeroMemory(&vertexBufferData, sizeof(vertexBufferData)); + vertexBufferData.pSysMem = vertexBuffer.data(); + + D3D11_BUFFER_DESC bufferDesc; + + memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.ByteWidth = (uint32_t)(sizeof(SimpleMesh::Vertex) * vertexBuffer.size()); + bufferDesc.CPUAccessFlags = 0; + bufferDesc.MiscFlags = 0; + bufferDesc.Usage = D3D11_USAGE_IMMUTABLE; + + V(m_device->CreateBuffer(&bufferDesc, &vertexBufferData, &m_vertexBuffer)); + } + + // bone index buffer + { + D3D11_BUFFER_DESC bufferDesc; + + memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.ByteWidth = (uint32_t)(sizeof(uint32_t) * vertexBuffer.size()); + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + + V(m_device->CreateBuffer(&bufferDesc, nullptr, &m_boneIndexBuffer)); + } + + // index buffer + { + D3D11_BUFFER_DESC bufferDesc; + + memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); + bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc.ByteWidth = (uint32_t)(sizeof(uint32_t) * m_indices.size()); + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + + V(m_device->CreateBuffer(&bufferDesc, nullptr, &m_indexBuffer)); + } + + // bone texture + { + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = 4; + desc.Height = (uint32_t)meshes.size(); + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + + V(m_device->CreateTexture2D(&desc, nullptr, &m_boneTexture)); + } + + // bone texture SRV + { + D3D11_SHADER_RESOURCE_VIEW_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + desc.Texture2D.MipLevels = 1; + desc.Texture2D.MostDetailedMip = 0; + V(m_device->CreateShaderResourceView(m_boneTexture, &desc, &m_boneTextureSRV)); + } +} + +SkinnedRenderMesh::~SkinnedRenderMesh() +{ + SAFE_RELEASE(m_vertexBuffer); + SAFE_RELEASE(m_boneIndexBuffer); + SAFE_RELEASE(m_indexBuffer); + SAFE_RELEASE(m_boneTexture); + SAFE_RELEASE(m_boneTextureSRV); +} + +void SkinnedRenderMesh::updateVisibleMeshes(const std::vector<uint32_t>& visibleMeshes) +{ + ID3D11DeviceContext* context; + m_device->GetImmediateContext(&context); + + // update bone index buffer + { + D3D11_MAPPED_SUBRESOURCE mappedRead; + V(context->Map(m_boneIndexBuffer, 0, D3D11_MAP_WRITE_DISCARD, NULL, &mappedRead)); + + uint32_t* boneIndexBuffer = (uint32_t*)mappedRead.pData; + for (uint32_t i = 0; i < visibleMeshes.size(); ++i) + { + const MeshInfo& info = m_meshesInfo[visibleMeshes[i]]; + for (uint32_t v = info.firstVertex; v < info.firstVertex + info.verticesCount; ++v) + { + boneIndexBuffer[v] = i; + } + } + + context->Unmap(m_boneIndexBuffer, 0); + } + + // update index buffer + { + D3D11_MAPPED_SUBRESOURCE mappedRead; + V(context->Map(m_indexBuffer, 0, D3D11_MAP_WRITE_DISCARD, NULL, &mappedRead)); + + uint32_t* indexBuffer = (uint32_t*)mappedRead.pData; + uint32_t indexCount = 0; + for (uint32_t meshIndex : visibleMeshes) + { + const MeshInfo& info = m_meshesInfo[meshIndex]; + memcpy(indexBuffer + indexCount, &m_indices[info.firstIndex], info.indicesCount * sizeof(uint32_t)); + indexCount += info.indicesCount; + } + context->Unmap(m_indexBuffer, 0); + m_indexCount = indexCount; + PX_ASSERT(m_indexCount % 3 == 0); + } +} + +void SkinnedRenderMesh::updateVisibleMeshTransforms(std::vector<PxMat44>& transforms) +{ + ID3D11DeviceContext* context; + m_device->GetImmediateContext(&context); + + // update bone transform texture + { + D3D11_MAPPED_SUBRESOURCE mappedRead; + V(context->Map(m_boneTexture, 0, D3D11_MAP_WRITE_DISCARD, NULL, &mappedRead)); + for (uint32_t i = 0; i < transforms.size(); ++i) + { + std::memcpy((uint8_t*)mappedRead.pData + i * mappedRead.RowPitch, &transforms[i], sizeof(PxMat44)); + } + context->Unmap(m_boneTexture, 0); + } +} + +void SkinnedRenderMesh::render(ID3D11DeviceContext& context) const +{ + context.IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + UINT strides[2] = { sizeof(SimpleMesh::Vertex), sizeof(uint32_t) }; + UINT offsets[2] = { 0 }; + ID3D11Buffer* buffers[2] = { m_vertexBuffer, m_boneIndexBuffer }; + context.IASetVertexBuffers(0, 2, buffers, strides, offsets); + + context.IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0); + + context.VSSetShaderResources(1, 1, &m_boneTextureSRV); + + context.DrawIndexed(m_indexCount, 0, 0); +}
\ No newline at end of file diff --git a/NvBlast/samples/SampleBase/renderer/SkinnedRenderMesh.h b/NvBlast/samples/SampleBase/renderer/SkinnedRenderMesh.h new file mode 100644 index 0000000..2f690d8 --- /dev/null +++ b/NvBlast/samples/SampleBase/renderer/SkinnedRenderMesh.h @@ -0,0 +1,82 @@ +/* +* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#ifndef SKINNED_RENDER_MESH_H +#define SKINNED_RENDER_MESH_H + +#include "Utils.h" +#include <DirectXMath.h> + +#include <vector> +#include "Renderable.h" +#include "Mesh.h" + +/** +SkinnedRenderMesh: + bonde indices are passed as vertex input, + bone transforms are stored in texture + max bone meshes count: SkinnedRenderMesh::MeshesCountMax +*/ +class SkinnedRenderMesh : public IRenderMesh +{ +public: + //////// ctor //////// + + SkinnedRenderMesh(const std::vector<const SimpleMesh*>& meshes); + ~SkinnedRenderMesh(); + + + //////// const //////// + + static const uint32_t MeshesCountMax = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + + //////// public API //////// + + void updateVisibleMeshes(const std::vector<uint32_t>& visibleMeshes); + void updateVisibleMeshTransforms(std::vector<PxMat44>& transforms); + + + //////// IRenderMesh implementation //////// + + virtual const std::vector<D3D11_INPUT_ELEMENT_DESC>& getInputElementDesc() const { return m_inputDesc; } + virtual void render(ID3D11DeviceContext& context) const; + +private: + //////// internal data //////// + + struct MeshInfo + { + uint32_t firstIndex; + uint32_t indicesCount; + + uint32_t firstVertex; + uint32_t verticesCount; + }; + + std::vector<D3D11_INPUT_ELEMENT_DESC> m_inputDesc; + + ID3D11Device* m_device; + + ID3D11Buffer* m_vertexBuffer; + ID3D11Buffer* m_boneIndexBuffer; + ID3D11Buffer* m_indexBuffer; + ID3D11Texture2D* m_boneTexture; + ID3D11ShaderResourceView* m_boneTextureSRV; + + uint32_t m_indexCount; + + std::vector<MeshInfo> m_meshesInfo; + std::vector<uint32_t> m_indices; +}; + + + +#endif //SKINNED_RENDER_MESH_H
\ No newline at end of file |