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,由于是改原有代码,所以也没贴代码,还有要注意的是那个纹理地址越界时開始几个纹理太小了,可能以为全部纹理都一样,事实上不是的,细致看前四个小树,是有差别的