DX11 SharpDX Directx11 How to add normal mapping ?

Recommended Posts

I am trying to add normal map to my project I have an example of a cube: 

I have normal in my shader I think. Then I set shader resource view for texture (NOT BUMP)

            device.ImmediateContext.PixelShader.SetShaderResource(0, textureView);
            device.ImmediateContext.Draw(VerticesCount,0);

What should I do to set my normal map or how it is done in dx11 generally example c++?

Share this post


Link to post
Share on other sites

Normal mapping usually works like this:

You have a normal map which is a texture containing tangent space normal vectors in the red and green components (XY). You have to transform it to world space (XYZ) and replace your vertex normal with this. All your following light calculations should use this new normal vector. That's it.

The trickiest part is the basis transformation from tangent space to world space which you have to do in the pixel shader. Usually games provide tangent and binormal (also called bitangent) vectors in the vertex buffers for the mesh. Or just store the tangent and calculate the bitangent like this:

bitangent = cross(normal, tangent)

For calculating tangent vectors for the vertices, there is an open source library called mikktspace written in C++. You can derive a C# implementation if there is not one already available. An other option is that you can provide a quaternion representing the tangent space. And the final option is that you can calculate the tangent space inside the pixel shader from screen space derivatives, like this.

When you have you normal, tangent and binormal vectors, which are unit vectors, you can assemble the tangent space transform matrix like so:

tangentBasis = float3x3(tangent, binormal, normal)

If you multiply your tangent space normal vectors which came from the normal map texture, you get the world space normal vector.

Share this post


Link to post
Share on other sites
2 hours ago, turanszkij said:

Usually games provide tangent and binormal (also called bitangent) vectors in the vertex buffers for the mesh.

Alternatively, you can use Tangent Space Normal Mapping without Precomputed Tangents. This does not require tangents (or bitangents) stored per vertex at the expense of doing all calculations in the pixel shader.

Info + GLSL

Since, I do not use GLSL myself, I also have an HLSL version.

Edit: My apologies, didn't read the full answer before posting

Edited by matt77hias

Share this post


Link to post
Share on other sites

IT IS GOD DAMN HARD. I have to study history. I do not have that time. If I use hlsl sided one can I stay away from all of those calculations ? If I do it, will it work same about quality ?

Share this post


Link to post
Share on other sites
33 minutes ago, gomidas said:

If I do it, will it work same about quality ?

Same quality as what? As providing the coordinate frame yourself? It is not numerically the same, but that is not a real issue for your purposes. It is a perturbation (i.e. small scale), so that will be fine.

Share this post


Link to post
Share on other sites

I get something wrong about the setting file I think.

public Texture2D T2D_DiffuseMap = "File.png";
public ShaderResourceView textureView;

textureView = new ShaderResourceView(device, T2D_DiffuseMap);
device.ImmediateContext.PixelShader.SetShaderResource(0, textureView);

So will I have a Texture2D array that keeps multiple files diffuse.png and normal.png then I will do it like : new ShaderResourceView(device, TextureData); //diffuse.png and normal.png ??? Then I will modifyshader file. Or I am getting it wrong ? I am asking because there is no source for c#.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Forum Statistics

    • Total Topics
      628764
    • Total Posts
      2984575
  • Similar Content

    • By Dimitry
      Hi. I have a game prototype written in C# that I've been working on for some time. 
      I've studied some network programming and Unity. I have a client-server application demo completed. But I realized that making all alone is quite troublesome.
      Unity graphics, networking, GUI, game logic, so on. So I am looking for a skilled developer who is also a fan of a Space Rangers computer game and space adventure games in general. 
      We could discuss and share some ideas and perhaps even meet in person at some coworking space. 
    • By Scouting Ninja
      So I am using Boids to create flocking behavior for  large amount of zombies.The problem I have is in my Separation pass I check the distance of each zombie compared to each zombie. I think this is wrong.
      This causes a exponential cost. 10 Zombies need to check all of the zombies 10*10 = 100 loops. Not bad but 1 000 *1 000 = 1 000 000 loops. So I am getting a power of two amount of loops.
      I feel that there is some thing simple I am missing?
    • By blueshogun96
      I'm writing a GUI based GPU tool and I'm using C# and WPF since it will make my life easier bringing this app to the Win10 store.  IMHO, it's surprisingly hard to find a good series of tutorials that teach you more than how to add some buttons to a window, input text, etc.  My app won't use that much, and what I really need is to create a GUI similar to that of the task manager.  What I mean are tabs to switch between graphs and tables, etc.  Also, I can't find any code on how to add a graph (histogram) to my app, and so on.  I've googled quite a bit and found out that some tutorials are behind a friggin pay wall?!  Ugh.
      Not to complain, just hoping to find something so I can get this thing working acceptably before Wednesday.
      Thanks,
      Shogun
    • By blueshogun96
      I'm writing a GPU tool with C# for the UI and command line .exes that the user interacts with, and writing the necessary driver code to make it work in C++ (via .dll).  So far, loading an unmanaged .dll file written in C++ is trivial and easy, but there's one part that confuses me (mostly because I am not a C# expert, yet).  How do you handle structures as parameters?  My code crashes when I try to use a structure as a parameter.  Should I use an IntPtr instead and just cast it? 
      I'll show you a bit of code to show you what I mean:
      C++:
       
      typedef struct _GPUDETAILS { CHAR DeviceDesc[128]; DWORD DeviceID; DWORD VendorID; } GPUDETAILS; ... GPUMONEXDRIVERNVAPI_API int Drv_GetGpuDetails( int AdapterNumber, GPUDETAILS* pGpuDetails ) { _LOG( __FUNCTION__ << "(): TODO: Implement...\n" ); if( !pGpuDetails ) { _ERROR( "Invalid parameter!" << std::endl ); return 0; } _LOG( __FUNCTION__ << "(): Gathering GPU details...\n" ); strcpy( pGpuDetails->DeviceDesc, "NVIDIA Something..." ); pGpuDetails->DeviceID = 0xFFFF; /* TODO */ pGpuDetails->VendorID = 0x10DE; /* This is always a given */ return 1; } Something simple for now.  Let's move on to the C# part...
      namespace GPUMonEx { /* * GPU Details structure * NOTE: Subject to change */ public struct GPUDETAILS { public string DeviceDesc; public UInt32 DeviceID; public UInt32 VendorID; } /* * Driver importer classes for the following APIs under Windows * TODO: Get ahold of Intel's SDK as well as implement AMD's equivalent for their hardware. * * NVAPI - NVIDIA Driver Specific functionality * D3DKMT - Direct3D internal driver functions. Should work for all GPUs, but currently needed for Intel. */ static class DrvD3DKMT { [DllImport("GPUMonEx.Driver.D3DKMT.dll")] public static extern int Drv_Initialize(); [DllImport("GPUMonEx.Driver.D3DKMT.dll")] public static extern void Drv_Uninitialize(); [DllImport("GPUMonEx.Driver.D3DKMT.dll")] public static extern unsafe int Drv_GetGpuDetails(int Adapter, ref GPUDETAILS pGpuDetails); [DllImport("GPUMonEx.Driver.D3DKMT.dll")] public static extern int Drv_GetOverallGpuLoad(); [DllImport("GPUMonEx.Driver.D3DKMT.dll")] public static extern int Drv_GetGpuTemperature(); } static class DrvNVAPI { [DllImport("GPUMonEx.Driver.NVAPI.dll")] public static extern int Drv_Initialize(); [DllImport("GPUMonEx.Driver.NVAPI.dll")] public static extern void Drv_Uninitialize(); [DllImport("GPUMonEx.Driver.NVAPI.dll")] public static extern unsafe int Drv_GetGpuDetails(int Adapter, ref GPUDETAILS pGpuDetails); [DllImport("GPUMonEx.Driver.NVAPI.dll")] public static extern int Drv_GetOverallGpuLoad(); [DllImport("GPUMonEx.Driver.NVAPI.dll")] public static extern int Drv_GetGpuTemperature(); } /* * GPU Driver interfacing classes (the ones you actually call in user mode) */ public abstract class GPUDriverBase { public abstract int Initialize(); public abstract void Uninitialize(); public abstract int GetGpuDetails( int Adapter, ref GPUDETAILS pGpuDetails ); public abstract int GetOverallGpuLoad(); public abstract int GetGpuTemperature(); } public class GPUDriverD3DKMT : GPUDriverBase { public override int Initialize() { return DrvD3DKMT.Drv_Initialize(); } public override void Uninitialize() { DrvD3DKMT.Drv_Uninitialize(); } public override int GetGpuDetails( int Adapter, ref GPUDETAILS pGpuDetails ) { return DrvD3DKMT.Drv_GetGpuDetails( Adapter, ref pGpuDetails ); } public override int GetOverallGpuLoad() { return DrvD3DKMT.Drv_GetOverallGpuLoad(); } public override int GetGpuTemperature() { return DrvD3DKMT.Drv_GetGpuTemperature(); } } public class GPUDriverNVAPI : GPUDriverBase { public override int Initialize() { return DrvNVAPI.Drv_Initialize(); } public override void Uninitialize() { DrvNVAPI.Drv_Uninitialize(); } public override int GetGpuDetails(int Adapter, ref GPUDETAILS pGpuDetails) { return DrvNVAPI.Drv_GetGpuDetails(Adapter, ref pGpuDetails); } public override int GetOverallGpuLoad() { return DrvNVAPI.Drv_GetOverallGpuLoad(); } public override int GetGpuTemperature() { return DrvNVAPI.Drv_GetGpuTemperature(); } } } So, focusing on Drv_GetGpuDetails(), how do I actually get a valid structure filled in here?  Calling that function just crashes.  I'm sure it's a stupid easy fix, but once again, I'm far too C++ oriented and have yet to get used to C# in the same manner.
      Any advice is welcome (on the question at hand or anything else).
      Shogun
    • By GreenGodDiary
      Having some issues with a geometry shader in a very basic DX app.
      We have an assignment where we are supposed to render a rotating textured quad, and in the geometry shader duplicate this quad and offset it by its normal. Very basic stuff essentially.
      My issue is that the duplicated quad, when rendered in front of the original quad, seems to fail the Z test and thus the original quad is rendered on top of it.
      Whats even weirder is that this only happens for one of the triangles in the duplicated quad, against one of the original quads triangles.

      Here's a video to show you what happens: Video (ignore the stretched textures)

      Here's my GS: (VS is simple passthrough shader and PS is just as basic)
      struct VS_OUT { float4 Pos : SV_POSITION; float2 UV : TEXCOORD; }; struct VS_IN { float4 Pos : POSITION; float2 UV : TEXCOORD; }; cbuffer cbPerObject : register(b0) { float4x4 WVP; }; [maxvertexcount(6)] void main( triangle VS_IN input[3], inout TriangleStream< VS_OUT > output ) { //Calculate normal float4 faceEdgeA = input[1].Pos - input[0].Pos; float4 faceEdgeB = input[2].Pos - input[0].Pos; float3 faceNormal = normalize(cross(faceEdgeA.xyz, faceEdgeB.xyz)); //Input triangle, transformed for (uint i = 0; i < 3; i++) { VS_OUT element; VS_IN vert = input[i]; element.Pos = mul(vert.Pos, WVP); element.UV = vert.UV; output.Append(element); } output.RestartStrip(); for (uint j = 0; j < 3; j++) { VS_OUT element; VS_IN vert = input[j]; element.Pos = mul(vert.Pos + float4(faceNormal, 0.0f), WVP); element.Pos.xyz; element.UV = vert.UV; output.Append(element); } }  
      I havent used geometry shaders much so im not 100% on what happens behind the scenes.
      Any tips appreciated! 
  • Popular Now