c# - Projection matrix causing inaccuracy in clip-space depth calculation? -


currently working slimdx's direct3d 11 bindings , having significant difficulty shader, source of follows:

/* * * * * * * * *  * param structs *  * * * * * * * * */ struct vspointin {     float3 pos      :   position;     float4 color    :   color; };  struct gsparticlein {     float3 pos      :   position;     float4 color    :   color;     float radius    :   radius; };  struct psparticlein {     float4 pos      :   sv_position;     float2 tex      :   texcoord0;     float3 eyepos   :   texcoord1;     float radius    :   texcoord2;     float4 color    :   color; };  struct psparticleout {     float4 color    : sv_target;     float depth     : sv_depth; };  /* * * * * * * * * * *   * constant buffers  *  * * * * * * * * * * */ cbuffer matrixbuffer : register(cb1) {     float4x4 invview;     float4x4 modelview;     float4x4 projection;     float4x4 modelviewprojection; };  cbuffer immutablebuffer {     float3 positions[4] =     {         float3(-1, 1, 0),         float3(1, 1, 0),         float3(-1, -1, 0),         float3(1, -1, 0)     };     float2 texcoords[4] =     {         float2(0, 0),         float2(1, 0),         float2(0, 1),         float2(1, 1)     };     float3 lightdirection = float3(-0.5, -0.5, -2.0); }  /* * * * * * * * *   * state objects *  * * * * * * * * */  blendstate additiveblending {     alphatocoverageenable = false;     blendenable[0] = true;     srcblend = src_alpha;     destblend = one;     blendop = add;     srcblendalpha = zero;     destblendalpha = zero;     blendopalpha = add;     rendertargetwritemask[0] = 0x0f; };  blendstate noblending {     alphatocoverageenable = false;     blendenable[0] = false; };  depthstencilstate enabledepth {     depthenable = true;     depthwritemask = all;     depthfunc = less_equal; };  depthstencilstate disabledepth {     depthenable = false;     depthwritemask = zero; };  /* * * * * * * * * * *   *  shader functions *  * * * * * * * * * * */ gsparticlein vsparticlemain(vspointin input) {     gsparticlein output;      output.pos = input.pos;     output.color = input.color;     output.radius = 5.0;      return output; }  [maxvertexcount(4)] void gsparticlemain(point gsparticlein input[1], inout trianglestream<psparticlein> spritestream) {     psparticlein output = (psparticlein)0;      [unroll]     for(int = 0; < 4; i++)     {         float3 position = positions[i] * input[0].radius;         position = mul(position, (float3x3)invview) + input[0].pos;         output.pos = mul(float4(position, 1.0), modelviewprojection);         output.eyepos = mul(float4(position, 1.0), modelview).xyz;          output.color = input[0].color;         output.tex = texcoords[i];         output.radius = input[0].radius;          spritestream.append(output);     }     spritestream.restartstrip(); }  psparticleout psparticlemain(psparticlein input) {     psparticleout output;      float3 norm;     norm.xy = (input.tex * 2.0) - 1.0;      float sqrad = dot(norm.xy, norm.xy);     if(sqrad > 1.0) discard;     norm.z = -sqrt(1.0 - sqrad);      float4 pixelpos = float4(input.eyepos + (norm * input.radius), 1.0);     float4 clspace = mul(pixelpos, projection);     float diffuse = max(0.0, dot(norm, lightdirection));      output.depth = clspace.z / clspace.w;      output.color = diffuse * input.color;      return output; } /* * * * * * * * * * * * * *  * technique declarations  *  * * * * * * * * * * * * * */ technique11 renderparticles {     pass p0     {         setvertexshader(compileshader(vs_5_0, vsparticlemain()));         setgeometryshader(compileshader(gs_5_0, gsparticlemain()));         setpixelshader(compileshader(ps_5_0, psparticlemain()));          setblendstate(noblending, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xffffffff);         setdepthstencilstate(enabledepth, 0);     } } 

the intent of shader operate on point list of colored vertices, expanding each vertex billboarded "impostor" sphere using geometry shader , writing final scene render target while writing adjusted depth (the eye-space depth offset "sphere" normal) of each pixel depth buffer. currently, configuration does render scene correctly in following image.

http://i.imgur.com/2sq6228.png

however, depth buffer never written , when inspected in graphics debugger, remains solid white (1.0). since believe fault in code may lie in way matrices constructed or passed shader, following represents contents of matrix constant buffer during sample draw call, reference:

inverse view 0   [0x00000000-0x0000000f] |   {      +0.9993909  +6.102026e-009     +0.03489951  +2.132527e-013} 1   [0x00000010-0x0000001f] |   { +7.1054282e-015              +1 -1.7484578e-007  +2.348344e-012} 2   [0x00000020-0x0000002f] |   {    -0.034899514 +1.7473927e-007     +0.99939084      -200.00002} 3   [0x00000030-0x0000003f] |   {              +0              +0              +0              +1}  model view 4   [0x00000040-0x0000004f] |   {     +0.99939078 +7.1054269e-015     -0.03489951      -6.9799023} 5   [0x00000050-0x0000005f] |   { +6.1020251e-009     +0.99999994 +1.7473926e-007 +3.4947851e-005} 6   [0x00000060-0x0000006f] |   {    +0.034899514 -1.7484578e-007     +0.99939084      +199.87817} 7   [0x00000070-0x0000007f] |   {              +0              +0              +0              +1}  projection 8   [0x00000080-0x0000008f] |   {      +2.0606079              +0              +0              +0} 9   [0x00000090-0x0000009f] |   {              +0      +2.7474773              +0              +0} 10  [0x000000a0-0x000000af] |   {              +0              +0         +1.0001        -0.10001} 11  [0x000000b0-0x000000bf] |   {              +0              +0              +1              +0}  model view projection 12  [0x000000c0-0x000000cf] |   {      +2.0593526 +1.4641498e-014    -0.071914211      -14.382842} 13  [0x000000d0-0x000000df] |   { +1.6765176e-008      +2.7474771 +4.8009213e-007 +9.6018426e-005} 14  [0x000000e0-0x000000ef] |   {    +0.034903005 -1.7486327e-007      +0.9994908      +199.79816} 15  [0x000000f0-0x000000ff] |   {    +0.034899514 -1.7484578e-007     +0.99939084      +199.87817} 

what know

  • by using visual studio 2012's graphics debugger, able confirm depth buffer bound correctly , may drawn correctly pixel shader. confirmed assigning output.depth random float in range [0, 1].

  • my view matrix generated slimdx.matrix.lookatlh() function in following snippet:

    private matrix createview() {     matrix rotmatrix;     var = vector3.unity;     var = looktarget;     var rot = rotation * ((float)math.pi / 180.0f);      matrix.rotationyawpitchroll(rot.y, rot.x, rot.z, out rotmatrix);     vector3.transformcoordinate(ref look, ref rotmatrix, out look);     vector3.transformcoordinate(ref up, ref rotmatrix, out up);     return matrix.lookatlh(position, position + look, up); } 
  • my projection matrix generated slimdx.matrix.perspectivefovlh() in following snippet:

    public camera(viewport viewport) {     var aspect = viewport.width / viewport.height;     var fov = 40.0f * ((float)math.pi / 180.0f);     projectionmatrix = matrix.perspectivefovlh(fov, aspect, 0.1f, 1000.0f); } 
  • my model matrix identity matrix , omitted wherever appear.

  • using graphical debugger able step though pixel shader point clip space depth calculated. before shader attempts divide clipspace.z clipspace.w, shader locals this:

    http://i.imgur.com/xogniyd.png

    this arbitrarily selected pixel though every pixel yields similar results clspace vector. can see, clspace.z , clspace.w similar in magnitude division results in ~1.

what i've tried

  • transposing matrices before uploading them device. did nothing cause distortion expect result of projection being inverted, suggested me pre-transposing matrices unnecessary slimdx's effect framework. (this suspicion later confirmed, slimdx's effect framework automatically transposes matrices set effect variables.)

  • transposing matrices implicitly adding column/row-major matrix packing flags when compiling effect. reversing multiplication order of vectors , matrices wherever appeared in shader. these misguided attempts @ addressing thought column/row-major issue.

  • using right-handed projection , view matrices opposed left-handed ones. no effect expected inversion of axes.

  • using number of different near , far projection parameters. had expected effect on near , far clipping distance though did nothing solve depth issue.

i've exhausted every available resource in trying track down whatever causing issue. i've run through every possible permutation of matrices, operand order , state settings can fathom , referred countless msdn articles , questions nothing seems apply. appreciate issue!

your depth buffer has same value written because have projection matrix wrong. value gets written w-value need juggle matrix around bit.

the directx documentation gives explanation of perspective transform.

basically matrix should follows

w, 0, 0, 0 0, h, 0, 0 0, 0, q, 1 0, 0, p, 0 

where

w = 1.0f / tanf( fovhoriz / 2 ); h = 1.0f / tanf( fovvert  / 2 ); q = zfar / (zfar - znear); p = -q * znear; 

Comments

Popular posts from this blog

jquery - How can I dynamically add a browser tab? -

node.js - Getting the socket id,user id pair of a logged in user(s) -

keyboard - C++ GetAsyncKeyState alternative -