DirectX 12 版 俄罗斯方块

原理跟WPF版本的差不多,只是渲染的底层逻辑都要自己写。
UI部分使用了Direct2D和DirextWrite实现。

4月19日更新
增加复杂模型的渲染
复杂模型

//部分实现代码
	m_device->GetWrappedDevice()->AcquireWrappedResources(m_device->GetWrappedBackBuffer().GetAddressOf(), 1);
	m_device->GetD2DContext()->SetTarget(m_device->GetD2DRenderTarget());
	ID2D1SolidColorBrush* pWhiteBrush = NULL;
	HRESULT hr = m_device->GetD2DContext()->CreateSolidColorBrush(D2D1::ColorF(1, 1, 1, 0.6), &pWhiteBrush);
	ID2D1SolidColorBrush* pBlackBrush = NULL;
	hr = m_device->GetD2DContext()->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &pBlackBrush);
	ID2D1SolidColorBrush* pGrayBrush = NULL;
	hr = m_device->GetD2DContext()->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Gray), &pGrayBrush);

	m_device->GetD2DContext()->BeginDraw();
	m_device->GetD2DContext()->SetTransform(D2D1::Matrix3x2F::Identity());
	m_device->GetD2DContext()->FillRectangle(D2D1::RectF(0, 0, 150, m_height), pWhiteBrush);
	m_device->GetD2DContext()->DrawText(
		L"Score:2700",
		10,
		m_device->m_textFormat.Get(),
		D2D1::RectF(5, 0, 150, 30),
		pBlackBrush
	);
	m_device->GetD2DContext()->DrawText(
		L"Level: 1",
		8,
		m_device->m_textFormat.Get(),
		D2D1::RectF(5, 20, 150, 30),
		pBlackBrush
	);
	m_device->GetD2DContext()->FillRoundedRectangle(D2D1::RoundedRect(D2D1::RectF(5, m_height - 40, 145, m_height - 5), 5, 5), pGrayBrush);
	m_device->GetD2DContext()->DrawText(
		L"Start",
		5,
		m_device->m_textFormat.Get(),
		D2D1::RectF(5, m_height - 30, 145, m_height - 5),
		pBlackBrush
	);

其中顶点数据与变换在程序中写,光照部分在着色器中实现。

//着色器代码
cbuffer SceneConstantBuffer : register(b0)
{
	matrix model;
	matrix view;
	matrix projection;
	float4 diffuse;
};

struct PSInput
{
	float4 position : SV_POSITION;
	float4 color : COLOR;
	float2 uv : TEXCOORD0;
	float3 worldNorm : TEXCOORD1;
	float3 worldPos : TEXCOORD2;
	float3 toEye : TEXCOORD3;
	float4 tangent : TEXCOORD4;
	float3 normal : TEXCOORD5;
};
Texture2D g_texture : register(t0);
SamplerState    g_sampler    : register(s0);


PSInput VSMain(float4 position : POSITION, float4 color : COLOR, float2 uv : TEXCOORD0, float3 normal : NORMAL)
{
	PSInput result=(PSInput)0;

	float4 pos = position;
	pos = mul(pos, model);
	pos = mul(pos, view);
	pos = mul(pos, projection);
	result.position = pos;
	result.color = diffuse;
	result.uv = uv;
	result.worldPos = pos.xyz / pos.w;
	result.worldNorm = normalize(mul(mul(normal.xyz, (float3x3)model), (float3x3)view));
	result.normal = normal;

	return result;
}

//
// lambert lighting function
//
float3 LambertLighting(
	float3 lightNormal,
	float3 surfaceNormal,
	float3 materialAmbient,
	float3 lightAmbient,
	float3 lightColor,
	float3 pixelColor
)
{
	// compute amount of contribution per light
	float diffuseAmount = saturate(dot(lightNormal, surfaceNormal));
	float3 diffuse = diffuseAmount * lightColor * pixelColor;

	// combine ambient with diffuse
	return saturate((materialAmbient * lightAmbient) + diffuse);
}

float4 CombineRGBWithAlpha(float3 rgb, float a)
{
	return float4(rgb.r, rgb.g, rgb.b, a);
}

float4 PSMain(PSInput input) : SV_TARGET
{
	//float3 diffuse = g_texture.Sample(g_sampler, input.uv).rgb;
	//return input.color;
	//return diffuse;
	//return g_texture.Sample(g_sampler, input.uv);
	float4 diffuse= g_texture.Sample(g_sampler, input.uv);

	float3 surfaceNormal = normalize(input.normal);
	float3 surfaceTangent = normalize(input.tangent.xyz);
	float3 worldNormal = input.worldNorm;

	float3x3 localToTangent = transpose(float3x3(surfaceTangent, cross(surfaceNormal, surfaceTangent) , surfaceNormal));
	float3x3 worldToTangent = mul((float3x3)model, localToTangent);

	//float3 tangentLightDir = normalize(mul(float3(0,0,1), model));
	float3 tangentLightDir = normalize(float3(0.5,1,1));

	float3 local1 = LambertLighting(tangentLightDir, worldNormal, float4(0.5, 0.5, 0.5, 1).rgb, float4(0.6, 0.6, 0.6, 1).rgb, float4(0.9, 0.9, 0.9,1).rgb, input.color.rgb);
	return CombineRGBWithAlpha(local1, input.color.a);

}

游戏截图

posted @ 2020-04-13 23:37  八爻老骥  阅读(298)  评论(0编辑  收藏  举报