DirectX 11 学习笔记-Part2-5【Cubemap/贴图置换/阴影/屏幕空间环境光遮蔽】【代码篇】

代码已上传至GitHub,这部分对应的项目为NormalDisplacementSsao。运行项目时可以使用数字键1-3切换渲染的shader,另外按下z键可以看到SSAO生成的遮罩贴图。这篇文章主要结合代码介绍渲染的流程(对应代码中的NDSsaoApp::DrawScene)。Shadow Map首先我们要渲染阴影深度图,看ShadowMap的定义class ShadowMap...
摘要由CSDN通过智能技术生成

代码已上传至GitHub,这部分对应的项目为NormalDisplacementSsao。运行项目时可以使用数字键1-3切换渲染的shader,另外按下z键可以看到SSAO生成的遮罩贴图。

这篇文章主要结合代码介绍渲染的流程(对应代码中的NDSsaoApp::DrawScene)。

Shadow Map

首先我们要渲染阴影深度图,看ShadowMap的定义

class ShadowMap
{
    ... ...
	ID3D11ShaderResourceView* mDepthMapSRV;
	ID3D11DepthStencilView* mDepthMapDSV;

	D3D11_VIEWPORT mViewport;
};

因为生成的深度图,既要作为管线的输出,也要作为着色器的输入,所以创建的2D纹理需要同时有ID3D11ShaderResourceView和ID3D11DepthStencilView。另外ShadowMap中定义了自己的Viewport,可以渲染出自己需要的大小的纹理。

纹理创建的过程和一般的模板深度纹理相同,但是要注意BindFlags要同时包D3D11_BIND_DEPTH_STENCIL和D3D11_BIND_SHADER_RESOURCE。

绘制阴影深度图,第一步是要把ShadowMap中的DepthStencilView绑定到管线的输出阶段。

void ShadowMap::BindDsvAndSetNullRenderTarget(ID3D11DeviceContext* dc)
{
    dc->RSSetViewports(1, &mViewport);

	// Set null render target because we are only going to draw to depth buffer.
	// Setting a null render target will disable color writes.
    ID3D11RenderTargetView* renderTargets[1] = {0};
    dc->OMSetRenderTargets(1, renderTargets, mDepthMapDSV);
    
    dc->ClearDepthStencilView(mDepthMapDSV, D3D11_CLEAR_DEPTH, 1.0f, 0);
}

这里在设置RenderTarget时,使用了空的RenderTargetView,因为我们只需要绘制深度buffer不需要输出颜色。

设置好输出后,我们要向DepthStencilView中绘制深度信息。

前面说过,我们有三种绘制形式,普通绘制,NormalMap绘制和贴图置换绘制。前两种对生成的阴影形状没有影响,因此在这里可以归为一种,贴图置换由于会影响物体的表面,所以在绘制阴影时也要做贴图置换。

void NDSsaoApp::DrawSceneToShadowMap()
{
        //Setup Const buffer... ...

	if(mDrawOptions != RenderOptionsDisplacementMap)
	{
		md3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
		for(size_t i =0;i<mSceneObjects.size();++i)
		{
			mSceneObjects[i]->Draw(this,BuildShadowMapEffect::Ptr(),BuildShadowMapEffect::Ptr()->BuildShadowMapTech, 
				&mLightView, &mLightProj);
		}
	}
	else
	{
		md3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST);
		for(size_t i =0;i<mSceneObjects.size();++i)
		{
			mSceneObjects[i]->Draw(this,BuildShadowMapEffect::Ptr(),BuildShadowMapEffect::Ptr()->TessBuildShadowMapTech, 
				&mLightView, &mLightProj);
		}
	}


	// FX sets tessellation stages, but it does not disable them.  So do that here
	// to turn off tessellation.
	md3dImmediateContext->HSSetShader(0, 0, 0);
	md3dImmediateContext->DSSetShader(0, 0, 0);

	md3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);


	mSkullVertexState.Apply(md3dImmediateContext);
	mSkull.Draw(this,BuildShadowMapEffect::Ptr(),BuildShadowMapEffect::Ptr()->BuildShadowMapTech, &mLightView, &mLightProj);
}

绘制前要设置许多的变量,这部分请查看源码。我们先看不做贴图置换的情况,此时使用的是BuildShadowMapTech,对应到着色器代码中

RasterizerState Depth
{
	DepthBias = 100000;
    DepthBiasClamp = 0.0f;
	SlopeScaledDepthBias = 1.0f;
};
VertexOut VS(VertexIn vin)
{
	VertexOut vout;

	vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj);
	vout.Tex  = mul(float4(vin.Tex, 0.0f, 1.0f), gTexTransform).xy;

	return vout;
}
technique11 BuildShadowMapTech
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_5_0, VS() ) );
        SetGeometryShader( NULL );
        SetPixelShader( NULL );
        SetRasterizerState(Depth);
    }
}

我们不需要输出颜色只需要深度信息,因此我们只需要VertexShader。在Vertex Shader的输出中,SV_POSITION是必须的,因为光栅化阶段的裁剪还是会进行的,而且我们需要由它来计算深度信息,而TEXCOORD是不需要的,但是如果输出中只有一个SV_POSITION在编译shader时会报错。

贴图置换时的绘制过程同样也是不需要输出颜色的,因此可以不需要PS。

techni
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值