Tag: directx

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

Warning! Some information on this page is older than 5 years now. I keep it for reference, but it probably doesn't reflect my current knowledge and beliefs.

Pages: > 1 2 3 4 5 ... 8 >

# Half-Pixel Offset in DirectX 11

21:58
Fri
09
Nov 2012

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 | #directx #rendering Share

# Implementing ID3D10Include

20:56
Sat
03
Nov 2012

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 | #directx Share

# Flat Shading in DirectX 11

23:50
Fri
02
Nov 2012

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 | #rendering #directx Share

# Direct3D 11 Checklist

22:52
Mon
23
Jul 2012

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 | #directx Share

# Direct2D versus Direct3D

17:27
Sun
20
May 2012

Direct2D library is not a completely new graphics API down to the driver level. It internally creates and uses Direct3D 10 device object. Of course it is a powerful library, not just a thin wrapper. But still everything ends up as a bunch of trianges uploaded to the buffer with Map/Unmap and sent to the GPU to be rendered using some vertex and pixel shader. PIX clearly shows all this:

Direct2D in PIX

As a result, Direct2D is able to exchange data with Direct3D 10. Unfortunately it's not the case with Direct3D 11. Topic How to use D2D with D3D11? at gamedev.net forum describes solution to this, full of problems and COM interface manipulation. Post DirectX Componentization and Interoperability by BenCon on DirectX Developer Blog nicely explains interop between different graphics API-s in Windows as a bigger picture. There is also a nasty hack to make D2D work (almost) directly with D3D11, described in post Hacking Direct2D to use directly Direct3D 11 instead of Direct3D 10.1 API on Code4k blog. But no clean and easy way exists.

So I give up with Direct2D for now. All in all, everything can be done by rendering triangles directly in Direct3D :P One thing I'll be missing is the perspective of easy high-quality text rendering with DirectWrite. Well, I'll go back to Bitmap Font Generator from AngelCode :P

Comments | #direct2d #directx #pix Share

# DirectXMath - A First Look

22:06
Sun
15
Apr 2012

Programmers using DirectX have access to the accompanying library full of routines that support various 3D math calculations. First it was D3DX - auxilliary library tightly coupled with DirectX itself. It's still there, but some time ago Microsoft released a new library called XNA Math. I've written about it here. This library also ships with latest versions of DirectX SDK (which was last updated in Jun 2010), but it is something completely new - a more independent, small, elegant and efficient library, portable between Windows (where it can use SSE2 or old FPU) and Xbox 360.

Now Microsoft comes up with another library called DirectXMath. See the official documentation and introductory blog post for details. As a successor of XNA Math, it looks very similar. Main differences are:

Sounds great? Well, I didn't tell yet how to get it. It's not shipped with DirectX SDK. You need the SDK for Windows 8. They say that:

The library is annotated using SAL2 (rather than the older VS-style or Windows-style annotations), so requires the standalone Windows SDK for Windows 8 Consumer Preview or some additional fixups to use with Visual C++ 2010.

So probably I'm not going to switch to this new library anytime soon :P

Comments | #directx #math Share

# FX Batch Compiler 1.1

22:48
Thu
17
Feb 2011

4 years ago I've coded a program to visually support batch compilation of multiple HLSL shaders using the console fxc.exe compiler from DirectX SDK. I called it FX Batch Compiler and it's open source, under GNU GPL license, written in C#. Now I've updated it to new version 1.1. So if you use Direct3D, check it to see if it can be useful for you. I use it sometimes in my projects.

Features:

Comments | #directx Share

# XNA Math and Access Violation

21:40
Wed
16
Feb 2011

XNA Math is a great math library bundled with DirectX SDK. I've written about it here: Introduction to XNA Math, XNA Math Cheat Sheet. Recently I've started coding some small raytracer using this library (especially XMVECTOR type) and I came across an error:

"Access violation reading location 0xffffffff"

Google didn't display many results when asked about this error in connection with "XNA Math" or "XMVECTOR", but I found a topic on our Polish gamdev forum: xnamath i dziwne crashe. Directed to other web places from there, I discovered that, just as I thought, this bug comes from misaligned address of the vector. XMVECTOR on PC is an alias for SSE __m128 type, which has to be always aligned to 16-byte boundary. Compiler seems to know about this alignment requirement and respects it whenever XMVECTOR is defined on the stack, passed as function parameter or returned from a function, but not when the vector is a member of some dynamically allocated class or struct. So this won't work:

struct Scene {
    XMVECTOR dir_to_light;
};

Scene *scene = new Scene();
scene->dir_to_light = XMVector3Normalize(
    XMVectorSet(1.5f, 1.f, -2.f, 0.f)); // Crash!

Adding special alignment declaration supported by Visual C++ - __declspec(align(16)) - doesn't help. it looks like operator new always aligns allocated objects to 8 bytes and there is no way to change this behavior other than redefining it to use your own custom memory allocator.

So I suppose the most simple and convenient way to walk around this problem is to use more "casual" types for storing vectors - the ones that do not use SSE and do not require alignment, like XMFLAOT3 (which is just struct with float x, y, z). Anyway XMVECTOR is designed to optimize computations when compiler is able to place it in the CPU registers. So my solution looks like this:

struct Scene {
    XMFLOAT3 dir_to_light;
};

Scene *scene = new Scene();
XMVECTOR dir_to_light = XMVector3Normalize(
    XMVectorSet(1.5f, 1.f, -2.f, 0.f));
XMStoreFloat3(&scene->dir_to_light, dir_to_light);

...

XMVECTOR dir_to_light = XMLoadFloat3(&scene->dir_to_light);
XMVECTOR n_dot_l = XMVectorSaturate(XMVector3Dot(normal, dir_to_light));

Comments | #directx #math Share

Pages: > 1 2 3 4 5 ... 8 >

STAT NO AD
[Stat] [STAT NO AD] [Download] [Dropbox] [pub] [Mirror] [Privacy policy]
Copyright © 2004-2018