🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

How to use GS for shadowmap generation(CSM)?

Started by
7 comments, last by ddlox 3 years, 8 months ago

I'm following https://www.ea.com/frostbite/news/shadows-decals-d3d10-techniques-from-frostbite​ The slide also gives the hlsl code. But the problem is CPU side coding. can anyone tell me how to do that?

Advertisement

that link leads to a 404

@ddlox Now its working

ok u will need to learn how to use a geomshader:

https://takinginitiative.wordpress.com/2011/01/12/directx10-tutorial-9-the-geometry-shader/

or this

https://www.braynzarsoft.net/viewtutorial/q16390-36-billboarding-geometry-shader

then u can modify these apps to do csm (u can pass yr data and cascade in the shader); i assume that u know the theory behind csm, if not, here is a good guide:

http://ogldev.atspace.co.uk/www/tutorial49/tutorial49.html

bear in mind that the frostbite version is not what you're going to end up with at first, but u will definitely gain cpu speed but at first it is likely that u will be gpu bound. U will need to transfer your culler data to the geomshader but I'll let u optimise it ?

That's it … all the best ?

i was asking how to do a shadowmap generation(3 cascades) using a geometry shader.

previous answer updated

I currently create shadow map textures separately (3 cascade - 3 textures) When I render the depth for 3 cascades I do the following.

descTex2D.MiscFlags = 0;
if (SUCCEEDED(hr = RE_D3D11_Device->CreateTexture2D(&descTex2D, NULL, &RE_D3D11_CSM[0])))
{
	D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
	SecureZeroMemory(&dsvDesc, sizeof(dsvDesc));
	dsvDesc.Flags = 0;
	dsvDesc.Format = DXGI_FORMAT_D32_FLOAT;
	dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
	dsvDesc.Texture2D.MipSlice = 0;
	if (SUCCEEDED(hr = RE_D3D11_Device->CreateDepthStencilView(RE_D3D11_CSM[0], &dsvDesc, &RE_D3D11_CSM_DSV[0])))
	{
		D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
		SecureZeroMemory(&srvDesc, sizeof(srvDesc));
		srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
		srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
		srvDesc.Texture2D.MipLevels = descTex2D.MipLevels;
		srvDesc.Texture2D.MostDetailedMip = 0;
		if (SUCCEEDED(hr = RE_D3D11_Device->CreateShaderResourceView(RE_D3D11_CSM[0], &srvDesc, &RE_D3D11_CSM_SRV[0])))
		{
			RE_D3D11_CSM_VP[0].TopLeftX = RE_D3D11_CSM_VP[0].TopLeftY = 0;
			RE_D3D11_CSM_VP[0].Height = 4096;
			RE_D3D11_CSM_VP[0].Width = 4096;
			RE_D3D11_CSM_VP[0].MinDepth = 0.0f;
			RE_D3D11_CSM_VP[0].MaxDepth = 1.0f;
		}
	}
}
D3D11_TEXTURE2D_DESC descTex2D;
SecureZeroMemory(&descTex2D, sizeof(descTex2D));
descTex2D.Usage = D3D11_USAGE_DEFAULT;
descTex2D.Format = DXGI_FORMAT_R32_TYPELESS;
descTex2D.Width = 3072
descTex2D.Height = 3072;
descTex2D.SampleDesc.Count = 1;
descTex2D.SampleDesc.Quality = 0;
descTex2D.MipLevels = 1;
descTex2D.ArraySize = 1;
descTex2D.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
descTex2D.CPUAccessFlags = 0;
descTex2D.MiscFlags = 0;
if (SUCCEEDED(hr = RE_D3D11_Device->CreateTexture2D(&descTex2D, NULL, &RE_D3D11_CSM[1])))
{
	D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
	SecureZeroMemory(&dsvDesc, sizeof(dsvDesc));
	dsvDesc.Flags = 0;
	dsvDesc.Format = DXGI_FORMAT_D32_FLOAT;
	dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
	dsvDesc.Texture2D.MipSlice = 0;
	if (SUCCEEDED(hr = RE_D3D11_Device->CreateDepthStencilView(RE_D3D11_CSM[1], &dsvDesc, &RE_D3D11_CSM_DSV[1])))
	{
		D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
		SecureZeroMemory(&srvDesc, sizeof(srvDesc));
		srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
		srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
		srvDesc.Texture2D.MipLevels = descTex2D.MipLevels;
		srvDesc.Texture2D.MostDetailedMip = 0;
		if (SUCCEEDED(hr = RE_D3D11_Device->CreateShaderResourceView(RE_D3D11_CSM[1], &srvDesc, &RE_D3D11_CSM_SRV[1])))
		{
			RE_D3D11_CSM_VP[1].TopLeftX = RE_D3D11_CSM_VP[1].TopLeftY = 0;
			RE_D3D11_CSM_VP[1].Height = 3072;
			RE_D3D11_CSM_VP[1].Width = 3072;
			RE_D3D11_CSM_VP[1].MinDepth = 0.0f;
			RE_D3D11_CSM_VP[1].MaxDepth = 1.0f;
		}
	}
}
etc...
		for (int i=0; i<3; i++)
		{
			RE_D3D11_ImmediateContext->RSSetViewports(1, &RE_D3D11_CSM_VP[i]);

			RE_D3D11_ImmediateContext->OMSetRenderTargets(0, &NULLRTV, RE_D3D11_CSM_DSV[i]);
			RE_D3D11_ImmediateContext->ClearDepthStencilView(RE_D3D11_CSM_DSV[i], D3D11_CLEAR_DEPTH, 1.0f, 0);

			mytest->CSM_GetLightViewProjection(i, mycam, RE_LightDirection, mLightViewProjection[i]);
			mytest->DrawCSM(RE_D3D11_ImmediateContext, RE_D3D11_SamplerState_Main, XMMatrixIdentity());

			RE_D3D11_ImmediateContext->OMSetRenderTargets(0, &NULLRTV, NULLDSV);

		}

I just want to know how to create the shadowmap texture(Is it a single one or separate 3 textures) for geometry shader single pass shadowmap generation. I have a little understanding about GS. What I cant understand is the CPU side coding parts(how to set viewports, render targets). Is it the same for my prev implementation? Take a peek at the below

I just want to know how to create the shadowmap texture(Is it a single one or separate 3 textures)

it is 1 texture with all 3 in it ?

shadowmapTexture is a texture array i.e. it is the same type as one of your RE_D3D11_CSM[i];

sliceCount is the number of textures that shadowmapTexture was initialised with;

so in your case sliceCount is 3;

view is the same type of as one of your RE_D3D11_CSM_DSV[i];

and it is this view that you pass to the shader;

so essentially you need these 3 variables 1 shadowmapTexture using CreateTexture2D with empty textures but , 1 slicecount, and 1 view:

// pseudo

******
STEP 1
******

std::vector<byte*> maps; 

// create 3 empties and fill with 0s
// make sure that u use the correct byte count to match the GS, i leave that to u as an exercise to find out
maps[0] to [2] = new byte[ width x height ] 

std::vector<D3D_subresource_data> initialdata;
i = 0
for (auto m : maps)
{
	D3D11_SUBRESOURCE_DATA srd;
	srd.pSysMem = maps[i++]
	srd....  // fill init data appropriately 
 
  	initialdata.emplace_back(srd)
}

D3D11_TEXTURE2D_DESC desc;
desc.BindFlags = ..BIND_SHADER_RESOURCE | ..BIND_RENDER_TARGET // please check properly one or both
sliceCount = desc.ArraySize = maps.size() 
desc....  // fill the rest appropriately 

ID3D11Txture* shadowmapTexture = nullptr
CreateTexture2D(desc, initialdata.data(), &shadowmapTexture)

ID3D11ShaderResourceView* view = nullptr;
********************************************************************
STEP 2 now create the texture array view like on the slide you show
********************************************************************

Step 3 pass to shader

Step 4 remove your for-loop from the c++ as it will be done for you in the gs

Step 5 call shader

I have already given u some links to see how to pass these as input to the geom shader. If u don't know how the geomshader works than honestly speaking you should not use it until you learn how to. It's like trying to drive a lorry without proper lessons, right ?

ok so i've done this from the top of my head, please tidy up and that should get u going.

That's it, u have all u need now … all the best ?

This topic is closed to new replies.

Advertisement