zoukankan      html  css  js  c++  java
  • Introdution to 3D Game Programming With DirectX11 第11章 习题解答

    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)));
    	}
    }




    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








    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);

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





    由于有爆炸效果,所以做了个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));
    }




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

  • 相关阅读:
    Java邮件开发(JavaMail)
    SQL删除所有表和数据
    Hyper-V由于虚拟机监控程序未运行
    .NET CORE IIS PUT和DELETE请求失败 405
    ReSharper 快捷键调试
    hyper-v提示监控未运行
    c#定义Ilist集合
    WindowsFormsApp1设置开机自启动
    SQL查询总数和分页数
    EF执行SQL语句
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/3806265.html
Copyright © 2011-2022 走看看