Sign in to follow this  
Plerion

Vertexshader - No z-test?

Recommended Posts

Hello! Im not yet really friend with vertexshaders but i try to get :P. I managed pixelshaders pretty well but vertexshaders give me odd behaviour! I use the following shader:
float3 position;
float radius;
float4x4 viewProj;

struct VertexInput
{
  float4 pos : POSITION0;
};

struct PixelInput
{
  float4 pos : POSITION0;
  float2 data : TEXCOORD0;
};

PixelInput VShader(VertexInput input)
{
  float dX = input.pos.x - position.x;
  float dZ = input.pos.z - position.z;
  
  float tot = dX * dX + dZ * dZ;
  tot = sqrt(tot);
  
  PixelInput ret = (PixelInput)0;
  ret.pos = mul(input.pos, viewProj);
  if(tot <= radius)
    ret.data.r = 1;
  else
    ret.data.r = 0;
    
  return ret;
}

float4 MyShader(PixelInput pInput) : COLOR0
{
  float4 c1, c2;
  c1.r = c1.g = c1.b = c1.a = 1.0;
  c2.r = c2.g = c2.a = 1.0;
  c2.b = 0.0;

  if(pInput.data.r > 0)
    return c1;
  else
    return c2;
}

technique EntryPoint
{
    pass p1
    {
        VertexShader = compile vs_2_0 VShader();
        PixelShader = compile ps_2_0 MyShader();
    }
}
But when i use this shader to draw some triangles there is no more depthtest. It just displays whats rendered last on a pixel. Why is that effect occuring? A i doing something wrong (i guess)? Greetings Cromon

Share this post


Link to post
Share on other sites
Hello!

Yes, its enabled:

void Render()
{
g_Device->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
g_Device->Clear(0, 0, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
g_Device->BeginScene();

g_Device->SetTransform(D3DTS_PROJECTION, &matProj);
g_Device->SetTransform(D3DTS_VIEW, &matView);

g_Device->SetRenderState(D3DRS_LIGHTING, FALSE);
g_Device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
g_Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

UINT nPasses = 0;
g_Effect->Begin(&nPasses, 0);

for(UINT i = 0; i < nPasses; ++i)
{
g_Effect->BeginPass(i);
g_Device->SetFVF(Vertex::FVF);
g_Device->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 3, vertices, Vertex::stride);
g_Effect->EndPass();
}

g_Effect->End();

g_Device->EndScene();
g_Device->Present(0, 0, 0, 0);
}

Share this post


Link to post
Share on other sites
What about turning on Z writing, so the depth buffer actually gets updated (D3DRS_ZWRITEENABLE) ? I don't know if it's on by default

Capturing this in a gpu debugger will show you exactly what render states are active and would be more useful to debug

Share this post


Link to post
Share on other sites

The next question is going to be how are you sure that this is a depth test issue? Screenshots might help.

Also - is it guaranteed that the positions in your vertex stream are all 4 components and the W component of all of them is 1.0? Most people send a float3 position into the vert shader and create the float4 as float4( pos, 1.0f )

Share this post


Link to post
Share on other sites
Yes, its turned on, but it has no effect. I depends on the order of my vertices what gets rendered! Thats how they look:

Vertex vertices[] =
{
{ -5.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(255, 0, 0) },
{ 5.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(255, 0, 0) },
{ 0.0f, -3.0f, 0.0f, D3DCOLOR_XRGB(255, 0, 0) },

{ -5.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(255, 255, 0) },
{ 5.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(255, 255, 0) },
{ 0.0f, 3.0f, 0.0f, D3DCOLOR_XRGB(255, 255, 0) },

{ -5.0f, 0.0f, -2.0f, D3DCOLOR_XRGB(255, 255, 255) },
{ 5.0f, 0.0f, -2.0f, D3DCOLOR_XRGB(255, 255, 255) },
{ 0.0f, 3.0f, -2.0f, D3DCOLOR_XRGB(255, 255, 255) },
};


So now the last triangle is on the top even if it has a z-value of -2. If i set the lower 3 vertices to the top its behind the other 2 as it should be.

Share this post


Link to post
Share on other sites
Screenshots here:
With shader and triangle with -2.0f as the last:
http://www.imagr.eu/up/4b37d3499db0e_wsh.JPG

Without shader and the triangle with -2.0f (the white) as the last:
http://www.imagr.eu/up/4b37d36512a6a_osh1.JPG

Without shader and the triangle with -2.0f (the white) as the first:
http://www.imagr.eu/up/4b37d3a0815b2_osh2.JPG

With shader and the triangle with -2.0f as the first:
http://www.imagr.eu/up/4b37d3d1582dd_wsh2.JPG

Share this post


Link to post
Share on other sites
Yeah I'm pretty sure it does

Oh, you know I overlooked something more obvious:

g_Device->SetTransform(D3DTS_PROJECTION, &matProj);
g_Device->SetTransform(D3DTS_VIEW, &matView);

This isn't going to set your shader's "viewProj" variable. That looks like old fixed-function junk

Share this post


Link to post
Share on other sites
Hey! I found the error. I wanted to correct zNear from 10.0f to 1.0f and accidentally wrote 0.0f. Set it to 1.0f and now it works.

I use the old transformations because i will also render things that dont get "shadered".

Share this post


Link to post
Share on other sites
yes, the variables get set ofc

D3DXMATRIX viewProj;
viewProj = matView * matProj;
g_Effect->SetMatrix("viewProj", &viewProj);


Ok. Now the depth works but actually i want to achieve another result. I want to get the parts of the triangle that are within a certain radius of a point to be colored white and the others to be colored yellow. Now there is a problem: If only one of the three vertices is within the range of the point the whole triangle gets colored white. And thats why the two triangles in the front are white even if only one vertex is within the range
{ 0.0f, 3.0f, 0.0f, D3DCOLOR_XRGB(255, 255, 0) },

this one has x and z distance 0 (because i set the point to 0, 0, 0) and i dont care about y distance. And because of this vertex the whole triangle now is white.

Share this post


Link to post
Share on other sites
To me it looks like you never assign the viewProj matrix, which could mean its default value is identity which would probably be whatever default projection mode your vid driver is using, like orthographic 2D?

in your .FX file, try changing float4x4 viewProj; to float4x4 viewProj : WORLDVIEWPROJ;

Unfortunately, i'm not a D3D developer, but my memory seems to recall that is how you tell the FX framework to track matrices?

-Danu
[EDIT: ooops, bit late...]

Share this post


Link to post
Share on other sites
Probably best to do that test per-pixel. I also assume you want this comparison done in world space, so send the world space position to the pixel shader and you can get the distance between two points as

float d = length( pointA - pointB );

where pointA and pointB are float3

edit: oh, if you don't care about Y distance then they can be float2

Share this post


Link to post
Share on other sites
Ok, that was what i wanted to do, yes, but how do i give the position to the pixelshader? i have
struct PixelInput
{
float4 pos : POSITION0;
float2 data : TEXCOORD0;
};

but i cannot use pos in the pixelshader else i get an error while compiling the shader.

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

Sign in to follow this