Introdution to 3D Game Programming With DirectX11 第11章 习题解答

时间:2022-10-16 03:34:57

11.1

这道题要注意使用了line strip,由于曾经一直用triangle list,所以在几何渲染的时候easy算错定点描绘的顺序。

贴一些代码,大概就能把这个问题解释清楚了,由于框架还不是特别熟,所以是在原有样例的基础上建立的自己的代码

void TreeBillboardApp::BuildCircleBuffers()
{
//
//Create the vertex buffer
//
std::vector<Vertex::Basic32> vertices(32);
for (int i = 0; i < 32; i++)
{
vertices[i].Pos.x = cosf(MathHelper::Pi * i / 16);
vertices[i].Pos.y = 0;
vertices[i].Pos.z = sinf(MathHelper::Pi * i / 16); XMVECTOR p = XMLoadFloat3(&vertices[i].Pos);
XMStoreFloat3(&vertices[i].Normal, XMVector3Normalize(p)); vertices[i].Tex.x = i / 32;
vertices[i].Tex.y = 0;
} D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(Vertex::Basic32) * 32;
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
vbd.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = &vertices[0];
HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &mCircleVB)); //
//Create the index buffer
// UINT indices[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 0 }; D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_IMMUTABLE;
ibd.ByteWidth = sizeof(UINT)* 33;
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, &mCircleIB));
} void TreeBillboardApp::DrawCircle(CXMMATRIX viewProj)
{
//--------------------------------------------------------------------------
//
//Draw the circle
//
// Set per object constants.
XMMATRIX world = XMLoadFloat4x4(&mCircleWorld);
XMMATRIX worldInvTranspose = MathHelper::InverseTranspose(world);
XMMATRIX worldViewProj = world*viewProj; Effects::CircleFX->SetWorld(world);
Effects::CircleFX->SetWorldInvTranspose(worldInvTranspose);
Effects::CircleFX->SetWorldViewProj(worldViewProj);
Effects::CircleFX->SetTexTransform(XMMatrixIdentity());
Effects::CircleFX->SetMaterial(mBoxMat);
Effects::CircleFX->SetDiffuseMap(mBoxMapSRV);
Effects::CircleFX->SetDirLights(mDirLights);
Effects::CircleFX->SetEyePosW(mEyePosW);
Effects::CircleFX->SetFogColor(Colors::Silver);
Effects::CircleFX->SetFogStart(15.0f);
Effects::CircleFX->SetFogRange(175.0f); md3dImmediateContext->IASetInputLayout(InputLayouts::Basic32);
md3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP); md3dImmediateContext->RSSetState(RenderStates::WireframeRS); UINT stride1 = sizeof(Vertex::Basic32);
UINT offset1 = 0;
md3dImmediateContext->IASetVertexBuffers(0, 1, &mCircleVB, &stride1, &offset1);
md3dImmediateContext->IASetIndexBuffer(mCircleIB, DXGI_FORMAT_R32_UINT, 0); ID3DX11EffectTechnique* circleTech;
D3DX11_TECHNIQUE_DESC techDesc; switch (mRenderOptions)
{
case RenderOptions::Lighting:
circleTech = Effects::CircleFX->Light3Tech;
break;
case RenderOptions::Textures:
circleTech = Effects::CircleFX->Light3TexAlphaClipTech;
break;
case RenderOptions::TexturesAndFog:
circleTech = Effects::CircleFX->Light3TexAlphaClipFogTech;
break;
} circleTech->GetDesc(&techDesc); for (UINT p = 0; p < techDesc.Passes; ++p)
{
//md3dImmediateContext->OMSetBlendState(RenderStates::AlphaToCoverageBS, blendFactor, 0xffffffff);
md3dImmediateContext->RSSetState(RenderStates::NoCullRS);
circleTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
md3dImmediateContext->DrawIndexed(33, 0, 0); // Restore default render state.
md3dImmediateContext->RSSetState(0);
}
}

还专给那个circle单写了fx,请无视那凝视

//=============================================================================
// Basic.fx by Frank Luna (C) 2011 All Rights Reserved.
//
// Basic effect that currently supports transformations, lighting, and texturing.
//============================================================================= #include "LightHelper.fx" cbuffer cbPerFrame
{
DirectionalLight gDirLights[3];
float3 gEyePosW; float gFogStart;
float gFogRange;
float4 gFogColor;
}; cbuffer cbPerObject
{
float4x4 gWorld;
float4x4 gWorldInvTranspose;
float4x4 gWorldViewProj;
float4x4 gTexTransform;
Material gMaterial;
}; // Nonnumeric values cannot be added to a cbuffer.
Texture2D gDiffuseMap; SamplerState samAnisotropic
{
Filter = ANISOTROPIC;
MaxAnisotropy = 4; AddressU = WRAP;
AddressV = WRAP;
}; struct VertexIn
{
float3 PosL : POSITION;
float3 NormalL : NORMAL;
float2 Tex : TEXCOORD;
}; struct VertexOut
{
float4 PosH : SV_POSITION;
float3 PosW : POSITION;
float3 NormalW : NORMAL;
float2 Tex : TEXCOORD;
}; struct GeoOut
{
float4 PosH : SV_POSITION;
float3 PosW : POSITION;
float3 NormalW : NORMAL;
float2 Tex : TEXCOORD;
uint PrimID : SV_PrimitiveID;
}; VertexOut VS(VertexIn vin)
{
VertexOut vout; // Transform to world space space.
vout.PosW = mul(float4(vin.PosL, 1.0f), gWorld).xyz;
vout.NormalW = mul(vin.NormalL, (float3x3)gWorldInvTranspose); // Transform to homogeneous clip space.
vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj); // Output vertex attributes for interpolation across triangle.
vout.Tex = mul(float4(vin.Tex, 0.0f, 1.0f), gTexTransform).xy; return vout;
} [maxvertexcount(4)]
void GS(line VertexOut gin[2],
uint primID : SV_PrimitiveID,
inout TriangleStream<GeoOut> triStream)
{
//
// Compute the local coordinate system of the sprite relative to the world
// space such that the billboard is aligned with the y-axis and faces the eye.
// float3 up = float3(0.0f, 5.0f, 0.0f);
//float3 look = gEyePosW - gin[0].CenterW;
//look.y = 0.0f; // y-axis aligned, so project to xz-plane
//look = normalize(look);
//float3 right = cross(up, look); //
// Compute triangle strip vertices (quad) in world space.
//
//float halfWidth = 0.5f*gin[0].SizeW.x;
//float halfHeight = 0.5f*gin[0].SizeW.y; float4 v[4];
v[0] = float4(gin[0].PosW, 1.0f);
v[1] = float4(gin[0].PosW + up, 1.0f);
v[2] = float4(gin[1].PosW, 1.0f);
v[3] = float4(gin[1].PosW + up, 1.0f); float3 n[4];
n[0] = gin[0].NormalW;
n[1] = gin[0].NormalW;
n[2] = gin[1].NormalW;
n[3] = gin[1].NormalW; float2 t[4];
t[0] = gin[0].Tex;
t[1].x = gin[0].Tex.x;
t[1].y = 1.0f;
t[2] = gin[1].Tex;
t[3].x = gin[1].Tex.x;
t[3].y = 1.0f; //
// Transform quad vertices to world space and output
// them as a triangle strip.
//
GeoOut gout;
[unroll]
for (int i = 0; i < 4; ++i)
{
gout.PosH = mul(v[i], gWorldViewProj);
gout.PosW = v[i].xyz;
gout.NormalW = n[i].xyz;
gout.Tex = t[i].xy;
gout.PrimID = primID; triStream.Append(gout);
}
} float4 PS(GeoOut pin, uniform int gLightCount, uniform bool gUseTexure, uniform bool gAlphaClip, uniform bool gFogEnabled) : SV_Target
{
// Interpolating normal can unnormalize it, so normalize it.
pin.NormalW = normalize(pin.NormalW); // The toEye vector is used in lighting.
float3 toEye = gEyePosW - pin.PosW; // Cache the distance to the eye from this surface point.
float distToEye = length(toEye); // Normalize.
toEye /= distToEye; // Default to multiplicative identity.
//float3 uvw = float3(pin.Tex, pin.PrimID % 4);
float4 texColor = float4(1, 1, 1, 1);
if (gUseTexure)
{
// Sample texture.
texColor = gDiffuseMap.Sample(samAnisotropic, pin.Tex); if (gAlphaClip)
{
// Discard pixel if texture alpha < 0.1. Note that we do this
// test as soon as possible so that we can potentially exit the shader
// early, thereby skipping the rest of the shader code.
clip(texColor.a - 0.1f);
}
} //
// Lighting.
// float4 litColor = texColor;
if (gLightCount > 0)
{
// Start with a sum of zero.
float4 ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
float4 diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
float4 spec = float4(0.0f, 0.0f, 0.0f, 0.0f); // Sum the light contribution from each light source.
[unroll]
for (int i = 0; i < gLightCount; ++i)
{
float4 A, D, S;
ComputeDirectionalLight(gMaterial, gDirLights[i], pin.NormalW, toEye,
A, D, S); ambient += A;
diffuse += D;
spec += S;
} // Modulate with late add.
litColor = texColor*(ambient + diffuse) + spec;
} //
// Fogging
// if (gFogEnabled)
{
float fogLerp = saturate((distToEye - gFogStart) / gFogRange); // Blend the fog color and the lit color.
litColor = lerp(litColor, gFogColor, fogLerp);
} // Common to take alpha from diffuse material and texture.
litColor.a = gMaterial.Diffuse.a * texColor.a; return litColor;
} technique11 Light1
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(1, false, false, false)));
}
} technique11 Light2
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(2, false, false, false)));
}
} technique11 Light3
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(3, false, false, false)));
}
} technique11 Light0Tex
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(0, true, false, false)));
}
} technique11 Light1Tex
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(1, true, false, false)));
}
} technique11 Light2Tex
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(2, true, false, false)));
}
} technique11 Light3Tex
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader(gs_5_0, GS()));
SetPixelShader(CompileShader(ps_5_0, PS(3, true, false, false)));
}
} technique11 Light0TexAlphaClip
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(0, true, true, false)));
}
} technique11 Light1TexAlphaClip
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(1, true, true, false)));
}
} technique11 Light2TexAlphaClip
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(2, true, true, false)));
}
} technique11 Light3TexAlphaClip
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(3, true, true, false)));
}
} technique11 Light1Fog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(1, false, false, true)));
}
} technique11 Light2Fog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader(gs_5_0, GS()));
SetPixelShader(CompileShader(ps_5_0, PS(2, false, false, true)));
}
} technique11 Light3Fog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(3, false, false, true)));
}
} technique11 Light0TexFog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(0, true, false, true)));
}
} technique11 Light1TexFog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(1, true, false, true)));
}
} technique11 Light2TexFog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(2, true, false, true)));
}
} technique11 Light3TexFog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(3, true, false, true)));
}
} technique11 Light0TexAlphaClipFog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(0, true, true, true)));
}
} technique11 Light1TexAlphaClipFog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(1, true, true, true)));
}
} technique11 Light2TexAlphaClipFog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(2, true, true, true)));
}
} technique11 Light3TexAlphaClipFog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(CompileShader( gs_5_0, GS() ));
SetPixelShader(CompileShader(ps_5_0, PS(3, true, true, true)));
}
}

Introdution to 3D Game Programming With DirectX11 第11章 习题解答

Introdution to 3D Game Programming With DirectX11 第11章 习题解答

Introdution to 3D Game Programming With DirectX11 第11章 习题解答

11.2

Basic.fx
#include "LightHelper.fx"

cbuffer cbPerFrame
{
DirectionalLight gDirLights[3];
float3 gEyePosW; float gFogStart;
float gFogRange;
float4 gFogColor;
}; cbuffer cbPerObject
{
float4x4 gWorld;
float4x4 gWorldInvTranspose;
float4x4 gWorldViewProj;
float4x4 gTexTransform;
Material gMaterial;
}; // Nonnumeric values cannot be added to a cbuffer.
Texture2D gDiffuseMap; SamplerState samAnisotropic
{
Filter = ANISOTROPIC;
MaxAnisotropy = 4; AddressU = WRAP;
AddressV = WRAP;
}; struct VertexIn
{
float3 PosL : POSITION;
float3 NormalL : NORMAL;
float2 Tex : TEXCOORD;
}; struct VertexOut
{
float3 PosL : POSITION;
float3 NormalL : NORMAL;
float2 Tex : TEXCOORD;
}; struct GeoOut
{
float4 PosH : SV_POSITION;
float3 PosW : POSITION;
float3 NormalW : NORMAL;
float2 Tex : TEXCOORD;
float FogLerp : FOG;
}; VertexOut VS(VertexIn vin)
{
VertexOut vout; vout.PosL = vin.PosL;
vout.NormalL = vin.NormalL;
vout.Tex = vin.Tex; return vout;
} void SubdivideZero(VertexOut inVerts[3], out VertexOut outVerts[3])
{
outVerts[0] = inVerts[0];
outVerts[1] = inVerts[1];
outVerts[2] = inVerts[2];
} void Subdivide(VertexOut inVerts[3], out VertexOut outVerts[6])
{
VertexOut m[3]; // Compute edge midpoints.
m[0].PosL = 0.5f*(inVerts[0].PosL + inVerts[1].PosL);
m[1].PosL = 0.5f*(inVerts[1].PosL + inVerts[2].PosL);
m[2].PosL = 0.5f*(inVerts[2].PosL + inVerts[0].PosL); // Project onto unit sphere
m[0].PosL = normalize(m[0].PosL);
m[1].PosL = normalize(m[1].PosL);
m[2].PosL = normalize(m[2].PosL); // Derive normals.
m[0].NormalL = m[0].PosL;
m[1].NormalL = m[1].PosL;
m[2].NormalL = m[2].PosL; // Interpolate texture coordinates.
m[0].Tex = 0.5f*(inVerts[0].Tex + inVerts[1].Tex);
m[1].Tex = 0.5f*(inVerts[1].Tex + inVerts[2].Tex);
m[2].Tex = 0.5f*(inVerts[2].Tex + inVerts[0].Tex); outVerts[0] = inVerts[0];
outVerts[1] = m[0];
outVerts[2] = m[2];
outVerts[3] = m[1];
outVerts[4] = inVerts[2];
outVerts[5] = inVerts[1];
} void SubdivideTwice(VertexOut inVerts[3], out VertexOut outVerts[15])
{
VertexOut m[12]; // Compute edge midpoints.
m[0].PosL = 0.75f * inVerts[0].PosL + 0.25 * inVerts[2].PosL;
m[1].PosL = 0.5f * inVerts[0].PosL + 0.5 * inVerts[2].PosL;
m[2].PosL = 0.25f * inVerts[0].PosL + 0.75 * inVerts[2].PosL;
m[3].PosL = 0.75f * inVerts[2].PosL + 0.25 * inVerts[1].PosL;
m[4].PosL = 0.5f * inVerts[2].PosL + 0.5 * inVerts[1].PosL;
m[5].PosL = 0.25f * inVerts[2].PosL + 0.75 * inVerts[1].PosL;
m[6].PosL = 0.75f * inVerts[1].PosL + 0.25 * inVerts[0].PosL;
m[7].PosL = 0.5f * inVerts[1].PosL + 0.5 * inVerts[0].PosL;
m[8].PosL = 0.25f * inVerts[1].PosL + 0.75 * inVerts[0].PosL;
m[9].PosL = 0.5f * m[4].PosL + 0.5 * m[7].PosL;
m[10].PosL = 0.5f * m[1].PosL + 0.5 * m[7].PosL;
m[11].PosL = 0.5f * m[1].PosL + 0.5 * m[4].PosL; // Project onto unit sphere
m[0].PosL = normalize(m[0].PosL);
m[1].PosL = normalize(m[1].PosL);
m[2].PosL = normalize(m[2].PosL);
m[3].PosL = normalize(m[3].PosL);
m[4].PosL = normalize(m[4].PosL);
m[5].PosL = normalize(m[5].PosL);
m[6].PosL = normalize(m[6].PosL);
m[7].PosL = normalize(m[7].PosL);
m[8].PosL = normalize(m[8].PosL);
m[9].PosL = normalize(m[9].PosL);
m[10].PosL = normalize(m[10].PosL);
m[11].PosL = normalize(m[11].PosL); // Derive normals.
m[0].NormalL = m[0].PosL;
m[1].NormalL = m[1].PosL;
m[2].NormalL = m[2].PosL;
m[3].NormalL = m[3].PosL;
m[4].NormalL = m[4].PosL;
m[5].NormalL = m[5].PosL;
m[6].NormalL = m[6].PosL;
m[7].NormalL = m[7].PosL;
m[8].NormalL = m[8].PosL;
m[9].NormalL = m[9].PosL;
m[10].NormalL = m[10].PosL;
m[11].NormalL = m[11].PosL; // Interpolate texture coordinates.
m[0].Tex = 0.75f * inVerts[0].Tex + 0.25 * inVerts[2].Tex;
m[1].Tex = 0.5f * inVerts[0].Tex + 0.5 * inVerts[2].Tex;
m[2].Tex = 0.25f * inVerts[0].Tex + 0.75 * inVerts[2].Tex;
m[3].Tex = 0.75f * inVerts[2].Tex + 0.25 * inVerts[1].Tex;
m[4].Tex = 0.5f * inVerts[2].Tex + 0.5 * inVerts[1].Tex;
m[5].Tex = 0.25f * inVerts[2].Tex + 0.75 * inVerts[1].Tex;
m[6].Tex = 0.75f * inVerts[1].Tex + 0.25 * inVerts[0].Tex;
m[7].Tex = 0.5f * inVerts[1].Tex + 0.5 * inVerts[0].Tex;
m[8].Tex = 0.25f * inVerts[1].Tex + 0.75 * inVerts[0].Tex;
m[9].Tex = 0.5f * m[4].Tex + 0.5 * m[7].Tex;
m[10].Tex = 0.5f * m[1].Tex + 0.5 * m[7].Tex;
m[11].Tex = 0.5f * m[1].Tex + 0.5 * m[4].Tex; outVerts[0] = inVerts[0];
outVerts[1] = m[0];
outVerts[2] = m[1];
outVerts[3] = m[2];
outVerts[4] = inVerts[2];
outVerts[5] = m[3];
outVerts[6] = m[4];
outVerts[7] = m[5];
outVerts[8] = inVerts[1];
outVerts[9] = m[6];
outVerts[10] = m[7];
outVerts[11] = m[8];
outVerts[12] = m[9];
outVerts[13] = m[10];
outVerts[14] = m[11];
} void OutputSubdivisionZero(VertexOut v[3], inout TriangleStream<GeoOut> triStream)
{
GeoOut gout[3]; [unroll]
for (int i = 0; i < 3; ++i)
{
// Transorm to world space space.
gout[i].PosW = mul(float4(v[i].PosL, 1.0f), gWorld).xyz;
gout[i].NormalW = mul(v[i].NormalL, (float3x3)gWorldInvTranspose); // Transform to homogeneous clip space.
gout[i].PosH = mul(float4(v[i].PosL, 1.0f), gWorldViewProj); gout[i].Tex = v[i].Tex;
} [unroll]
for (int j = 0; j < 3; ++j)
{
triStream.Append(gout[j]);
}
} void OutputSubdivision(VertexOut v[6], inout TriangleStream<GeoOut> triStream)
{
GeoOut gout[6]; [unroll]
for (int i = 0; i < 6; ++i)
{
// Transorm to world space space.
gout[i].PosW = mul(float4(v[i].PosL, 1.0f), gWorld).xyz;
gout[i].NormalW = mul(v[i].NormalL, (float3x3)gWorldInvTranspose); // Transform to homogeneous clip space.
gout[i].PosH = mul(float4(v[i].PosL, 1.0f), gWorldViewProj); gout[i].Tex = v[i].Tex;
} [unroll]
for (int j = 0; j < 5; ++j)
{
triStream.Append(gout[j]);
}
triStream.RestartStrip(); triStream.Append(gout[1]);
triStream.Append(gout[5]);
triStream.Append(gout[3]);
} void OutputSubdivisionTwice(VertexOut v[15], inout TriangleStream<GeoOut> triStream)
{
GeoOut gout[15]; [unroll]
for (int i = 0; i < 15; ++i)
{
// Transorm to world space space.
gout[i].PosW = mul(float4(v[i].PosL, 1.0f), gWorld).xyz;
gout[i].NormalW = mul(v[i].NormalL, (float3x3)gWorldInvTranspose); // Transform to homogeneous clip space.
gout[i].PosH = mul(float4(v[i].PosL, 1.0f), gWorldViewProj); gout[i].Tex = v[i].Tex;
} triStream.Append(gout[0]);
triStream.Append(gout[11]);
triStream.Append(gout[1]);
triStream.Append(gout[13]);
triStream.Append(gout[2]);
triStream.Append(gout[14]);
triStream.Append(gout[3]);
triStream.Append(gout[5]);
triStream.Append(gout[4]); triStream.RestartStrip(); triStream.Append(gout[11]);
triStream.Append(gout[10]);
triStream.Append(gout[13]);
triStream.Append(gout[12]);
triStream.Append(gout[14]);
triStream.Append(gout[6]);
triStream.Append(gout[5]); triStream.RestartStrip(); triStream.Append(gout[10]);
triStream.Append(gout[9]);
triStream.Append(gout[12]);
triStream.Append(gout[7]);
triStream.Append(gout[6]); triStream.RestartStrip(); triStream.Append(gout[9]);
triStream.Append(gout[8]);
triStream.Append(gout[7]); } [maxvertexcount(24)]
void GS(triangle VertexOut gin[3], inout TriangleStream<GeoOut> triStream)
{ if (length(gEyePosW) >= 30)
{
VertexOut v[3];
SubdivideZero(gin, v);
OutputSubdivisionZero(v, triStream);
}
else if ((length(gEyePosW) >= 15))
{
VertexOut v[6];
Subdivide(gin, v);
OutputSubdivision(v, triStream);
}else
{
VertexOut v[15];
SubdivideTwice(gin, v);
OutputSubdivisionTwice(v, triStream);
}
} float4 PS(GeoOut pin, uniform int gLightCount, uniform bool gUseTexure, uniform bool gAlphaClip, uniform bool gFogEnabled) : SV_Target
{
// Interpolating normal can unnormalize it, so normalize it.
pin.NormalW = normalize(pin.NormalW); // The toEye vector is used in lighting.
float3 toEye = gEyePosW - pin.PosW; // Cache the distance to the eye from this surface point.
float distToEye = length(toEye); // Normalize.
toEye /= distToEye; // Default to multiplicative identity.
float4 texColor = float4(1, 1, 1, 1);
if(gUseTexure)
{
// Sample texture.
texColor = gDiffuseMap.Sample( samAnisotropic, pin.Tex ); if(gAlphaClip)
{
// Discard pixel if texture alpha < 0.1. Note that we do this
// test as soon as possible so that we can potentially exit the shader
// early, thereby skipping the rest of the shader code.
clip(texColor.a - 0.1f);
}
} //
// Lighting.
// float4 litColor = texColor;
if( gLightCount > 0 )
{
// Start with a sum of zero.
float4 ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
float4 diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
float4 spec = float4(0.0f, 0.0f, 0.0f, 0.0f); // Sum the light contribution from each light source.
[unroll]
for(int i = 0; i < gLightCount; ++i)
{
float4 A, D, S;
ComputeDirectionalLight(gMaterial, gDirLights[i], pin.NormalW, toEye,
A, D, S); ambient += A;
diffuse += D;
spec += S;
} // Modulate with late add.
litColor = texColor*(ambient + diffuse) + spec;
} //
// Fogging
// if( gFogEnabled )
{
float fogLerp = saturate( (distToEye - gFogStart) / gFogRange ); // Blend the fog color and the lit color.
litColor = lerp(litColor, gFogColor, fogLerp);
} // Common to take alpha from diffuse material and texture.
litColor.a = gMaterial.Diffuse.a * texColor.a; return litColor;
} technique11 Light1
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader(CompileShader(gs_5_0, GS()));
SetPixelShader( CompileShader( ps_5_0, PS(1, false, false, false) ) );
}
} technique11 Light2
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(2, false, false, false) ) );
}
} technique11 Light3
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(3, false, false, false) ) );
}
} technique11 Light0Tex
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(0, true, false, false) ) );
}
} technique11 Light1Tex
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(1, true, false, false) ) );
}
} technique11 Light2Tex
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(2, true, false, false) ) );
}
} technique11 Light3Tex
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(3, true, false, false) ) );
}
} technique11 Light0TexAlphaClip
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(0, true, true, false) ) );
}
} technique11 Light1TexAlphaClip
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(1, true, true, false) ) );
}
} technique11 Light2TexAlphaClip
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(2, true, true, false) ) );
}
} technique11 Light3TexAlphaClip
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(3, true, true, false) ) );
}
} technique11 Light1Fog
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(1, false, false, true) ) );
}
} technique11 Light2Fog
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(2, false, false, true) ) );
}
} technique11 Light3Fog
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(3, false, false, true) ) );
}
} technique11 Light0TexFog
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(0, true, false, true) ) );
}
} technique11 Light1TexFog
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(1, true, false, true) ) );
}
} technique11 Light2TexFog
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(2, true, false, true) ) );
}
} technique11 Light3TexFog
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(3, true, false, true) ) );
}
} technique11 Light0TexAlphaClipFog
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(0, true, true, true) ) );
}
} technique11 Light1TexAlphaClipFog
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(1, true, true, true) ) );
}
} technique11 Light2TexAlphaClipFog
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(2, true, true, true) ) );
}
} technique11 Light3TexAlphaClipFog
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(3, true, true, true) ) );
}
}
LightHelper.fx
//***************************************************************************************
// LightHelper.fx by Frank Luna (C) 2011 All Rights Reserved.
//
// Structures and functions for lighting calculations.
//*************************************************************************************** struct DirectionalLight
{
float4 Ambient;
float4 Diffuse;
float4 Specular;
float3 Direction;
float pad;
}; struct PointLight
{
float4 Ambient;
float4 Diffuse;
float4 Specular; float3 Position;
float Range; float3 Att;
float pad;
}; struct SpotLight
{
float4 Ambient;
float4 Diffuse;
float4 Specular; float3 Position;
float Range; float3 Direction;
float Spot; float3 Att;
float pad;
}; struct Material
{
float4 Ambient;
float4 Diffuse;
float4 Specular; // w = SpecPower
float4 Reflect;
}; //---------------------------------------------------------------------------------------
// Computes the ambient, diffuse, and specular terms in the lighting equation
// from a directional light. We need to output the terms separately because
// later we will modify the individual terms.
//---------------------------------------------------------------------------------------
void ComputeDirectionalLight(Material mat, DirectionalLight L,
float3 normal, float3 toEye,
out float4 ambient,
out float4 diffuse,
out float4 spec)
{
// Initialize outputs.
ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
spec = float4(0.0f, 0.0f, 0.0f, 0.0f); // The light vector aims opposite the direction the light rays travel.
float3 lightVec = -L.Direction; // Add ambient term.
ambient = mat.Ambient * L.Ambient; // Add diffuse and specular term, provided the surface is in
// the line of site of the light. float diffuseFactor = dot(lightVec, normal); // Flatten to avoid dynamic branching.
[flatten]
if( diffuseFactor > 0.0f )
{
float3 v = reflect(-lightVec, normal);
float specFactor = pow(max(dot(v, toEye), 0.0f), mat.Specular.w); diffuse = diffuseFactor * mat.Diffuse * L.Diffuse;
spec = specFactor * mat.Specular * L.Specular;
}
} //---------------------------------------------------------------------------------------
// Computes the ambient, diffuse, and specular terms in the lighting equation
// from a point light. We need to output the terms separately because
// later we will modify the individual terms.
//---------------------------------------------------------------------------------------
void ComputePointLight(Material mat, PointLight L, float3 pos, float3 normal, float3 toEye,
out float4 ambient, out float4 diffuse, out float4 spec)
{
// Initialize outputs.
ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
spec = float4(0.0f, 0.0f, 0.0f, 0.0f); // The vector from the surface to the light.
float3 lightVec = L.Position - pos; // The distance from surface to light.
float d = length(lightVec); // Range test.
if( d > L.Range )
return; // Normalize the light vector.
lightVec /= d; // Ambient term.
ambient = mat.Ambient * L.Ambient; // Add diffuse and specular term, provided the surface is in
// the line of site of the light. float diffuseFactor = dot(lightVec, normal); // Flatten to avoid dynamic branching.
[flatten]
if( diffuseFactor > 0.0f )
{
float3 v = reflect(-lightVec, normal);
float specFactor = pow(max(dot(v, toEye), 0.0f), mat.Specular.w); diffuse = diffuseFactor * mat.Diffuse * L.Diffuse;
spec = specFactor * mat.Specular * L.Specular;
} // Attenuate
float att = 1.0f / dot(L.Att, float3(1.0f, d, d*d)); diffuse *= att;
spec *= att;
} //---------------------------------------------------------------------------------------
// Computes the ambient, diffuse, and specular terms in the lighting equation
// from a spotlight. We need to output the terms separately because
// later we will modify the individual terms.
//---------------------------------------------------------------------------------------
void ComputeSpotLight(Material mat, SpotLight L, float3 pos, float3 normal, float3 toEye,
out float4 ambient, out float4 diffuse, out float4 spec)
{
// Initialize outputs.
ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
spec = float4(0.0f, 0.0f, 0.0f, 0.0f); // The vector from the surface to the light.
float3 lightVec = L.Position - pos; // The distance from surface to light.
float d = length(lightVec); // Range test.
if( d > L.Range )
return; // Normalize the light vector.
lightVec /= d; // Ambient term.
ambient = mat.Ambient * L.Ambient; // Add diffuse and specular term, provided the surface is in
// the line of site of the light. float diffuseFactor = dot(lightVec, normal); // Flatten to avoid dynamic branching.
[flatten]
if( diffuseFactor > 0.0f )
{
float3 v = reflect(-lightVec, normal);
float specFactor = pow(max(dot(v, toEye), 0.0f), mat.Specular.w); diffuse = diffuseFactor * mat.Diffuse * L.Diffuse;
spec = specFactor * mat.Specular * L.Specular;
} // Scale by spotlight factor and attenuate.
float spot = pow(max(dot(-lightVec, L.Direction), 0.0f), L.Spot); // Scale by spotlight factor and attenuate.
float att = spot / dot(L.Att, float3(1.0f, d, d*d)); ambient *= spot;
diffuse *= att;
spec *= att;
}
Effects.h
#ifndef EFFECTS_H
#define EFFECTS_H #include "d3dUtil.h" #pragma region Effect
class Effect
{
public:
Effect(ID3D11Device* device, const std::wstring& filename);
virtual ~Effect(); private:
Effect(const Effect& rhs);
Effect& operator=(const Effect& rhs); protected:
ID3DX11Effect* mFX;
};
#pragma endregion #pragma region BasicEffect
class BasicEffect : public Effect
{
public:
BasicEffect(ID3D11Device* device, const std::wstring& filename);
~BasicEffect(); void SetWorldViewProj(CXMMATRIX M) { WorldViewProj->SetMatrix(reinterpret_cast<const float*>(&M)); }
void SetWorld(CXMMATRIX M) { World->SetMatrix(reinterpret_cast<const float*>(&M)); }
void SetWorldInvTranspose(CXMMATRIX M) { WorldInvTranspose->SetMatrix(reinterpret_cast<const float*>(&M)); }
void SetTexTransform(CXMMATRIX M) { TexTransform->SetMatrix(reinterpret_cast<const float*>(&M)); }
void SetEyePosW(const XMFLOAT3& v) { EyePosW->SetRawValue(&v, 0, sizeof(XMFLOAT3)); }
void SetDirLight(const DirectionalLight* lights) { DirLights->SetRawValue(lights, 0, 3 * sizeof(DirectionalLight)); }
void SetMatrial(const Material& mat) { Mat->SetRawValue(&mat, 0, sizeof(Material)); }
void SetDiffuseMap(ID3D11ShaderResourceView* tex) { DiffuseMap->SetResource(tex); } ID3DX11EffectTechnique* Light1Tech;
ID3DX11EffectTechnique* Light2Tech;
ID3DX11EffectTechnique* Light3Tech; ID3DX11EffectMatrixVariable* WorldViewProj;
ID3DX11EffectMatrixVariable* World;
ID3DX11EffectMatrixVariable* WorldInvTranspose;
ID3DX11EffectMatrixVariable* TexTransform;
ID3DX11EffectVectorVariable* EyePosW;
ID3DX11EffectVariable* DirLights;
ID3DX11EffectVariable* Mat; ID3DX11EffectShaderResourceVariable* DiffuseMap;
};
#pragma endregion #pragma region Effects
class Effects
{
public:
static void InitAll(ID3D11Device* device);
static void DestroyAll(); static BasicEffect* BasicFX;
};
#pragma endregion #endif
RenderStates.h
#ifndef RENDERSTATES_H
#define RENDERSTATES_H #include "d3dUtil.h" class RenderStates
{
public:
static void InitAll(ID3D11Device* device);
static void DestroyAll(); // Rasterize states
static ID3D11RasterizerState* WireframeRS;
static ID3D11RasterizerState* NoCullRS;
static ID3D11RasterizerState* CullClockwiseRS; // Blend states
static ID3D11BlendState* AlphaToCoverageBS;
static ID3D11BlendState* TransparentBS;
static ID3D11BlendState* NoRenderTargetWritesBS; // Depth/stencil states
}; #endif
Vertex.h
#ifndef VERTEX_H
#define VERTEX_H #include "d3dUtil.h" namespace Vertex
{
// Basic 32-byte vertex structure.
struct Basic32
{
Basic32() : Pos(0.0f, 0.0f, 0.0f), Normal(0.0f, 0.0f, 0.0f), Tex(0.0f, 0.0f) {}
Basic32(const XMFLOAT3& p, const XMFLOAT3& n, const XMFLOAT2& uv)
: Pos(p), Normal(n), Tex(uv) {}
Basic32(float px, float py, float pz, float nx, float ny, float nz, float u, float v)
: Pos(px, py, pz), Normal(nx, ny, nz), Tex(u, v) {}
XMFLOAT3 Pos;
XMFLOAT3 Normal;
XMFLOAT2 Tex;
};
} class InputLayoutDesc
{
public:
// Init like const int A::a[4] = {0, 1, 2, 3}; in .cpp file.
static const D3D11_INPUT_ELEMENT_DESC Basic32[3]; }; class InputLayouts
{
public:
static void InitAll(ID3D11Device* device);
static void DestroyAll(); static ID3D11InputLayout* Basic32;
}; #endif
Effects.cpp
#include "Effects.h" #pragma region Effect
Effect::Effect(ID3D11Device* device, const std::wstring& filename)
: mFX(0)
{
std::ifstream fin(filename, std::ios::binary); fin.seekg(0, std::ios_base::end);
int size = (int)fin.tellg();
fin.seekg(0, std::ios_base::beg);
std::vector<char> compiledShader(size); fin.read(&compiledShader[0], size);
fin.close(); HR(D3DX11CreateEffectFromMemory(&compiledShader[0], size,
0, device, &mFX));
} Effect::~Effect()
{
ReleaseCOM(mFX);
}
#pragma endregion #pragma region BasicEffect
BasicEffect::BasicEffect(ID3D11Device* device, const std::wstring& filename)
: Effect(device, filename)
{
Light1Tech = mFX->GetTechniqueByName("Light1");
Light2Tech = mFX->GetTechniqueByName("Light2");
Light3Tech = mFX->GetTechniqueByName("Light3"); WorldViewProj = mFX->GetVariableByName("gWorldViewProj")->AsMatrix();
World = mFX->GetVariableByName("gWorld")->AsMatrix();
WorldInvTranspose = mFX->GetVariableByName("gWorldInvTranspose")->AsMatrix();
TexTransform = mFX->GetVariableByName("gTexTransform")->AsMatrix();
EyePosW = mFX->GetVariableByName("gEyePosW")->AsVector();
DirLights = mFX->GetVariableByName("gDirLights");
Mat = mFX->GetVariableByName("gMaterial");
DiffuseMap = mFX->GetVariableByName("gDiffuseMap")->AsShaderResource();
} BasicEffect::~BasicEffect()
{
}
#pragma endregion #pragma region Effects BasicEffect* Effects::BasicFX = 0; void Effects::InitAll(ID3D11Device* device)
{
BasicFX = new BasicEffect(device, L"FX/Basic.fxo");
} void Effects::DestroyAll()
{
SafeDelete(BasicFX);
}
#pragma endregion
Main.cpp
#include "d3dApp.h"
#include "d3dx11Effect.h"
#include "GeometryGenerator.h"
#include "MathHelper.h"
#include "Effects.h"
#include "Vertex.h"
#include "RenderStates.h" enum RenderOptions
{
Lit = 0,
Lit2 = 1,
}; enum TextureOptions
{
Wireframe = 0,
Color = 1,
};
class Icosahedron : public D3DApp
{
public:
Icosahedron(HINSTANCE hInstance);
~Icosahedron(); bool Init();
void OnResize();
void UpdateScene(float dt);
void DrawScene(); void OnMouseDown(WPARAM btnState, int x, int y);
void OnMouseUp(WPARAM btnState, int x, int y);
void OnMouseMove(WPARAM btnState, int x, int y); private:
void BuildIcosahedronGeometryBuffers(); private:
ID3D11Buffer* mIcosahedronVB;
ID3D11Buffer* mIcosahedronIB; ID3D11ShaderResourceView* mIcosahedronMapSRV; DirectionalLight mDirLights[3];
Material mIcosahedronMat; XMFLOAT4X4 mIcosahedronWorld; UINT mIcosahedronIndexCount; XMFLOAT4X4 mView;
XMFLOAT4X4 mProj; RenderOptions mRenderOptions;
TextureOptions mTexOptions; XMFLOAT3 mEyePosW; float mTheta;
float mPhi;
float mRadius; POINT mLastMousePos;
}; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
PSTR cmdLine, int showCmd)
{
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif Icosahedron theApp(hInstance); if (!theApp.Init())
return 0; return theApp.Run();
} Icosahedron::Icosahedron(HINSTANCE hInstance)
: D3DApp(hInstance), mIcosahedronVB(0), mIcosahedronIB(0), mEyePosW(0.0f, 0.0f, 0.0f), mRenderOptions(RenderOptions::Lit),
mIcosahedronIndexCount(0), mTheta(1.3f*MathHelper::Pi), mPhi(0.4f*MathHelper::Pi), mRadius(80.0f), mTexOptions(TextureOptions::Color)
{
mMainWndCaption = L"Icosahedron";
mEnable4xMsaa = true; mLastMousePos.x = 0;
mLastMousePos.y = 0; XMMATRIX I = XMMatrixIdentity();
XMStoreFloat4x4(&mView, I);
XMStoreFloat4x4(&mProj, I); XMMATRIX icosahedronScale = XMMatrixScaling(5.0f, 5.0f, 5.0f);
XMMATRIX icosahedronOffset = XMMatrixTranslation(0.0f, 0.0f, 0.0f);
XMStoreFloat4x4(&mIcosahedronWorld, icosahedronScale*icosahedronOffset); mDirLights[0].Ambient = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f);
mDirLights[0].Diffuse = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
mDirLights[0].Specular = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
mDirLights[0].Direction = XMFLOAT3(0.57735f, -0.57735f, 0.57735f); mDirLights[1].Ambient = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
mDirLights[1].Diffuse = XMFLOAT4(0.20f, 0.20f, 0.20f, 1.0f);
mDirLights[1].Specular = XMFLOAT4(0.25f, 0.25f, 0.25f, 1.0f);
mDirLights[1].Direction = XMFLOAT3(-0.57735f, -0.57735f, 0.57735f); mDirLights[2].Ambient = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
mDirLights[2].Diffuse = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f);
mDirLights[2].Specular = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
mDirLights[2].Direction = XMFLOAT3(0.0f, -0.707f, -0.707f); mIcosahedronMat.Ambient = XMFLOAT4(0.48f, 0.77f, 0.46f, 1.0f);
mIcosahedronMat.Diffuse = XMFLOAT4(0.48f, 0.77f, 0.46f, 1.0f);
mIcosahedronMat.Specular = XMFLOAT4(0.2f, 0.2f, 0.2f, 16.0f);
} Icosahedron::~Icosahedron()
{
md3dImmediateContext->ClearState();
ReleaseCOM(mIcosahedronVB);
ReleaseCOM(mIcosahedronIB); Effects::DestroyAll();
InputLayouts::DestroyAll();
RenderStates::DestroyAll();
} bool Icosahedron::Init()
{
if (!D3DApp::Init())
return false; Effects::InitAll(md3dDevice);
InputLayouts::InitAll(md3dDevice);
RenderStates::InitAll(md3dDevice); BuildIcosahedronGeometryBuffers(); return true;
} void Icosahedron::OnResize()
{
D3DApp::OnResize(); XMMATRIX P = XMMatrixPerspectiveFovLH(0.25f*MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
XMStoreFloat4x4(&mProj, P);
} void Icosahedron::UpdateScene(float dt)
{
float x = mRadius*sinf(mPhi)*cosf(mTheta);
float z = mRadius*sinf(mPhi)*sinf(mTheta);
float y = mRadius*cosf(mPhi); mEyePosW = XMFLOAT3(x, y, z); // Build the view matrix.
XMVECTOR pos = XMVectorSet(x, y, z, 1.0f);
XMVECTOR target = XMVectorZero();
XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); XMMATRIX V = XMMatrixLookAtLH(pos, target, up);
XMStoreFloat4x4(&mView, V); //
// Switch the render mode based in key input
//
if (GetAsyncKeyState('1') & 0x8000)
mRenderOptions = RenderOptions::Lit; if (GetAsyncKeyState('2') & 0x8000)
mRenderOptions = RenderOptions::Lit2; if (GetAsyncKeyState('W') & 0x8000)
mTexOptions = TextureOptions::Wireframe; if (GetAsyncKeyState('C') & 0x8000)
mTexOptions = TextureOptions::Color;
} void Icosahedron::DrawScene()
{
md3dImmediateContext->ClearRenderTargetView(mRenderTargetView, reinterpret_cast<const float*>(&Colors::Silver));
md3dImmediateContext->ClearDepthStencilView(mDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); md3dImmediateContext->IASetInputLayout(InputLayouts::Basic32);
md3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); XMMATRIX view = XMLoadFloat4x4(&mView);
XMMATRIX proj = XMLoadFloat4x4(&mProj);
XMMATRIX viewProj = view*proj; Effects::BasicFX->SetEyePosW(mEyePosW);
Effects::BasicFX->SetDirLight(mDirLights); //
// Figure out which technique to use
//
ID3DX11EffectTechnique* IcosahedronTech; switch (mRenderOptions)
{
case RenderOptions::Lit:
IcosahedronTech = Effects::BasicFX->Light1Tech;
break;
case RenderOptions::Lit2:
IcosahedronTech = Effects::BasicFX->Light2Tech;
break;
} UINT stride = sizeof(Vertex::Basic32);
UINT offset = 0; D3DX11_TECHNIQUE_DESC techDesc; //
// DraW the icosahedron.
// IcosahedronTech->GetDesc(&techDesc);
for (UINT p = 0; p < techDesc.Passes; ++p)
{ md3dImmediateContext->IASetVertexBuffers(0, 1, &mIcosahedronVB, &stride, &offset);
md3dImmediateContext->IASetIndexBuffer(mIcosahedronIB, DXGI_FORMAT_R32_UINT, 0); // Set per object constants.
XMMATRIX world = XMLoadFloat4x4(&mIcosahedronWorld);
XMMATRIX worldInvTranspose = MathHelper::InverseTranspose(world);
XMMATRIX worldViewProj = world*view*proj; Effects::BasicFX->SetWorld(world);
Effects::BasicFX->SetWorldInvTranspose(worldInvTranspose);
Effects::BasicFX->SetWorldViewProj(worldViewProj);
Effects::BasicFX->SetTexTransform(XMMatrixIdentity());
Effects::BasicFX->SetMatrial(mIcosahedronMat);
//Effects::BasicFX->SetDiffuseMap(mIcosahedronMapSRV); switch (mTexOptions)
{
case TextureOptions::Color:
md3dImmediateContext->RSSetState(RenderStates::NoCullRS);
break;
case TextureOptions::Wireframe:
md3dImmediateContext->RSSetState(RenderStates::WireframeRS);
break;
} IcosahedronTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
md3dImmediateContext->DrawIndexed(mIcosahedronIndexCount, 0, 0); // Restore default render state.
md3dImmediateContext->RSSetState(0);
} HR(mSwapChain->Present(0, 0));
} void Icosahedron::OnMouseDown(WPARAM btnState, int x, int y)
{
mLastMousePos.x = x;
mLastMousePos.y = y; SetCapture(mhMainWnd);
} void Icosahedron::OnMouseUp(WPARAM btnState, int x, int y)
{
ReleaseCapture();
} void Icosahedron::OnMouseMove(WPARAM btnState, int x, int y)
{
if ((btnState & MK_LBUTTON) != 0)
{
// Make each pixel correspond to a quater of a degree.
float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x));
float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y)); // Update angles based on input to orbit camera around box.
mTheta += dx;
mPhi += dy; // Restric the angle mPhi.
mPhi = MathHelper::Clamp(mPhi, 0.1f, MathHelper::Pi - 0.1f);
}
else if ((btnState & MK_RBUTTON) != 0)
{
// Make each pixel correspond to 0.01 unit in the scene.
float dx = 0.1f*static_cast<float>(x - mLastMousePos.x);
float dy = 0.1f*static_cast<float>(y - mLastMousePos.y); //Update the camera radius based on inputs.
mRadius += dx - dy; // Restrict the radius.
mRadius = MathHelper::Clamp(mRadius, 10.0f, 500.0f);
} mLastMousePos.x = x;
mLastMousePos.y = y;
} void Icosahedron::BuildIcosahedronGeometryBuffers()
{
GeometryGenerator::MeshData icosahedron; GeometryGenerator geoGen;
geoGen.CreateGeosphere(1.0f, 0u, icosahedron); //
// Extract the vertex elements we are interested in and pack the
// vertices of all the meshes into one vertex buffer
// std::vector<Vertex::Basic32> vertices(icosahedron.Vertices.size()); for (UINT i = 0; i < icosahedron.Vertices.size(); ++i)
{
vertices[i].Pos = icosahedron.Vertices[i].Position;
vertices[i].Normal = icosahedron.Vertices[i].Normal;
vertices[i].Tex = icosahedron.Vertices[i].TexC;
} D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(Vertex::Basic32) * icosahedron.Vertices.size();
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = &vertices[0];
HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &mIcosahedronVB)); //
// Pack the indices of all the meshes into one index buffer.
// D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_IMMUTABLE;
ibd.ByteWidth = sizeof(UINT)* icosahedron.Indices.size();
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA iinitData;
iinitData.pSysMem = &icosahedron.Indices[0];
mIcosahedronIndexCount = icosahedron.Indices.size();
HR(md3dDevice->CreateBuffer(&ibd, &iinitData, &mIcosahedronIB));
}
RenderStates.cpp
#include "RenderStates.h" ID3D11RasterizerState* RenderStates::WireframeRS = 0;
ID3D11RasterizerState* RenderStates::NoCullRS = 0;
ID3D11RasterizerState* RenderStates::CullClockwiseRS = 0; ID3D11BlendState* RenderStates::AlphaToCoverageBS = 0;
ID3D11BlendState* RenderStates::TransparentBS = 0;
ID3D11BlendState* RenderStates::NoRenderTargetWritesBS = 0; void RenderStates::InitAll(ID3D11Device* device)
{
//
// WireframeRS
//
D3D11_RASTERIZER_DESC wireframeDesc;
ZeroMemory(&wireframeDesc, sizeof(D3D11_RASTERIZER_DESC));
wireframeDesc.FillMode = D3D11_FILL_WIREFRAME;
wireframeDesc.CullMode = D3D11_CULL_BACK;
wireframeDesc.FrontCounterClockwise = false;
wireframeDesc.DepthClipEnable = true; HR(device->CreateRasterizerState(&wireframeDesc, &WireframeRS)); //
// NoCullRS
//
D3D11_RASTERIZER_DESC noCullDesc;
ZeroMemory(&noCullDesc, sizeof(D3D11_RASTERIZER_DESC));
noCullDesc.FillMode = D3D11_FILL_SOLID;
noCullDesc.CullMode = D3D11_CULL_NONE;
noCullDesc.FrontCounterClockwise = false;
noCullDesc.DepthClipEnable = true; HR(device->CreateRasterizerState(&noCullDesc, &NoCullRS)); //
// CullClockwiseRS
// // Note: Define such that we still cull backfaces by making front faces CCW.
// If we did not cull bacefaces, then we have to worry about the BackFace
// property in the D3D11_DEPTH_STENCIL_DESC
D3D11_RASTERIZER_DESC cullClockwiseDesc;
ZeroMemory(&cullClockwiseDesc, sizeof(D3D11_RASTERIZER_DESC));
cullClockwiseDesc.FillMode = D3D11_FILL_SOLID;
cullClockwiseDesc.CullMode = D3D11_CULL_BACK;
cullClockwiseDesc.FrontCounterClockwise = true;
cullClockwiseDesc.DepthClipEnable = true; HR(device->CreateRasterizerState(&cullClockwiseDesc, &CullClockwiseRS)); //
// AlphaToCoverageBS
// D3D11_BLEND_DESC alphaToCoverageDesc = { 0 };
alphaToCoverageDesc.AlphaToCoverageEnable = true;
alphaToCoverageDesc.IndependentBlendEnable = false;
alphaToCoverageDesc.RenderTarget[0].BlendEnable = false;
alphaToCoverageDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; HR(device->CreateBlendState(&alphaToCoverageDesc, &AlphaToCoverageBS)); //
// TransparentBS
// D3D11_BLEND_DESC transparentDesc = { 0 };
transparentDesc.AlphaToCoverageEnable = false;
transparentDesc.IndependentBlendEnable = false; transparentDesc.RenderTarget[0].BlendEnable = true;
transparentDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
transparentDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
transparentDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
transparentDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
transparentDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
transparentDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
transparentDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; HR(device->CreateBlendState(&transparentDesc, &TransparentBS)); //
//NoRenderTargetWritesBS
// D3D11_BLEND_DESC noRenderTargetWritesDesc = { 0 };
noRenderTargetWritesDesc.AlphaToCoverageEnable = false;
noRenderTargetWritesDesc.IndependentBlendEnable = false; noRenderTargetWritesDesc.RenderTarget[0].BlendEnable = false;
noRenderTargetWritesDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
noRenderTargetWritesDesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
noRenderTargetWritesDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
noRenderTargetWritesDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
noRenderTargetWritesDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
noRenderTargetWritesDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
noRenderTargetWritesDesc.RenderTarget[0].RenderTargetWriteMask = 0; HR(device->CreateBlendState(&noRenderTargetWritesDesc, &NoRenderTargetWritesBS));
} void RenderStates::DestroyAll()
{
ReleaseCOM(WireframeRS);
ReleaseCOM(NoCullRS);
ReleaseCOM(CullClockwiseRS); ReleaseCOM(AlphaToCoverageBS);
ReleaseCOM(TransparentBS);
ReleaseCOM(NoRenderTargetWritesBS);
}
Vertex.cpp
#include "Vertex.h"
#include "Effects.h" #pragma region InputLayoutDesc const D3D11_INPUT_ELEMENT_DESC InputLayoutDesc::Basic32[3] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }
}; #pragma endregion #pragma region InputLayouts ID3D11InputLayout* InputLayouts::Basic32 = 0; void InputLayouts::InitAll(ID3D11Device* device)
{
D3DX11_PASS_DESC passDesc; //
// Basic32
// Effects::BasicFX->Light1Tech->GetPassByIndex(0)->GetDesc(&passDesc);
HR(device->CreateInputLayout(InputLayoutDesc::Basic32, 3, passDesc.pIAInputSignature,
passDesc.IAInputSignatureSize, &Basic32));
} void InputLayouts::DestroyAll()
{
ReleaseCOM(Basic32);
} #pragma endregion

Introdution to 3D Game Programming With DirectX11 第11章 习题解答

Introdution to 3D Game Programming With DirectX11 第11章 习题解答

Introdution to 3D Game Programming With DirectX11 第11章 习题解答

Introdution to 3D Game Programming With DirectX11 第11章 习题解答

Introdution to 3D Game Programming With DirectX11 第11章 习题解答

Introdution to 3D Game Programming With DirectX11 第11章 习题解答

11.3 那个primitiveID用的有点问题,GS的第一个參数用了个数组,所以primitiveID依照数组的第一个元素设置了

void Explosion(VertexOut inVerts[3], uint primID : SV_PrimitiveID, inout TriangleStream<GeoOut> triStream)
{
VertexOut explosionVerts[3];
GeoOut gout[3];
float3 u = inVerts[1].PosL - inVerts[0].PosL;
float3 v = inVerts[2].PosL - inVerts[0].PosL;
float3 n = cross(u, v);
[unroll]
for (int i = 0; i < 3; ++i)
{
explosionVerts[i].PosL = inVerts[i].PosL + /*primID * */gScale * gTime * n;
// Transorm to world space space.
gout[i].PosW = mul(float4(explosionVerts[i].PosL, 1.0f), gWorld).xyz;
gout[i].NormalW = mul(normalize(explosionVerts[i].PosL), (float3x3)gWorldInvTranspose); // Transform to homogeneous clip space.
gout[i].PosH = mul(float4(explosionVerts[i].PosL, 1.0f), gWorldViewProj); gout[i].Tex = inVerts[i].Tex;
} [unroll]
for (int j = 0; j < 3; ++j)
{
triStream.Append(gout[j]);
}
} [maxvertexcount(24)]
void GS(triangle VertexOut gin[3], uint primID : SV_PrimitiveID, inout TriangleStream<GeoOut> triStream)
{ if (length(gEyePosW) >= 30)
{
//VertexOut v[3];
//SubdivideZero(gin, v);
//OutputSubdivisionZero(v, triStream);
Explosion(gin, primID, triStream);
}
else if ((length(gEyePosW) >= 15))
{
VertexOut v[6];
Subdivide(gin, v);
OutputSubdivision(v, triStream);
}else
{
VertexOut v[15];
SubdivideTwice(gin, v);
OutputSubdivisionTwice(v, triStream);
}
}
    if (GetAsyncKeyState('E') & 0x8000)
{
fExpTimeBase = mTimer.TotalTime();
bExplosion = true;
} if (GetAsyncKeyState('F') & 0x8000)
fScale++;
}
    Effects::BasicFX->SetExpTime(mExpTime);
Effects::BasicFX->SetExplosionScalar(fScale);

和上一题比,代码变动不大

Introdution to 3D Game Programming With DirectX11 第11章 习题解答

Introdution to 3D Game Programming With DirectX11 第11章 习题解答

Introdution to 3D Game Programming With DirectX11 第11章 习题解答

Introdution to 3D Game Programming With DirectX11 第11章 习题解答

由于有爆炸效果,所以做了个gif,可能网页上看不到,下载就能看到

11.4代码写的非常乱,变量名设定的也不合适,但还好,效果出来了

//=============================================================================
// Basic.fx by Frank Luna (C) 2011 All Rights Reserved.
//
// Basic effect that currently supports transformations, lighting, and texturing.
//============================================================================= #include "LightHelper.fx" cbuffer cbPerFrame
{
DirectionalLight gDirLights[3];
float3 gEyePosW; float gFogStart;
float gFogRange;
float4 gFogColor;
}; cbuffer cbPerObject
{
float4x4 gWorld;
float4x4 gWorldInvTranspose;
float4x4 gWorldViewProj;
float4x4 gTexTransform;
Material gMaterial; }; // Nonnumeric values cannot be added to a cbuffer.
Texture2D gDiffuseMap; SamplerState samAnisotropic
{
Filter = ANISOTROPIC;
MaxAnisotropy = 4; AddressU = WRAP;
AddressV = WRAP;
}; struct VertexIn
{
float3 PosL : POSITION;
float3 NormalL : NORMAL;
float2 Tex : TEXCOORD;
}; struct VertexOut
{
float4 PosH : SV_POSITION;
float3 PosW : POSITION;
float3 NormalW : NORMAL;
float2 Tex : TEXCOORD;
}; struct GeoOut
{
float4 PosH : SV_POSITION;
float3 PosW : POSITION;
float3 NormalW : NORMAL;
float2 Tex : TEXCOORD;
}; VertexOut VS(VertexIn vin)
{
VertexOut vout; // Transform to world space space.
vout.PosW = mul(float4(vin.PosL, 1.0f), gWorld).xyz;
vout.NormalW = mul(vin.NormalL, (float3x3)gWorldInvTranspose); // Transform to homogeneous clip space.
vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj); // Output vertex attributes for interpolation across triangle.
vout.Tex = mul(float4(vin.Tex, 0.0f, 1.0f), gTexTransform).xy;
return vout;
} VertexOut VSONE(VertexIn vin)
{
VertexOut vout; // Transform to world space space.
vout.PosW = vin.PosL;
vout.NormalW = vin.NormalL; // Transform to homogeneous clip space.
vout.PosH = (vin.PosL, 1.0f); // Output vertex attributes for interpolation across triangle.
vout.Tex = vin.Tex;
return vout;
} [maxvertexcount(3)]
void GS(point VertexOut gin[1], inout LineStream<GeoOut> lineStream)
{
GeoOut gout[2];
gout[0].PosH = mul(float4(gin[0].PosW, 1.0f), gWorldViewProj);
gout[0].PosW = mul(float4(gin[0].PosW, 1.0f), gWorld).xyz;
gout[0].NormalW = mul(gin[0].NormalW, (float3x3)gWorldInvTranspose);
gout[0].Tex = mul(float4(gin[0].Tex, 0.0f, 1.0f), gTexTransform).xy;
gout[1].PosW = mul(float4((gin[0].PosW + gin[0].NormalW), 1.0f), gWorld).xyz;
gout[1].NormalW = mul(normalize((gin[0].PosW + gin[0].NormalW)), (float3x3)gWorldInvTranspose);
gout[1].PosH = mul(float4((gin[0].PosW + gin[0].NormalW), 1.0f), gWorldViewProj);
gout[1].Tex = gout[0].Tex; lineStream.Append(gout[1]);
lineStream.Append(gout[0]); } float4 PS(GeoOut pin, uniform int gLightCount, uniform bool gUseTexure, uniform bool gAlphaClip, uniform bool gFogEnabled) : SV_Target
{
// Interpolating normal can unnormalize it, so normalize it.
pin.NormalW = normalize(pin.NormalW); // The toEye vector is used in lighting.
float3 toEye = gEyePosW - pin.PosW; // Cache the distance to the eye from this surface point.
float distToEye = length(toEye); // Normalize.
toEye /= distToEye; // Default to multiplicative identity.
float4 texColor = float4(1, 1, 1, 1);
if(gUseTexure)
{
// Sample texture.
texColor = gDiffuseMap.Sample( samAnisotropic, pin.Tex ); if(gAlphaClip)
{
// Discard pixel if texture alpha < 0.1. Note that we do this
// test as soon as possible so that we can potentially exit the shader
// early, thereby skipping the rest of the shader code.
clip(texColor.a - 0.1f);
}
} //
// Lighting.
// float4 litColor = texColor;
if( gLightCount > 0 )
{
// Start with a sum of zero.
float4 ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
float4 diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
float4 spec = float4(0.0f, 0.0f, 0.0f, 0.0f); // Sum the light contribution from each light source.
[unroll]
for(int i = 0; i < gLightCount; ++i)
{
float4 A, D, S;
ComputeDirectionalLight(gMaterial, gDirLights[i], pin.NormalW, toEye,
A, D, S); ambient += A;
diffuse += D;
spec += S;
} // Modulate with late add.
litColor = texColor*(ambient + diffuse) + spec;
} //
// Fogging
// if( gFogEnabled )
{
float fogLerp = saturate( (distToEye - gFogStart) / gFogRange ); // Blend the fog color and the lit color.
litColor = lerp(litColor, gFogColor, fogLerp);
} // Common to take alpha from diffuse material and texture.
litColor.a = gMaterial.Diffuse.a * texColor.a; return litColor;
} technique11 Light1
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VSONE() ) );
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(1, false, false, false) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(1, false, false, false)));
}
} technique11 Light2
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(2, false, false, false) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(2, false, false, false)));
}
} technique11 Light3
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(3, false, false, false) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(3, false, false, false)));
}
} technique11 Light0Tex
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(0, true, false, false) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(0, true, false, false)));
}
} technique11 Light1Tex
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(1, true, false, false) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(1, true, false, false)));
}
} technique11 Light2Tex
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(2, true, false, false) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(2, true, false, false)));
}
} technique11 Light3Tex
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(3, true, false, false) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(3, true, false, false)));
}
} technique11 Light0TexAlphaClip
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(0, true, true, false) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(0, true, true, false)));
}
} technique11 Light1TexAlphaClip
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(1, true, true, false) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(1, true, true, false)));
}
} technique11 Light2TexAlphaClip
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(2, true, true, false) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(2, true, true, false)));
}
} technique11 Light3TexAlphaClip
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(3, true, true, false) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(3, true, true, false)));
}
} technique11 Light1Fog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(1, false, false, true) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(1, false, false, true)));
}
} technique11 Light2Fog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(2, false, false, true) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(2, false, false, true)));
}
} technique11 Light3Fog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(3, false, false, true) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(3, false, false, true)));
}
} technique11 Light0TexFog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(0, true, false, true) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(0, true, false, true)));
}
} technique11 Light1TexFog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(1, true, false, true) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(1, true, false, true)));
}
} technique11 Light2TexFog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(2, true, false, true) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(2, true, false, true)));
}
} technique11 Light3TexFog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(3, true, false, true) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(3, true, false, true)));
}
} technique11 Light0TexAlphaClipFog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(0, true, true, true) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(0, true, true, true)));
}
} technique11 Light1TexAlphaClipFog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(1, true, true, true) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(1, true, true, true)));
}
} technique11 Light2TexAlphaClipFog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(2, true, true, true) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(2, true, true, true)));
}
} technique11 Light3TexAlphaClipFog
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSONE()));
SetGeometryShader( CompileShader(gs_5_0, GS()) );
SetPixelShader( CompileShader( ps_5_0, PS(3, true, true, true) ) );
} pass P1
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS(3, true, true, true)));
}
}
//***************************************************************************************
// BlendDemo.cpp by Frank Luna (C) 2011 All Rights Reserved.
//
// Demonstrates blending, HLSL clip(), and fogging.
//
// Controls:
// Hold the left mouse button down and move the mouse to rotate.
// Hold the right mouse button down to zoom in and out.
//
// Press '1' - Lighting only render mode.
// Press '2' - Texture render mode.
// Press '3' - Fog render mode.
//
//*************************************************************************************** #include "d3dApp.h"
#include "d3dx11Effect.h"
#include "GeometryGenerator.h"
#include "MathHelper.h"
#include "LightHelper.h"
#include "Effects.h"
#include "Vertex.h"
#include "RenderStates.h"
#include "Waves.h" enum RenderOptions
{
Lighting = 0,
Textures = 1,
TexturesAndFog = 2
}; class BlendApp : public D3DApp
{
public:
BlendApp(HINSTANCE hInstance);
~BlendApp(); bool Init();
void OnResize();
void UpdateScene(float dt);
void DrawScene(); void OnMouseDown(WPARAM btnState, int x, int y);
void OnMouseUp(WPARAM btnState, int x, int y);
void OnMouseMove(WPARAM btnState, int x, int y); private:
float GetHillHeight(float x, float z)const;
XMFLOAT3 GetHillNormal(float x, float z)const;
void BuildLandGeometryBuffers();
void BuildWaveGeometryBuffers();
void BuildCrateGeometryBuffers(); private:
ID3D11Buffer* mLandVB;
ID3D11Buffer* mLandIB; ID3D11Buffer* mWavesVB;
ID3D11Buffer* mWavesIB; ID3D11Buffer* mBoxVB;
ID3D11Buffer* mBoxIB; ID3D11ShaderResourceView* mGrassMapSRV;
ID3D11ShaderResourceView* mWavesMapSRV;
ID3D11ShaderResourceView* mBoxMapSRV; Waves mWaves; DirectionalLight mDirLights[3];
Material mLandMat;
Material mWavesMat;
Material mBoxMat; XMFLOAT4X4 mGrassTexTransform;
XMFLOAT4X4 mWaterTexTransform;
XMFLOAT4X4 mLandWorld;
XMFLOAT4X4 mWavesWorld;
XMFLOAT4X4 mBoxWorld; XMFLOAT4X4 mView;
XMFLOAT4X4 mProj; UINT mLandIndexCount; XMFLOAT2 mWaterTexOffset; RenderOptions mRenderOptions; XMFLOAT3 mEyePosW; float mTheta;
float mPhi;
float mRadius; POINT mLastMousePos;
}; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
PSTR cmdLine, int showCmd)
{
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif BlendApp theApp(hInstance); if( !theApp.Init() )
return 0; return theApp.Run();
} BlendApp::BlendApp(HINSTANCE hInstance)
: D3DApp(hInstance), mLandVB(0), mLandIB(0), mWavesVB(0), mWavesIB(0), mBoxVB(0), mBoxIB(0), mGrassMapSRV(0), mWavesMapSRV(0), mBoxMapSRV(0),
mWaterTexOffset(0.0f, 0.0f), mEyePosW(0.0f, 0.0f, 0.0f), mLandIndexCount(0), mRenderOptions(RenderOptions::TexturesAndFog),
mTheta(1.3f*MathHelper::Pi), mPhi(0.4f*MathHelper::Pi), mRadius(80.0f)
{
mMainWndCaption = L"Blend Demo";
mEnable4xMsaa = false; mLastMousePos.x = 0;
mLastMousePos.y = 0; XMMATRIX I = XMMatrixIdentity();
XMStoreFloat4x4(&mLandWorld, I);
XMStoreFloat4x4(&mWavesWorld, I);
XMStoreFloat4x4(&mView, I);
XMStoreFloat4x4(&mProj, I); XMMATRIX boxScale = XMMatrixScaling(15.0f, 15.0f, 15.0f);
XMMATRIX boxOffset = XMMatrixTranslation(8.0f, 5.0f, -15.0f);
XMStoreFloat4x4(&mBoxWorld, boxScale*boxOffset); XMMATRIX grassTexScale = XMMatrixScaling(5.0f, 5.0f, 0.0f);
XMStoreFloat4x4(&mGrassTexTransform, grassTexScale); mDirLights[0].Ambient = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f);
mDirLights[0].Diffuse = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
mDirLights[0].Specular = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
mDirLights[0].Direction = XMFLOAT3(0.57735f, -0.57735f, 0.57735f); mDirLights[1].Ambient = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
mDirLights[1].Diffuse = XMFLOAT4(0.20f, 0.20f, 0.20f, 1.0f);
mDirLights[1].Specular = XMFLOAT4(0.25f, 0.25f, 0.25f, 1.0f);
mDirLights[1].Direction = XMFLOAT3(-0.57735f, -0.57735f, 0.57735f); mDirLights[2].Ambient = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
mDirLights[2].Diffuse = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f);
mDirLights[2].Specular = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
mDirLights[2].Direction = XMFLOAT3(0.0f, -0.707f, -0.707f); mLandMat.Ambient = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
mLandMat.Diffuse = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
mLandMat.Specular = XMFLOAT4(0.2f, 0.2f, 0.2f, 16.0f); mWavesMat.Ambient = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
mWavesMat.Diffuse = XMFLOAT4(1.0f, 1.0f, 1.0f, 0.5f);
mWavesMat.Specular = XMFLOAT4(0.8f, 0.8f, 0.8f, 32.0f); mBoxMat.Ambient = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
mBoxMat.Diffuse = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
mBoxMat.Specular = XMFLOAT4(0.4f, 0.4f, 0.4f, 16.0f);
} BlendApp::~BlendApp()
{
md3dImmediateContext->ClearState();
ReleaseCOM(mLandVB);
ReleaseCOM(mLandIB);
ReleaseCOM(mWavesVB);
ReleaseCOM(mWavesIB);
ReleaseCOM(mBoxVB);
ReleaseCOM(mBoxIB);
ReleaseCOM(mGrassMapSRV);
ReleaseCOM(mWavesMapSRV);
ReleaseCOM(mBoxMapSRV); Effects::DestroyAll();
InputLayouts::DestroyAll();
RenderStates::DestroyAll();
} bool BlendApp::Init()
{
if(!D3DApp::Init())
return false; mWaves.Init(160, 160, 1.0f, 0.03f, 5.0f, 0.3f); // Must init Effects first since InputLayouts depend on shader signatures.
Effects::InitAll(md3dDevice);
InputLayouts::InitAll(md3dDevice);
RenderStates::InitAll(md3dDevice); HR(D3DX11CreateShaderResourceViewFromFile(md3dDevice,
L"Textures/grass.dds", 0, 0, &mGrassMapSRV, 0 )); HR(D3DX11CreateShaderResourceViewFromFile(md3dDevice,
L"Textures/water2.dds", 0, 0, &mWavesMapSRV, 0 )); HR(D3DX11CreateShaderResourceViewFromFile(md3dDevice,
L"Textures/WireFence.dds", 0, 0, &mBoxMapSRV, 0 )); BuildLandGeometryBuffers();
BuildWaveGeometryBuffers();
BuildCrateGeometryBuffers(); return true;
} void BlendApp::OnResize()
{
D3DApp::OnResize(); XMMATRIX P = XMMatrixPerspectiveFovLH(0.25f*MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
XMStoreFloat4x4(&mProj, P);
} void BlendApp::UpdateScene(float dt)
{
// Convert Spherical to Cartesian coordinates.
float x = mRadius*sinf(mPhi)*cosf(mTheta);
float z = mRadius*sinf(mPhi)*sinf(mTheta);
float y = mRadius*cosf(mPhi); mEyePosW = XMFLOAT3(x, y, z); // Build the view matrix.
XMVECTOR pos = XMVectorSet(x, y, z, 1.0f);
XMVECTOR target = XMVectorZero();
XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); XMMATRIX V = XMMatrixLookAtLH(pos, target, up);
XMStoreFloat4x4(&mView, V); //
// Every quarter second, generate a random wave.
//
static float t_base = 0.0f;
if( (mTimer.TotalTime() - t_base) >= 0.1f )
{
t_base += 0.1f; DWORD i = 5 + rand() % (mWaves.RowCount()-10);
DWORD j = 5 + rand() % (mWaves.ColumnCount()-10); float r = MathHelper::RandF(0.5f, 1.0f); mWaves.Disturb(i, j, r);
} mWaves.Update(dt); //
// Update the wave vertex buffer with the new solution.
// D3D11_MAPPED_SUBRESOURCE mappedData;
HR(md3dImmediateContext->Map(mWavesVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedData)); Vertex::Basic32* v = reinterpret_cast<Vertex::Basic32*>(mappedData.pData);
for(UINT i = 0; i < mWaves.VertexCount(); ++i)
{
v[i].Pos = mWaves[i];
v[i].Normal = mWaves.Normal(i); // Derive tex-coords in [0,1] from position.
v[i].Tex.x = 0.5f + mWaves[i].x / mWaves.Width();
v[i].Tex.y = 0.5f - mWaves[i].z / mWaves.Depth();
} md3dImmediateContext->Unmap(mWavesVB, 0); //
// Animate water texture coordinates.
// // Tile water texture.
XMMATRIX wavesScale = XMMatrixScaling(5.0f, 5.0f, 0.0f); // Translate texture over time.
mWaterTexOffset.y += 0.05f*dt;
mWaterTexOffset.x += 0.1f*dt;
XMMATRIX wavesOffset = XMMatrixTranslation(mWaterTexOffset.x, mWaterTexOffset.y, 0.0f); // Combine scale and translation.
XMStoreFloat4x4(&mWaterTexTransform, wavesScale*wavesOffset); //
// Switch the render mode based in key input.
//
if( GetAsyncKeyState('1') & 0x8000 )
mRenderOptions = RenderOptions::Lighting; if( GetAsyncKeyState('2') & 0x8000 )
mRenderOptions = RenderOptions::Textures; if( GetAsyncKeyState('3') & 0x8000 )
mRenderOptions = RenderOptions::TexturesAndFog;
} void BlendApp::DrawScene()
{
md3dImmediateContext->ClearRenderTargetView(mRenderTargetView, reinterpret_cast<const float*>(&Colors::Silver));
md3dImmediateContext->ClearDepthStencilView(mDepthStencilView, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0); md3dImmediateContext->IASetInputLayout(InputLayouts::Basic32);
//md3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); float blendFactor[] = {0.0f, 0.0f, 0.0f, 0.0f}; UINT stride = sizeof(Vertex::Basic32);
UINT offset = 0; XMMATRIX view = XMLoadFloat4x4(&mView);
XMMATRIX proj = XMLoadFloat4x4(&mProj);
XMMATRIX viewProj = view*proj; // Set per frame constants.
Effects::BasicFX->SetDirLights(mDirLights);
Effects::BasicFX->SetEyePosW(mEyePosW);
Effects::BasicFX->SetFogColor(Colors::Silver);
Effects::BasicFX->SetFogStart(15.0f);
Effects::BasicFX->SetFogRange(175.0f); ID3DX11EffectTechnique* boxTech;
ID3DX11EffectTechnique* landAndWavesTech; switch(mRenderOptions)
{
case RenderOptions::Lighting:
boxTech = Effects::BasicFX->Light3Tech;
landAndWavesTech = Effects::BasicFX->Light3Tech;
break;
case RenderOptions::Textures:
boxTech = Effects::BasicFX->Light3TexAlphaClipTech;
landAndWavesTech = Effects::BasicFX->Light3TexTech;
break;
case RenderOptions::TexturesAndFog:
boxTech = Effects::BasicFX->Light3TexAlphaClipFogTech;
landAndWavesTech = Effects::BasicFX->Light3TexFogTech;
break;
} D3DX11_TECHNIQUE_DESC techDesc; //
// Draw the box with alpha clipping.
// boxTech->GetDesc( &techDesc );
for(UINT p = 0; p < techDesc.Passes; ++p)
{
if (0 == p)
{
md3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
}
else
{
md3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
} md3dImmediateContext->IASetVertexBuffers(0, 1, &mBoxVB, &stride, &offset);
md3dImmediateContext->IASetIndexBuffer(mBoxIB, DXGI_FORMAT_R32_UINT, 0); // Set per object constants.
XMMATRIX world = XMLoadFloat4x4(&mBoxWorld);
XMMATRIX worldInvTranspose = MathHelper::InverseTranspose(world);
XMMATRIX worldViewProj = world*view*proj; Effects::BasicFX->SetWorld(world);
Effects::BasicFX->SetWorldInvTranspose(worldInvTranspose);
Effects::BasicFX->SetWorldViewProj(worldViewProj);
Effects::BasicFX->SetTexTransform(XMMatrixIdentity());
Effects::BasicFX->SetMaterial(mBoxMat);
Effects::BasicFX->SetDiffuseMap(mBoxMapSRV); md3dImmediateContext->RSSetState(RenderStates::NoCullRS);
boxTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
md3dImmediateContext->DrawIndexed(36, 0, 0); // Restore default render state.
md3dImmediateContext->RSSetState(0);
} //
// Draw the hills and water with texture and fog (no alpha clipping needed).
// landAndWavesTech->GetDesc( &techDesc );
for(UINT p = 0; p < techDesc.Passes; ++p)
{
if (0 == p)
{
md3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
}
else
{
md3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
}
//
// Draw the hills.
//
md3dImmediateContext->IASetVertexBuffers(0, 1, &mLandVB, &stride, &offset);
md3dImmediateContext->IASetIndexBuffer(mLandIB, DXGI_FORMAT_R32_UINT, 0); // Set per object constants.
XMMATRIX world = XMLoadFloat4x4(&mLandWorld);
XMMATRIX worldInvTranspose = MathHelper::InverseTranspose(world);
XMMATRIX worldViewProj = world*view*proj; Effects::BasicFX->SetWorld(world);
Effects::BasicFX->SetWorldInvTranspose(worldInvTranspose);
Effects::BasicFX->SetWorldViewProj(worldViewProj);
Effects::BasicFX->SetTexTransform(XMLoadFloat4x4(&mGrassTexTransform));
Effects::BasicFX->SetMaterial(mLandMat);
Effects::BasicFX->SetDiffuseMap(mGrassMapSRV); landAndWavesTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
md3dImmediateContext->DrawIndexed(mLandIndexCount, 0, 0); //
// Draw the waves.
//
md3dImmediateContext->IASetVertexBuffers(0, 1, &mWavesVB, &stride, &offset);
md3dImmediateContext->IASetIndexBuffer(mWavesIB, DXGI_FORMAT_R32_UINT, 0); // Set per object constants.
world = XMLoadFloat4x4(&mWavesWorld);
worldInvTranspose = MathHelper::InverseTranspose(world);
worldViewProj = world*view*proj; Effects::BasicFX->SetWorld(world);
Effects::BasicFX->SetWorldInvTranspose(worldInvTranspose);
Effects::BasicFX->SetWorldViewProj(worldViewProj);
Effects::BasicFX->SetTexTransform(XMLoadFloat4x4(&mWaterTexTransform));
Effects::BasicFX->SetMaterial(mWavesMat);
Effects::BasicFX->SetDiffuseMap(mWavesMapSRV); md3dImmediateContext->OMSetBlendState(RenderStates::TransparentBS, blendFactor, 0xffffffff);
landAndWavesTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
md3dImmediateContext->DrawIndexed(3*mWaves.TriangleCount(), 0, 0); // Restore default blend state
md3dImmediateContext->OMSetBlendState(0, blendFactor, 0xffffffff);
} HR(mSwapChain->Present(0, 0));
} void BlendApp::OnMouseDown(WPARAM btnState, int x, int y)
{
mLastMousePos.x = x;
mLastMousePos.y = y; SetCapture(mhMainWnd);
} void BlendApp::OnMouseUp(WPARAM btnState, int x, int y)
{
ReleaseCapture();
} void BlendApp::OnMouseMove(WPARAM btnState, int x, int y)
{
if( (btnState & MK_LBUTTON) != 0 )
{
// Make each pixel correspond to a quarter of a degree.
float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x));
float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y)); // Update angles based on input to orbit camera around box.
mTheta += dx;
mPhi += dy; // Restrict the angle mPhi.
mPhi = MathHelper::Clamp(mPhi, 0.1f, MathHelper::Pi-0.1f);
}
else if( (btnState & MK_RBUTTON) != 0 )
{
// Make each pixel correspond to 0.01 unit in the scene.
float dx = 0.1f*static_cast<float>(x - mLastMousePos.x);
float dy = 0.1f*static_cast<float>(y - mLastMousePos.y); // Update the camera radius based on input.
mRadius += dx - dy; // Restrict the radius.
mRadius = MathHelper::Clamp(mRadius, 20.0f, 500.0f);
} mLastMousePos.x = x;
mLastMousePos.y = y;
} float BlendApp::GetHillHeight(float x, float z)const
{
return 0.3f*( z*sinf(0.1f*x) + x*cosf(0.1f*z) );
} XMFLOAT3 BlendApp::GetHillNormal(float x, float z)const
{
// n = (-df/dx, 1, -df/dz)
XMFLOAT3 n(
-0.03f*z*cosf(0.1f*x) - 0.3f*cosf(0.1f*z),
1.0f,
-0.3f*sinf(0.1f*x) + 0.03f*x*sinf(0.1f*z)); XMVECTOR unitNormal = XMVector3Normalize(XMLoadFloat3(&n));
XMStoreFloat3(&n, unitNormal); return n;
} void BlendApp::BuildLandGeometryBuffers()
{
GeometryGenerator::MeshData grid; GeometryGenerator geoGen; geoGen.CreateGrid(160.0f, 160.0f, 50, 50, grid); mLandIndexCount = grid.Indices.size(); //
// Extract the vertex elements we are interested and apply the height function to
// each vertex.
// std::vector<Vertex::Basic32> vertices(grid.Vertices.size());
for(UINT i = 0; i < grid.Vertices.size(); ++i)
{
XMFLOAT3 p = grid.Vertices[i].Position; p.y = GetHillHeight(p.x, p.z); vertices[i].Pos = p;
vertices[i].Normal = GetHillNormal(p.x, p.z);
vertices[i].Tex = grid.Vertices[i].TexC;
} D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(Vertex::Basic32) * grid.Vertices.size();
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = &vertices[0];
HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &mLandVB)); //
// Pack the indices of all the meshes into one index buffer.
// D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_IMMUTABLE;
ibd.ByteWidth = sizeof(UINT) * mLandIndexCount;
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA iinitData;
iinitData.pSysMem = &grid.Indices[0];
HR(md3dDevice->CreateBuffer(&ibd, &iinitData, &mLandIB));
} void BlendApp::BuildWaveGeometryBuffers()
{
// Create the vertex buffer. Note that we allocate space only, as
// we will be updating the data every time step of the simulation. D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_DYNAMIC;
vbd.ByteWidth = sizeof(Vertex::Basic32) * mWaves.VertexCount();
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
vbd.MiscFlags = 0;
HR(md3dDevice->CreateBuffer(&vbd, 0, &mWavesVB)); // Create the index buffer. The index buffer is fixed, so we only
// need to create and set once. std::vector<UINT> indices(3*mWaves.TriangleCount()); // 3 indices per face // Iterate over each quad.
UINT m = mWaves.RowCount();
UINT n = mWaves.ColumnCount();
int k = 0;
for(UINT i = 0; i < m-1; ++i)
{
for(DWORD j = 0; j < n-1; ++j)
{
indices[k] = i*n+j;
indices[k+1] = i*n+j+1;
indices[k+2] = (i+1)*n+j; indices[k+3] = (i+1)*n+j;
indices[k+4] = i*n+j+1;
indices[k+5] = (i+1)*n+j+1; k += 6; // next quad
}
} D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_IMMUTABLE;
ibd.ByteWidth = sizeof(UINT) * indices.size();
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA iinitData;
iinitData.pSysMem = &indices[0];
HR(md3dDevice->CreateBuffer(&ibd, &iinitData, &mWavesIB));
} void BlendApp::BuildCrateGeometryBuffers()
{
GeometryGenerator::MeshData box; GeometryGenerator geoGen;
geoGen.CreateBox(1.0f, 1.0f, 1.0f, box); //
// Extract the vertex elements we are interested in and pack the
// vertices of all the meshes into one vertex buffer.
// std::vector<Vertex::Basic32> vertices(box.Vertices.size()); for(UINT i = 0; i < box.Vertices.size(); ++i)
{
vertices[i].Pos = box.Vertices[i].Position;
vertices[i].Normal = box.Vertices[i].Normal;
vertices[i].Tex = box.Vertices[i].TexC;
} D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(Vertex::Basic32) * box.Vertices.size();
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = &vertices[0];
HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &mBoxVB)); //
// Pack the indices of all the meshes into one index buffer.
// D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_IMMUTABLE;
ibd.ByteWidth = sizeof(UINT) * box.Indices.size();
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA iinitData;
iinitData.pSysMem = &box.Indices[0];
HR(md3dDevice->CreateBuffer(&ibd, &iinitData, &mBoxIB));
}

Introdution to 3D Game Programming With DirectX11 第11章 习题解答

Introdution to 3D Game Programming With DirectX11 第11章 习题解答

11.6-11.7注意那个DrawIndexed要自己create index buffer,由于是改原有代码,所以也没贴代码,还有要注意的是那个纹理地址越界时開始几个纹理太小了,可能以为全部纹理都一样,事实上不是的,细致看前四个小树,是有差别的