【DX11习题学习三】第六章练习 Drawing in Direct3D(中)

本系列只针对书中每章节的编程练习题,不涉及书中的数学题,需要数学部分的解答请点击


对应原书 P264 6.15EXERCISES

6.Modify the Colored Cube demo by applying the following transformation to each vertex in the vertex shader prior to transforming to world space.
vin.Pos.xy += 0.5f*sin(vin.Pos.x)*sin(3.0f*gTime);
vin.Pos.z *= 0.6f + 0.4f*sin(2.0f*gTime);

The gTime constant buffer variable corresponds to the current GameTimer::TotalTime() value. This will animate the vertices as a function of time by distorting them periodically with the sine function.

题意:修改彩色立方体小程序,在VS阶段中的变换到世界空间之前对每个顶点使用上面的变换公式,其中 gTime是恒定缓冲区变量,其值对应GameTimer::TotalTime()(注意这个类是作者在书中提供的类)


这道题的实现效果挺有趣。这道题主要是想我们学习如何通过Effect框架对shader文件(fx文件)中的cbuffer变量赋值。

问题的关键在如何解决fx文件中的gTime变量,只要参考原文件中gWorldViewProj的操作就能实现题目效果。


在color.fx文件中修改

cbuffer cbPerObject
{
	float4x4 gWorldViewProj; 
	// ================Ex 6 of Cp 6====================
	float gTime;
	// ===========================================
};
以及

VertexOut VS(VertexIn vin)
{
	VertexOut vout;
	// ================Ex 6 of Cp 6====================
	vin.PosL.xy += 0.5f*sin(vin.PosL.x)*sin(3.0f*gTime);
	vin.PosL.z += 0.6f + 0.4f*sin(2.0f*gTime);
	// ===========================================
	// Transform to homogeneous clip space.
	vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj);
	
	// Just pass vertex color into the pixel shader.
    vout.Color = vin.Color;
    return vout;
}
Colored Cube demo的源文件中

BoxApp类中添加私有成员mfxTime

	ID3DX11EffectMatrixVariable* mfxWorldViewProj;
	// ================Ex 6 of Cp 6====================
	ID3DX11EffectScalarVariable* mfxTime;
	// ===========================================
BoxApp::BuildFX()方法中使成员mfxTime跟fx文件的gTime变量绑定在一起

	mfxWorldViewProj = mFX->GetVariableByName("gWorldViewProj")->AsMatrix();
	// ================Ex 6 of Cp 6====================
	mfxTime = mFX->GetVariableByName("gTime")->AsScalar();
	// ===========================================
最后在 BoxApp::DrawScene()方法中,实现赋值

	mfxWorldViewProj->SetMatrix(reinterpret_cast<float*>(&worldViewProj));
	// ================Ex 6 of Cp 6====================
	mfxTime->SetFloat(mTimer.TotalTime());
	// ===========================================

7. Merge the vertices of a box and pyramid into one large vertex buffer. Also merge the indices of the box and pyramid into one large index buffer (but do not update the index values). Then draw the box and pyramid one-by-one using the parameters of ID3D11DeviceContext::DrawIndexed. Use the world transformation matrix so that the box and pyramid are disjoint in world space.
题意:把金字塔和正方体的顶点和索引分别组合一个顶点缓存和一个索引缓存,然后使用 ID3D11DeviceContext::DrawIndexed逐个绘制。注意使用世界矩阵变换,避免两个物体交错在一起。

比较简单,看代码吧

void BoxApp::BuildGeometryBuffers()
{
	// Create vertex buffer
    Vertex vertices[] =
    {
		// ================正方体顶点====================
		{ XMFLOAT3(-1.0f, -1.0f, -1.0f), (const float*)&Colors::White   },
		{ XMFLOAT3(-1.0f, +1.0f, -1.0f), (const float*)&Colors::Black   },
		{ XMFLOAT3(+1.0f, +1.0f, -1.0f), (const float*)&Colors::Red     },
		{ XMFLOAT3(+1.0f, -1.0f, -1.0f), (const float*)&Colors::Green   },
		{ XMFLOAT3(-1.0f, -1.0f, +1.0f), (const float*)&Colors::Blue    },
		{ XMFLOAT3(-1.0f, +1.0f, +1.0f), (const float*)&Colors::Yellow  },
		{ XMFLOAT3(+1.0f, +1.0f, +1.0f), (const float*)&Colors::Cyan    },
		{ XMFLOAT3(+1.0f, -1.0f, +1.0f), (const float*)&Colors::Magenta },
		// ================金字塔顶点====================
		{ XMFLOAT3(0.0f,+1.0f, 0.0f), (const float*)&Colors::Red },			 //金字塔顶部顶点,索引号为0
		{ XMFLOAT3(-1.0f, -1.0f, +1.0f), (const float*)&Colors::Green },    //金字塔底部左上顶点,索引号为1
		{ XMFLOAT3(+1.0f, -1.0f, +1.0f), (const float*)&Colors::Black },    //金字塔底部右上顶点,索引号为2
		{ XMFLOAT3(+1.0f, -1.0f, -1.0f), (const float*)&Colors::Blue }, 	     //金字塔底部右下顶点,索引号为3
		{ XMFLOAT3(-1.0f, -1.0f, -1.0f), (const float*)&Colors::Magenta }, //金字塔底部左下顶点,索引号为4
		// ===========================================
    };

    D3D11_BUFFER_DESC vbd;
    vbd.Usage = D3D11_USAGE_IMMUTABLE;
	vbd.ByteWidth = sizeof(Vertex) * (mPyramidVerticesCount+mBoxVerticesCount);
    vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vbd.CPUAccessFlags = 0;
    vbd.MiscFlags = 0;
	vbd.StructureByteStride = 0;
    D3D11_SUBRESOURCE_DATA vinitData;
    vinitData.pSysMem = vertices;
    HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &mBoxVB));


	// Create the index buffer

	UINT indices[] = {
		// ================正方体索引====================
		// front face
		0, 1, 2,
		0, 2, 3,

		// back face
		4, 6, 5,
		4, 7, 6,

		// left face
		4, 5, 1,
		4, 1, 0,

		// right face
		3, 2, 6,
		3, 6, 7,

		// top face
		1, 5, 6,
		1, 6, 2,

		// bottom face
		4, 0, 3, 
		4, 3, 7,
		// ================金字塔索引====================
		// back face
		0, 1, 2,
		//  right face
		0, 2, 3,
		// front face
		0, 3, 4,
		//  left face
		0, 4, 1,
		// bottom face
		1, 3, 2,
		1, 4, 3
		// ===========================================
	};

	D3D11_BUFFER_DESC ibd;
    ibd.Usage = D3D11_USAGE_IMMUTABLE;
	ibd.ByteWidth = sizeof(UINT) * (mPyramidIndexCount+mBoxIndexCount);
    ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
    ibd.CPUAccessFlags = 0;
    ibd.MiscFlags = 0;
	ibd.StructureByteStride = 0;
    D3D11_SUBRESOURCE_DATA iinitData;
    iinitData.pSysMem = indices;
    HR(md3dDevice->CreateBuffer(&ibd, &iinitData, &mBoxIB));
}
BoxApp::DrawScene()修改

	// ================Ex 7 of Cp 6====================
	
	XMMATRIX view  = XMLoadFloat4x4(&mView);
	XMMATRIX proj  = XMLoadFloat4x4(&mProj);
	
	// ===========================================
    D3DX11_TECHNIQUE_DESC techDesc;
    mTech->GetDesc( &techDesc );
    for(UINT p = 0; p < techDesc.Passes; ++p)
    {
		// ================Ex 7 of Cp 6====================
		//================绘制正方体====================
		XMMATRIX world = XMLoadFloat4x4(&mBoxWorld);
		XMMATRIX worldViewProj = view * proj * world;
		mfxWorldViewProj->SetMatrix(reinterpret_cast<float*>(&worldViewProj));
		mTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
		md3dImmediateContext->DrawIndexed(mBoxIndexCount, 0, 0);
		//================绘制金字塔===================

		world = XMLoadFloat4x4(&mPyramidWorld);
		worldViewProj = view * proj * world;
		mfxWorldViewProj->SetMatrix(reinterpret_cast<float*>(&worldViewProj));
		mTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
		md3dImmediateContext->DrawIndexed(mPyramidIndexCount, mBoxIndexCount, mBoxVerticesCount);

		// ===========================================
		//mTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
		// 36 indices for the box.
		//md3dImmediateContext->DrawIndexed(36, 0, 0);
    }
在构造函数中添加

	// ================Ex 7 of Cp 6====================
	mPyramidIndexCount = 18;
	mBoxIndexCount = 36;
	mPyramidVerticesCount = 5;
	mBoxVerticesCount = 8;

	XMStoreFloat4x4(&mBoxWorld, XMMatrixTranslation(0.0f, 0.0f, 0.0f));
	XMStoreFloat4x4(&mPyramidWorld, XMMatrixTranslation(0.5f, 0.0f, 0.0f));
	// ===========================================



8.Modify the Colored Cube demo by rendering the cube in wireframe mode. Do this in two different ways: First, by setting the rasterization render state from the C++ code by callingID3D11DeviceContext::RSSetState; second, by setting the rasterization render state from the effect file by callingSetRasterizerState() in the effect pass.
题意:把立方体例子修改成只渲染线框的模式。方法有两种:
第一种在C++代码中调用ID3D11DeviceContext::RSSetState;第二种在effect文件的pass中调用SetRasterizerState()


第一种方法:

声明ID3D11RasterizerState对象,通过设置D3D11_RASTERIZER_DESC对象描述目标效果后用CreateRasterizerState实例化ID3D11RasterizerState对象,在DrawScene函数的ID3D11DeviceContext::RSSetState方法(同了挺高代码阅读性,一般放着IA相关函数后面调用)即可实现效果


创建新的类成员

	// ================Ex 8 of Cp 6====================
	ID3D11RasterizerState* mWireframeRS;
	// ===========================================
Init()成员函数中加入

	// ================Ex 8 of Cp 6====================
	D3D11_RASTERIZER_DESC wireframeDesc;
	ZeroMemory(&wireframeDesc, sizeof(D3D11_RASTERIZER_DESC));//必须先执行清零初始化
	wireframeDesc.FillMode = D3D11_FILL_WIREFRAME;
	wireframeDesc.CullMode = D3D11_CULL_NONE;
	wireframeDesc.FrontCounterClockwise = false;
	wireframeDesc.DepthClipEnable = true;

	HR(md3dDevice->CreateRasterizerState(&wireframeDesc, &mWireframeRS));
	// ===========================================
void BoxApp::DrawScene()
{
	md3dImmediateContext->ClearRenderTargetView(mRenderTargetView, reinterpret_cast<const float*>(&Colors::LightSteelBlue));
	md3dImmediateContext->ClearDepthStencilView(mDepthStencilView, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0);

	md3dImmediateContext->IASetInputLayout(mInputLayout);
    md3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
	// ================Ex 8 of Cp 6====================
	md3dImmediateContext->RSSetState(mWireframeRS);
	// ===========================================
<span style="white-space:pre">	</span>.....
}

第二种方法:

直接上代码吧

cbuffer cbPerObject
{
	float4x4 gWorldViewProj; 
};
// ================Ex 8 of Cp 6====================
RasterizerState DisableCulling
{
	CullMode = NONE;
	FillMode = WIREFRAME;
};
// ===========================================
struct VertexIn
{
	float3 PosL   : POSITION;
	float4 Color : COLOR;
};

struct VertexOut
{
	float4 PosH  : SV_POSITION;
    <span style="white-space:pre">	</span>float4 Color : COLOR;
};

VertexOut VS(VertexIn vin)
{
	VertexOut vout;
	vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj);
    <span style="white-space:pre">	</span>vout.Color = vin.Color;
    
    return vout;
}
float4 PS(VertexOut pin) : SV_Target
{
    return pin.Color;
}
technique11 ColorTech
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_5_0, VS() ) );
	SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_5_0, PS() ) );
	// ================Ex 8 of Cp 6====================
	SetRasterizerState(DisableCulling);
	// ============================================
    }
}


补充:D3D11_RASTERIZER_DESC对象更多的设置内容,可到MSDN查找,或者参考此博客


9. Modify the Colored Cube demo by disabling backface culling (CullMode = None); also try culling front faces instead of back faces (CullMode = Front). Do this in two different ways: First, by setting the rasterization render state from the C++ code by calling ID3D11DeviceContext::RSSetState; second, by setting the rasterization render state from the effect file by calling SetRasterizerState() in the effect pass. 
题意:把立方体例子修改成禁止背面剔除(CullMode = None)和剔除朝前三角形(CullMode = Front)的模式。方法有两种:
第一种在C++代码中调用ID3D11DeviceContext::RSSetState;第二种在effect文件的pass中调用SetRasterizerState()

跟上面那道题类似

第一种方法只需把第8题的修改CullMode为如下

wireframeDesc.CullMode = D3D11_CULL_FRONT;
第二种 方法同理

RasterizerState DisableCulling
{
	CullMode = FRONT;
	FillMode = SOLID;
};

10.If vertex memory is significant, then reducing from 128-bit color values to 32-bit color values may be worthwhile. Modify the “Box” demo by using a 32-bit color value instead of a 128-bit color value in the vertexstructure. Your  vertex structure and corresponding vertex input description will look like this:

如果顶点内存变得很重要,把128位的颜色值变成32位的颜色值会相当有效!把在顶点结构把颜色值修改成32位,可以像下面这样设置顶点输入描述:
struct Vertex
{
XMFLOAT3 Pos;
XMCOLOR Color;
};
D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,
D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12,
D3D11_INPUT_PER_VERTEX_DATA, 0}
};

The 8-bit color components need to be packed into a UINT in the format ABGR, not RGBA; this is because the byte order is reversed in little-endian format (the bytesABGRwill actually be ordered RGBA in littleendian). For multi-byte data, big-endian stores the most significant byte at the lowest address in memory, and the least significant byte at the highest address, and little-endian stores the least significant byte at the lowest address in memory, and the most significant byte at the highest address in memory. The conversion fromARGB(which XMCOLOR uses) to ABGR can be done with a function like the following:

注意:这里有一个ABGR的概念,其实就是RGBA在小端机中表示(RGBA的对应的颜色通道和Apla通道反转放置);多字节的大端机从最低地址开始存储最高有效字节,最高地址存储最低有效字节,而小端机则是从最低地址开始存储最低有效字节,在最高地址存储最高有效字节,从ARGB(XMCOLOR 使用的类型)转换到ABGR的方法如下:

static D3DX11INLINE UINT ArgbToAbgr(UINT argb)
{
BYTE A = (argb >> 24) & 0xff;
BYTE R = (argb >> 16) & 0xff;
BYTE G = (argb >> 8) & 0xff;
BYTE B = (argb >> 0) & 0xff;
return (A << 24) | (B << 16) | (G << 8) | (R << 0);
}


方法题目都说的差不多了,直接上代码吧

第一步:

struct Vertex
{
	XMFLOAT3 Pos;
	XMCOLOR  Color;
};

static D3DX11INLINE UINT ArgbToAbgr(UINT argb)
{
	BYTE A = (argb >> 24) & 0xff;
	BYTE R = (argb >> 16) & 0xff;
	BYTE G = (argb >> 8) & 0xff;
	BYTE B = (argb >> 0) & 0xff;
	return (A << 24) | (B << 16) | (G << 8) | (R << 0);
}
第二步:

void BoxApp::BuildVertexLayout()
{
	// Create the vertex input layout.
	D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
	{
		{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
		{"COLOR",    0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}
	};

	// Create the input layout
    D3DX11_PASS_DESC passDesc;
    mTech->GetPassByIndex(0)->GetDesc(&passDesc);
	HR(md3dDevice->CreateInputLayout(vertexDesc, 2, passDesc.pIAInputSignature, 
		passDesc.IAInputSignatureSize, &mInputLayout));
}
 
最后:

void BoxApp::BuildGeometryBuffers()
{
	// Create vertex buffer
    Vertex vertices[] =
    {
		{ XMFLOAT3(-1.0f, -1.0f, -1.0f), ArgbToAbgr(0xFFFFFFFF) },
		{ XMFLOAT3(-1.0f, +1.0f, -1.0f), ArgbToAbgr(0xFF000000) },
		{ XMFLOAT3(+1.0f, +1.0f, -1.0f), ArgbToAbgr(0xFFFF0000) },
		{ XMFLOAT3(+1.0f, -1.0f, -1.0f), ArgbToAbgr(0xFF00FF00) },
		{ XMFLOAT3(-1.0f, -1.0f, +1.0f), ArgbToAbgr(0xFF0000FF) },
		{ XMFLOAT3(-1.0f, +1.0f, +1.0f), ArgbToAbgr(0xFFFFFF00) },
		{ XMFLOAT3(+1.0f, +1.0f, +1.0f), ArgbToAbgr(0xFF00FFFF) },
		{ XMFLOAT3(+1.0f, -1.0f, +1.0f), ArgbToAbgr(0xFFFF00FF) },
	
    };
........;
}












  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值