Tag: directx

Entries for tag "directx", ordered from most recent. Entry count: 49.

Pages: 1 2 3 ... 7 >

22:23
Mon
16
Sep 2013

Book Review: DirectX 11.1 Game Programming

"DirectX 11.1 Game Programming" is a new book published by Packt Publishing, written by Pooya Eimandar. It introduces new features of DirectX 11.1 and some other technologies available for game developers when writing Metro-style apps for Windows 8. The book uses C++/CX - a new language based on C++, with the syntax somewhat similar to C++/CLI (the language is extended by managed pointer operator ^). But while C++/CLI is a .NET language (like C#), C++/CX is compiled to native code and the ^ pointer is just a convenient syntax for reference-counting smart pointer to a COM object. Math is done with DirectXMath library (the successor of XNA Math).

Each of the chapters describes several loosely coupled topics. Their flattened list looks like this:

I have mixed feelings about this book. Contrary to what title suggests and what the author claims inside ("By the end of this chapter, we are going to have a multithreaded game engine"), you obviously cannot learn game programming by reading just 146 pages. Especially as the book covers so many different topics. It looks like the author wanted to include everything what's fresh and sexy in Microsoft Windows 8 API-s. As a result, each example is kind of "Hello World" - the simplest possible application of the described technology.

But at the same time, the book is also not teaching 3D games programming from the start. It explains some selected basic concepts in more details (e.g. describes what vertex shader does, shows how rotation matrices look like, how to use constant, vertex and index buffer or shows a diagram of the graphics pipeline - 3 times actually :) but generally you should already know C++ and preferably DirectX 10/11 to make use of the knowledge from this book. It is more like an overview of "What's New" in Windows 8, DirectX 11-11.1 and new Visual Studio.

I think the biggest value of this book is the attached source code. Each chapter is accompanied by a complete C++/CX project that shows an application of the described technology and the text in the book is an overview of this code. So if you already know some game programming in C++ and DirectX 10/11, this book can be a good tutorial which will help you to start using latest Microsoft technologies and develop Windows 8 Metro-style games. Preface says "This book will help you easily create your own framework and build your first game for Metro Style all by yourself in order to publish it on the Windows Store." and that is true.

But whether this is worth doing, that's another question. Surely you can use DX 11 on 9- or 10-compatible hardware, using Feature Level, but you cannot use most of what this book describes below Windows 8, and many of these things also without buying Visual Studio Professional or higher. According to Steam Hardware & Software Survey: Auguest 2013, while 64.78% of gamers already have DirectX 11 capable system and GPU, only 15.41% of them have Windows 8 installed (and it's already a year since its release).

Now it's time for a contest. Packt has proposed to offer 3 digital copies of the book. All you need to do is head on over to the book page, look through the product description of the book and then drop a line via the comments below this post to let us know what interests you the most about this book. 3 best comments win!!! Deadline: The contest will close in 1 weeks time. Winners will be contacted by email, so be sure to use your real email address when you comment.

Comments (11) | Tags: books competitions reviews directx | Author: Adam Sawicki | Share

19:44
Wed
30
Jan 2013

CConstantBuffer, CTypedConstantBuffer

DirectX 10 and 11 have new, redesigned API that has its pros and cons. One can say that it is now more clean and well organized, but on the other hand it requires more (or as those who code in higher-level languages than C++ or use existing game engines would say - *even more*) lines of code than old Direct3D 9. So I created classes that encapsulate some most typical boilerplate D3D11 code. Here is first one - CConstantBuffer, which handles constant buffer, required now to pass any uniform parameters to a shader.

class CConstantBuffer {
public:
    CConstantBuffer(
        size_t bytesLength,
        const void* initialData = nullptr,
        bool immutable = false );
    ~CConstantBuffer();
    ID3D11Buffer* Buffer() { return m_Buffer.get(); }
    void Update(const void* src);
    void SetForVS(UINT slot);
    // ...and so on for HS, DS, GS, PS, CS.
private:
    size_t m_Length;
    unique_ptr<ID3D11Buffer, ReleaseDeleter> m_Buffer;
};

Read full entry > | Comments (4) | Tags: directx | Author: Adam Sawicki | Share

16:09
Sat
19
Jan 2013

How to Flip Triangles in Triangle Mesh

Given triangle mesh, as we use it in real-time rendering of 3D graphics, we say that each triangle have two sides, depending on whether its vertices are oriented clockwise or counterclockwise from particular point of view. In Direct3D, by default, triangles oriented clockwise are considered front-facing and they are visible, while triangles oriented counterclockwise are invisible because they are discarded by the API feature called backface culling.

When we have backface culling enabled and we convert mesh between coordinate systems, we sometimes need to "flip triangles". When vertices of each triangle are separate, an algorithm for this is easy. We just need to swap first with third vertex of each triangle (or any other two vertices). So we can start implementing the flipping method like this:

class CMesh
{
    ...
    D3D11_PRIMITIVE_TOPOLOGY m_Topology;
    bool m_HasIndices;
    std::vector<SVertex> m_Vertices;
    std::vector<uint32_t> m_Indices;
};

void CMesh::FlipTriangles()
{
    if(m_Topology == D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST)
    {
        if(m_HasIndices)
            FlipTriangleListInArray<uint32_t>(m_Indices);
        else
            FlipTriangleListInArray<SVertex>(m_Vertices);
    }
    ...
}

Where the function template for flipping triangles in a vector is:

template<typename T>
void CMesh::FlipTriangleListInArray(std::vector<T>& values)
{
    for(size_t i = 0, count = values.size(); i < count - 2; i += 3)
        std::swap(values[i], values[i + 2]);
}

Simple reversing all elements in the vector with std::reverse would also do the job. But things get complicated when we consider triangle strip topology. (I assume here that you know how graphics API-s generate orientation of triangles in a triangle strip.) Reversing vertices works, but only when number of vertices in the strip is odd. When it's even, triangles stay oriented in the same way.

I asked question about this on forum.warsztat.gd (in Polish). User albiero proposed following solution: just duplicate first vertex. It will generate additional degenerate (invisible) triangle, but thanks to this all following triangles will be flipped. It seems to work!

I also wanted to handle strip-cut index (a special value -1 which starts new triangle strip), so the rest of my fully-featured algorithm for triangle flipping is:

    ...
    else if(m_Topology == D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP)
    {
        if(m_HasIndices)
        {
            size_t begIndex = 0;
            while(begIndex < m_Indices.size())
            {
                const size_t indexCount = m_Indices.size();
                while(begIndex < indexCount && m_Indices[begIndex] == UINT_MAX)
                    ++begIndex;
                if(begIndex == indexCount)
                    break;
                size_t endIndex = begIndex + 1;
                while(endIndex < indexCount && m_Indices[endIndex] != UINT_MAX)
                    ++endIndex;
                // m_Indices.size() can change here!
                FlipTriangleStripInArray<uint32_t>(m_Indices, begIndex, endIndex);
                begIndex = endIndex + 1;
            }
        }
        else
            FlipTriangleStripInArray<SVertex>(m_Vertices, 0, m_Vertices.size());
    }
}

Where function template for flipping triangles in selected part of a vector is:

template<typename T>
void CMesh::FlipTriangleStripInArray(std::vector<T>& values, size_t begIndex, size_t endIndex)
{
    const size_t count = endIndex - begIndex;
    if(count < 3) return;
    // Number of elements (and triangles) is odd: Reverse elements.
    if(count % 2)
        std::reverse(values.begin() + begIndex, values.begin() + endIndex);
    // Number of elements (and triangles) is even: Repeat first element.
    else
        values.insert(values.begin() + begIndex, values[begIndex]);
}

Comments (13) | Tags: directx rendering algorithms | Author: Adam Sawicki | Share

21:56
Wed
16
Jan 2013

DirectX 11 Renderer - a Screenshot

Here is what I've been working on in my free time recently. It's a renderer For PC, Windows, using DirectX 11.

It may not look spectacular here because I've just quickly put random stuff into this scene, but I already have lots of code that can do useful things, like deferred shading with dynamic directional and point lights, a bunch of material parameters, mesh processing and loading from OBJ file format, heightmap generation, particle effects and postprocessing (including bloom of course :)

In the next posts I will describe some pieces of my technology and share some C++ code.

Comments (14) | Tags: rendering productions directx | Author: Adam Sawicki | Share

21:58
Fri
09
Nov 2012

Half-Pixel Offset in DirectX 11

There is a problem graphics programmers often have to face known as half-pixel/half-texel offset. In Direct3D 9 the probably most official article about it was Directly Mapping Texels to Pixels. In Direct3D 10/11 they changed the way it works so it can be said that the problem is gone now. But I can see the entry about SV_Position in the Semantics article does not explain it clearly, so here is my short explanation.

A pixel on a screen or texel on a texture can be seen as a matrix cell, visualized as square filled with some color. That's the way we treat it in 2D graphics where we index pixels from left-top corner using integer (x, y) coordinates.

But in 3D graphics, texture can be sampled using floating-point coordinates and interpolation between texel colors can be performed. Texture coordinates in DirectX also starts from left-top corner, but position (0, 0) means the very corner of the texture, NOT the center of the first texel! Similarly, position (1, 1) on texture means its bottom-right corner. So to get exactly the color of the second texel of 8 x 8 texture, we have to sample with coordinates (1.5 / 8, 0.5 / 8).

Now if we rendered 3D scene onto a texture to perform e.g. deferred shading or some other screen-space postprocessing and we want to redraw it to the target back buffer, how do we determine coordinates for sampling this texture based on position of rendered pixel? There is a system value semantics available at pixel shader input called SV_Position which gives (x, y) pixel position. It is expressed in pixels, so it goes to e.g. (1920, 1080) and not to (1, 1) like texture coordinates. But it turns out that in Direct3D 10/11, the value of SV_Target for first pixels on the screen is not (0, 0), (1, 0), but (0.5, 0.5), (1.5, 0.5)!

Therefore to sample texture based on pixel position, it's enought to divide it by screen resolution. No need to perform any half-pixel offset - to add or subtract (0.5, 0.5), like it was done in Direct3D 9.

Texture2D g_Texture : register(t0);
SamplerState g_SamplerState : register(s0);

cbuffer : register(b0) {
    float2 g_ScreenResolution;
};

void PixelShader(float2 Position : SV_Position, out float4 Color : SV_Target)
{
    Color = g_Texture.Sample(g_SamplerState, Position / g_ScreenResolution);
}

Comments (7) | Tags: directx rendering | Author: Adam Sawicki | Share

20:56
Sat
03
Nov 2012

Implementing ID3D10Include

DirectX shaders in HLSL language can use #include preprocessor directive, just like C and C++ code. When you compile a shader from file using D3DX11CompileFromFile function, it works automatically. But what if you keep your shader source in memory and compile it with D3DX11CompileFromMemory? DirectX doesn't know the location of source file (if any), so it can't locate additional files to include.

But there is a solution. Parameter __in LPD3D10INCLUDE pInclude allows passing your own object implementing ID3D10Include interface (a typedef to ID3DInclude) that can help DirectX in loading included files while preprocessing shader source. We don't event have to deal with COM interfaces here. We can just implement and use a class like the one below. The code uses lots of stuff from my CommonLib, so it's not self-contained and ready to copy-paste, but it should give a clue about how to do it.

class CShaderInclude : public ID3DInclude
{
public:
    // shaderDir: Directory of current shader file, used by #include "FILE"
    // systemDir: Default shader includes directory, used by #include <FILE>
    CShaderInclude(const char* shaderDir, const char* systemDir) :
        m_ShaderDir(shaderDir),
        m_SystemDir(systemDir)
    {
    }

    HRESULT __stdcall Open(
        D3D_INCLUDE_TYPE IncludeType,
        LPCSTR pFileName,
        LPCVOID pParentData,
        LPCVOID *ppData,
        UINT *pBytes);
    
    HRESULT __stdcall Close(LPCVOID pData);

private:
    string m_ShaderDir;
    string m_SystemDir;
};

HRESULT __stdcall CShaderInclude::Open(
    D3D_INCLUDE_TYPE IncludeType,
    LPCSTR pFileName,
    LPCVOID pParentData,
    LPCVOID *ppData,
    UINT *pBytes)
{
    try
    {
        /*
        If pFileName is absolute: finalPath = pFileName.
        If pFileName is relative: finalPath = dir + "\\" + pFileName
        */
        string finalPath;
        switch(IncludeType)
        {
        case D3D_INCLUDE_LOCAL: // #include "FILE"
            common::RelativeToAbsolutePath(&finalPath, m_ShaderDir, pFileName);
            break;
        case D3D_INCLUDE_SYSTEM: // #include <FILE>
            common::RelativeToAbsolutePath(&finalPath, m_SystemDir, pFileName);
            break;
        default:
            assert(0);
        }

        common::FileStream fileStream(finalPath, common::FM_READ);
        uint32_t fileSize = fileStream.GetSize();

        if(fileSize)
        {
            char* buf = new char[fileSize];
            fileStream.MustRead(buf, fileSize);

            *ppData = buf;
            *pBytes = fileSize;
        }
        else
        {
            *ppData = nullptr;
            *pBytes = 0;
        }
        return S_OK;
    }
    catch(common::Error& err)
    {
        PrintError(err);
        return E_FAIL;
    }
}

HRESULT __stdcall CShaderInclude::Close(LPCVOID pData)
{
    // Here we must correctly free buffer created in Open.
    char* buf = (char*)pData;
    delete[] buf;
    return S_OK;
}

/*
Inputs:
    std::vector<char> shaderData
    const char* filePath
    const char* functionName
    const char* profile
Outputs:
    HRESULT hr
    ID3DBlob* shaderBlob
    ID3DBlob* errorBlob
*/

string shaderDir;
common::ExtractFilePath(&shaderDir, filePath);

CShaderInclude includeObj(shaderDir.c_str(), "Shaders/Include");

HRESULT hr = D3DX11CompileFromMemory(
    shaderData.data(),
    shaderData.size(),
    filePath,
    nullptr, // pDefines
    &includeObj,
    functionName,
    profile,
    0, // Flags1
    0, // Flags2
    nullptr, // pPump
    &shaderBlob,
    &errorBlob,
    nullptr); // pHResult

Comments (4) | Tags: directx | Author: Adam Sawicki | Share

23:50
Fri
02
Nov 2012

Flat Shading in DirectX 11

I code a terrain heightmap rendering and today I wanted to make it looking like in Darwinia. After preparing approporiate texture it turned out that normals of my mesh used for lighting are smoothed. That's not a suprise - after all there is a single vertex in every particular place, shared by surrounding triangles, refered multiple times from index buffer.

How to make triangles flat shaded? Make every vertex unique to its triangle to have different normal? In Direct3D 9 there was this state used by fixed function pipeline you could set to device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); What about Direct3D 10/11?

A simple solution is to use interpolation modifiers. Fields of structure passed from vertex shader to pixel shader can have these modifiers to tell GPU how to interpolate (or not to interpolate) particular value on the surface of a triangle. nointerpolation means the value will be taken from one of vertices. That solves the problem.

struct VS_TO_PS
{
    float4 Pos : SV_Position;
    nointerpolation float3 Normal : NORMAL;
    float2 TexCoord : TEXCOORD0;
};

Comments (2) | Tags: rendering directx | Author: Adam Sawicki | Share

22:52
Mon
23
Jul 2012

Direct3D 11 Checklist

In DirectX 9 there is a lot of states to be set in the device object, so there are these lengthy articles about what could be the cause of not seeing anything rendered on the screen. For example, you could forget to set D3DRS_LIGHTING to FALSE (default is TRUE) and all your geometry is totally black.

Direct3D 11, on the other hand, has more clean API. There is no fixed-function pipeline, only shaders and all remaining states are grouped into state objects. Still there are some things that need to be set before you make a successful draw call, so I prepared a handy checklist for that. Just remember that you can set NULL as any state object and it's still OK - some well defined defaults will be used in that case.

Of course that's not all what is possible, You can also change render target and depth-stencil, setup scissor rects, stream output, compute shader, unordered access views... Basically all you can find in ID3D11DeviceContext class. But I enlisted what I use most often.

Comments (16) | Tags: directx | Author: Adam Sawicki | Share

Pages: 1 2 3 ... 7 >

STAT NO AD [Stat] [Admin] [STAT NO AD] [pub] [Mirror] Copyright © 2004-2014 Adam Sawicki
Copyright © 2004-2014 Adam Sawicki