Jump to content
  • Advertisement
Sign in to follow this  
Medo Mex

Getting Pixel Depth

This topic is 2194 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Well I wouldn't consider it a 'cost', as it will enable you to draw the scene just once. (Well, not in a project, but for the normal, depth, position, etc... information)

 

I suggest that you try the suggested method, and then after we can optimize.

Share this post


Link to post
Share on other sites
Advertisement

I did the following, now I'm getting a black screen:

void render()
{
IDirect3DSurface9*  oldBB;
device->GetRenderTarget(0, &oldBB);

device->SetRenderTarget(0, DepthSurface);
device->SetRenderTarget(1, ColorSurface);

// -- Render the scene
HRESULT hr = device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
assert(SUCCEEDED(hr));

device->BeginScene();

RenderScene();

device->SetRenderTarget(0, oldBB);
device->SetRenderTarget(1, NULL);
oldBB->Release();

d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);
}

Share this post


Link to post
Share on other sites

If i understood d3d process correctly :

When you create the device there is a "main" backbuffer surface created for you implicitly so at last "step" you need to draw to that surface to be able to see something on screen:

void render()
{
IDirect3DSurface9*  oldBB;
device->GetRenderTarget(0, &oldBB); // grabs the last render target, and it happens to be main (backbuffer) since there is nothing set before

device->SetRenderTarget(0, DepthSurface);
device->SetRenderTarget(1, ColorSurface);

// -- Render the scene
HRESULT hr = device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
assert(SUCCEEDED(hr));

device->BeginScene();

RenderScene();

device->SetRenderTarget(0, oldBB); // backbuffer is set
device->SetRenderTarget(1, NULL);
oldBB->Release();
 
DrawSomethingThatUsesDepthAndColorTextureToBackbuffer();

d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL); // "presents" content of the backbuffer to the screen
}


So that means I will have to return depth, color and normal with each Pixel Shader?

It is up you how many RTs you need, what do you want to store in them and when to switch to other RT...

Edited by belfegor

Share this post


Link to post
Share on other sites

@belfegor: There is something confuse me, I have already drawn everything when I called RenderScene();

 

Now what should I do in DrawSomethingThatUsesDepthAndColorTextureToBackbuffer()? Should I render the scene again?

Share this post


Link to post
Share on other sites

Drawing a so-called fullscreen quad with that color render target as texture. Alternatively, switch that color and "depth" rendertarget, so that the color goes to your normal backbuffer - again.

 

You're now actually close to what is called deferred rendering so you might wanna read about that.

Share this post


Link to post
Share on other sites
I have 2 problems:
 
1. I'm using D3DXSaveTextureToFile() in order to try to save the texture to the hard drive for testing purpose, the following line save a screenshot of the window:
HRESULT hr = D3DXSaveTextureToFile("depth.png", D3DXIFF_PNG, DepthTex, NULL);
 
The following line save pure black image file:
HRESULT hr = D3DXSaveTextureToFile("depth.png", D3DXIFF_PNG, ColorTex, NULL);
 
I think the first line should save the depth texture?
 
2. I tried switching between depth and color so I can see the scene as "unbird" suggested, but I see a black screen instead:
IDirect3DSurface9*  oldBB; // "old" backbuffer surface
device->GetRenderTarget(0, &oldBB); // store it, increments ref count

device->SetRenderTarget(0, DepthSurface);
device->SetRenderTarget(1, ColorSurface);

HRESULT hr = device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
assert(SUCCEEDED(hr));

device->BeginScene();

// Draw everything
RenderScene();

device->EndScene();

device->SetRenderTarget(0, ColorSurface); // *** Switch to color surface ***
device->SetRenderTarget(1, NULL);
oldBB->Release(); // decrement ref count

device->Present(NULL, NULL, NULL, NULL);

Share this post


Link to post
Share on other sites
OMG Medo, you still don't get it. I don't know how to simplify it more.
 

There is something confuse me, I have already drawn everything when I called RenderScene();

Yes but you draw it to these surfaces:
 

void Render()
{
...
device->SetRenderTarget(0, DepthSurface);
device->SetRenderTarget(1, ColorSurface);

// -- Render the scene
HRESULT hr = device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
assert(SUCCEEDED(hr));

device->BeginScene();
 
RenderScene();
...
}

every draw call draws to the last render target set by SetRenderTarget function, but backbuffer surface is still empty so there is nothing to display on screen.
 

HRESULT hr = D3DXSaveTextureToFile("depth.png", D3DXIFF_PNG, DepthTex, NULL);

Be careful with this function:
1. Dont call it when texture you are about to save has its surface still bound as render target
2. Note the format of the texture you are about the save, as far as i know PNG cannot hold floating point texture, so better to use DDS as it is far more capable.
 

device->SetRenderTarget(0, ColorSurface); // *** Switch to color surface ***

This is not backbuffer surface so still nothing to display on screen!

Unbird suggested to draw "fullscreen quad" as last step.

EDIT:
Since i doubt that you will find decent tutorial for "fullscreen quad", and i wish that someone helped me at beginning like i do for you now, here is simple example to play with:
cpp
class FSQuad
{
private:
	LPDIRECT3DDEVICE9            device;
	LPDIRECT3DVERTEXBUFFER9      vBuffer;
	LPDIRECT3DINDEXBUFFER9       iBuffer;
	LPDIRECT3DVERTEXDECLARATION9 vDeclaration;

	struct FS_VERTEX
	{
		D3DXVECTOR3 position;
		D3DXVECTOR2 texcoord;
	};

public:

	FSQuad(LPDIRECT3DDEVICE9 _device)
		: device(_device), iBuffer(nullptr), vBuffer(nullptr), vDeclaration(nullptr)
	{
		device->AddRef();
	}

	~FSQuad()
	{
		if(nullptr != device)
		{
			device->Release();
			device = nullptr;
		}

		if(nullptr != iBuffer)
		{
			iBuffer->Release();
			iBuffer = nullptr;
		}

		if(nullptr != vBuffer)
		{
			vBuffer->Release();
			vBuffer = nullptr;
		}

		if(nullptr != vDeclaration)
		{
			vDeclaration->Release();
			vDeclaration = nullptr;
		}
	}

	bool init()
	{
		D3DVERTEXELEMENT9 fsVertexElements[] =
		{
			{0, 0,  D3DDECLTYPE_FLOAT3,  D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
			{0, 12, D3DDECLTYPE_FLOAT2,  D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
			D3DDECL_END()
		};

		HRESULT hr = D3D_OK;
		hr = device->CreateVertexBuffer(sizeof(FS_VERTEX) * 4, D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &vBuffer, nullptr);
		if(FAILED(hr))
		{
			MessageBox(0, "Failed to create FS VB!", 0, 0);
			return false;
		}

		hr = device->CreateIndexBuffer(sizeof(USHORT) * 6, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &iBuffer, nullptr);
		if(FAILED(hr))
		{
			MessageBox(0, "Failed to create FS IB!", 0, 0);
			return false;
		}

		hr = device->CreateVertexDeclaration(fsVertexElements, &vDeclaration);
		if(FAILED(hr))
		{
			MessageBox(0, "Failed to create FS VD!", 0, 0);
			return false;
		}

		float c = 1.0f;
		float z = 1.0f;
		FS_VERTEX* pVertices = nullptr;
		vBuffer->Lock(0, 0, (void**)&pVertices, 0);
		pVertices[0].position = D3DXVECTOR3( -c,  c,  z); pVertices[0].texcoord = D3DXVECTOR2(0.0f, 0.0f);
		pVertices[1].position = D3DXVECTOR3(  c,  c,  z); pVertices[1].texcoord = D3DXVECTOR2(1.0f, 0.0f);
		pVertices[2].position = D3DXVECTOR3(  c, -c,  z); pVertices[2].texcoord = D3DXVECTOR2(1.0f, 1.0f);
		pVertices[3].position = D3DXVECTOR3( -c, -c,  z); pVertices[3].texcoord = D3DXVECTOR2(0.0f, 1.0f);
		vBuffer->Unlock();

		USHORT* pIndices = nullptr;
		iBuffer->Lock(0, 0, (void**)&pIndices, 0);
		pIndices[0]       = 0;
		pIndices[1]       = 1;
		pIndices[2]       = 2;
		pIndices[3]       = 0;
		pIndices[4]       = 2;
		pIndices[5]       = 3;
		iBuffer->Unlock();

		return true;
	}

	void draw()
	{
		device->SetStreamSource(0, vBuffer, 0, sizeof(FS_VERTEX));
		device->SetIndices(iBuffer);
		device->SetVertexDeclaration(vDeclaration);
		device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2);
	}
};
then you have shader like this, here you could use your depth & color texture:
float4 ScreenParams; // xy width/height of screen

struct VERTEX
{
	float3 Position  : POSITION;
	float2 TexCoord0 : TEXCOORD0;
};

struct VS_OUTPUT
{
	float4 Position  : POSITION;
	float2 TexCoord0 : TEXCOORD0;
};

struct PS_OUTPUT
{
    float4 Color : COLOR0;
};

void VertexProgram(in VERTEX IN, out VS_OUTPUT OUT)
{
	float2 texelOffset = float2(-1.0f / ScreenParams.x, 1.0f / ScreenParams.y);
	float2 result      = IN.Position.xy;
    result.xy         += texelOffset;
	OUT.Position.x     = result.x;
	OUT.Position.y     = result.y;
	OUT.Position.z     = 1.0f;
	OUT.Position.w     = 1.0f;
	OUT.TexCoord0      = float2(0.5f, -0.5f) * IN.Position.xy + 0.5f.xx;
}

void PixelProgram(in VS_OUTPUT IN, out PS_OUTPUT OUT)
{
    ...
    OUT.Color = ...;
}
Edited by belfegor

Share this post


Link to post
Share on other sites

I'm still getting a window screenshot when I execute this line:

HRESULT hr = D3DXSaveTextureToFile("depth.dds", D3DXIFF_DDS, DepthTex, NULL);

It seems that the render target "DepthTex" is getting color instead of depth map.

Edited by Medo3337

Share this post


Link to post
Share on other sites

1. Where do you call it?

2. Does the camera look at something "useful" at the time when you take the screenshot?

3. What is stored in DepthTex?

Share this post


Link to post
Share on other sites

1. I'm calling it after device->Present()

 

2. The camera is looking at far and close mountains, so I think that's a good scene

 

3. I'm getting a screenshot of the scene instead of the depth texture

 

I'm sure that D3D9 is writing color to the first render target instead of depth map.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!