[DirectX]Programming.Role.Playing.Games:02_01 Draw2D

    Programming.Role.Playing.Games.with.DirectX第2章开始介绍坐标系,矩阵和向量一些数学概念,每本dx书都是必备的吗?这些就没什么好说的,直接来第一个工程,就是Draw2D,书是用固定管线来实现的,因此没什么难度,刚好自己有学过一点Shader,就用Shader也实现了一遍。就如上图,左边的就是用固定管线实现的,右边是用Shader实现的

    我用的框架是之前学习dx11的,也就是这个网站(http://www.rastertek.com/tutdx11.html)上的,封装的比较好,dx的初始化就在D3DClass内中,window的初始化在SystemClass中。这些都是基础,也没什么好讲的,就跳过。吐槽下,总感觉跨度有点大,如果是dx新手的话,而且还是英文版,上手有点难啊,直接上顶点缓存,贴图加载等。

    来看下代码:

    固定管线渲染:

void ModelClass::Render(IDirect3DDevice9* device, D3DXMATRIX worldMatrix, D3DXMATRIX viewMatrix, D3DXMATRIX projectionMatrix) 
{
	device->SetTexture(0, m_texture->GetTexture());

	device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
	device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
	device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);

	device->SetStreamSource(0, m_vertexBuffer, 0, sizeof(VertexType));
	device->SetFVF(VERTEX_FVF);

	device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

	device->SetTexture(0, nullptr);
}

    SetTexture表面要是用那张贴图来进行纹理映射,SetSamplerState是设置纹理过滤器,SetStreamSource就是把顶点缓存与渲染流水线关联,SetFVF是告诉流水线什么顶点格式。其实也有个类似的函数SetVertexDeclaration。DrawPrimitive就是绘制的函数了,D3DPT_TRIANGLESTRIP是三角带(一时忘了叫什么来着)的意思,前3个顶点构成1个三角面,接着下一个顶点和前2个顶点再构成一个三角面。这些函数网上都可以查到详细的资料。

    接下来的就是Shader的,因为顶点是D3DFVF_XYZRHW,之前还真没有用到过,网上查了下,RHW是D3D里面的一种顶点格式,是一种自带视图、投影、世界等变换和光线计算等处理的顶点格式,而且这些处理我们无法用SetTransform等进行的转换。我就认为在顶点着色器阶段对顶点的处理是无效的。然后经测试,使用RHW的话,在顶点着色器阶段对顶点的处理是无效的

    Shader渲染代码:

void ShaderModelClass::Render(IDirect3DDevice9* device, D3DXMATRIX worldMatrix, D3DXMATRIX viewMatrix, D3DXMATRIX projectionMatrix)
{
	bool result;
	UINT passMaxNum;
	float time;

	time = (float)::timeGetTime() / 1000.0f;

	device->SetStreamSource(0, m_vertexBuffer, 0, sizeof(VertexType));
	device->SetFVF(VERTEX_FVF);

	result = m_colorShader->Render(device, m_texture->GetTexture(), time);
	if (!result)
		return;

	m_colorShader->GetEffect()->Begin(&passMaxNum, 0);
	for (UINT pass = 0; pass < passMaxNum; ++pass)
	{
		m_colorShader->GetEffect()->BeginPass(pass);
		device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
		m_colorShader->GetEffect()->EndPass();
	}
	m_colorShader->GetEffect()->End();
}

    这里用的是effect框架,比单独写vertexshader和pixelshader快,而且没有vertexshader和pixelshader的问题,这个我之前有说过。注意下,这里时间是用来做上图的渐变效果的。    

    接下来Shader:

texture modelTexture;
float time;

sampler ModelTextureSampler = sampler_state
{
	Texture = <modelTexture>;
	MipFilter = POINT;
	MinFilter = POINT;
	MagFilter = POINT;
	//MipFilter = LINEAR;
	//MinFilter = LINEAR;
	//MagFilter = LINEAR;
	//MipFilter = ANISOTROPIC;
	//MinFilter = ANISOTROPIC;
	//MagFilter = ANISOTROPIC;
};

struct VertexInputType
{
	float4 vertex : POSITION;
	float2 texcoord : TEXCOORD0;
};

struct PixelInputType
{
	float4 pos : POSITION;
	float2 texcoord : TEXCOORD0;
};

PixelInputType ColorVertexShader(VertexInputType input)
{
	PixelInputType output;

	output.pos = input.vertex;//可以在这里随意修改顶点,会发现对结果没有任何影响
	output.texcoord = input.texcoord;

	return output;
}

float4 ColorPixelShader(PixelInputType input) : COLOR
{
	float param = max(0.5, cos(time));//利用传过来的时间和cos函数进行变化,来实现渐变效果,用来和左边的固定管线渲染的区分
	float4 color = tex2D(ModelTextureSampler, input.texcoord) * param;

	return color;
}

technique ColorTechnique
{
	pass pass0
	{
		VertexShader = compile vs_2_0 ColorVertexShader();
		PixelShader = compile ps_2_0 ColorPixelShader();
	}
}

    这么一看,Shader的代码也很简单,也没什么说的,具体的看完整源码。

    一些配置这边说下,

    CharacterSet是Unicode, dx9sdk的配置,最重要的是C/C++中Language选项的ConformanceMode设置为No,不然TCHAR*不能转为LPCWSTR,这个我到现在还不知道原因。

源码下载:下载地址

猜你喜欢

转载自blog.csdn.net/zp288105109a/article/details/80860702
今日推荐