The CreateScene function creates the elements making up the 3-D scene. In this sample, the scene consists of a single light, the viewport, the background and surface materials, the three transformation matrices, and the execute buffer holding the state changes and drawing primitives.
static HRESULT
CreateScene(void)
{
HRESULT hRes;
D3DMATERIAL d3dMaterial;
D3DLIGHT d3dLight;
DWORD dwVertexSize;
DWORD dwInstructionSize;
DWORD dwExecuteBufferSize;
D3DEXECUTEBUFFERDESC d3dExecuteBufferDesc;
D3DEXECUTEDATA d3dExecuteData;
ASSERT(NULL != lpd3d);
ASSERT(NULL != lpd3dDevice);
ASSERT(NULL == lpd3dViewport);
ASSERT(NULL == lpd3dMaterial);
ASSERT(NULL == lpd3dBackgroundMaterial);
ASSERT(NULL == lpd3dExecuteBuffer);
ASSERT(NULL == lpd3dLight);
ASSERT(0 == hd3dWorldMatrix);
ASSERT(0 == hd3dViewMatrix);
ASSERT(0 == hd3dProjMatrix);
// Create the light.
hRes = lpd3d->lpVtbl->CreateLight(lpd3d, &lpd3dLight, NULL);
if (FAILED(hRes))
return hRes;
ZeroMemory(&d3dLight, sizeof(d3dLight));
d3dLight.dwSize = sizeof(d3dLight);
d3dLight.dltType = D3DLIGHT_POINT;
d3dLight.dcvColor.dvR = D3DVAL( 1.0);
d3dLight.dcvColor.dvG = D3DVAL( 1.0);
d3dLight.dcvColor.dvB = D3DVAL( 1.0);
d3dLight.dcvColor.dvA = D3DVAL( 1.0);
d3dLight.dvPosition.dvX = D3DVAL( 1.0);
d3dLight.dvPosition.dvY = D3DVAL(-1.0);
d3dLight.dvPosition.dvZ = D3DVAL(-1.0);
d3dLight.dvAttenuation0 = D3DVAL( 1.0);
d3dLight.dvAttenuation1 = D3DVAL( 0.1);
d3dLight.dvAttenuation2 = D3DVAL( 0.0);
hRes = lpd3dLight->lpVtbl->SetLight(lpd3dLight, &d3dLight);
if (FAILED(hRes))
return hRes;
// Create the background material.
hRes = lpd3d->lpVtbl->CreateMaterial(lpd3d,
&lpd3dBackgroundMaterial, NULL);
if (FAILED(hRes))
return hRes;
ZeroMemory(&d3dMaterial, sizeof(d3dMaterial));
d3dMaterial.dwSize = sizeof(d3dMaterial);
d3dMaterial.dcvDiffuse.r = D3DVAL(0.0);
d3dMaterial.dcvDiffuse.g = D3DVAL(0.0);
d3dMaterial.dcvDiffuse.b = D3DVAL(0.0);
d3dMaterial.dcvAmbient.r = D3DVAL(0.0);
d3dMaterial.dcvAmbient.g = D3DVAL(0.0);
d3dMaterial.dcvAmbient.b = D3DVAL(0.0);
d3dMaterial.dcvSpecular.r = D3DVAL(0.0);
d3dMaterial.dcvSpecular.g = D3DVAL(0.0);
d3dMaterial.dcvSpecular.b = D3DVAL(0.0);
d3dMaterial.dvPower = D3DVAL(0.0);
// Since this is the background material, we don't want a ramp to be
// allocated. (We will not be smooth-shading the background.)
d3dMaterial.dwRampSize = 1;
hRes = lpd3dBackgroundMaterial->lpVtbl->SetMaterial
(lpd3dBackgroundMaterial, &d3dMaterial);
if (FAILED(hRes))
return hRes;
hRes = lpd3dBackgroundMaterial->lpVtbl->GetHandle
(lpd3dBackgroundMaterial, lpd3dDevice, &hd3dBackgroundMaterial);
if (FAILED(hRes))
return hRes;
// Create the viewport.
// The viewport parameters are set in the UpdateViewport function,
// which is called in response to WM_SIZE.
hRes = lpd3d->lpVtbl->CreateViewport(lpd3d, &lpd3dViewport, NULL);
if (FAILED(hRes))
return hRes;
hRes = lpd3dDevice->lpVtbl->AddViewport(lpd3dDevice, lpd3dViewport);
if (FAILED(hRes))
return hRes;
hRes = lpd3dViewport->lpVtbl->SetBackground(lpd3dViewport,
hd3dBackgroundMaterial);
if (FAILED(hRes))
return hRes;
hRes = lpd3dViewport->lpVtbl->AddLight(lpd3dViewport, lpd3dLight);
if (FAILED(hRes))
return hRes;
// Create the matrices.
hRes = lpd3dDevice->lpVtbl->CreateMatrix(lpd3dDevice,
&hd3dWorldMatrix);
if (FAILED(hRes))
return hRes;
hRes = lpd3dDevice->lpVtbl->SetMatrix(lpd3dDevice, hd3dWorldMatrix,
&d3dWorldMatrix);
if (FAILED(hRes))
return hRes;
hRes = lpd3dDevice->lpVtbl->CreateMatrix(lpd3dDevice,
&hd3dViewMatrix);
if (FAILED(hRes))
return hRes;
hRes = lpd3dDevice->lpVtbl->SetMatrix(lpd3dDevice, hd3dViewMatrix,
&d3dViewMatrix);
if (FAILED(hRes))
return hRes;
hRes = lpd3dDevice->lpVtbl->CreateMatrix(lpd3dDevice,
&hd3dProjMatrix);
if (FAILED(hRes))
return hRes;
SetPerspectiveProjection(&d3dProjMatrix, HALF_HEIGHT, FRONT_CLIP,
BACK_CLIP);
hRes = lpd3dDevice->lpVtbl->SetMatrix(lpd3dDevice, hd3dProjMatrix,
&d3dProjMatrix);
if (FAILED(hRes))
return hRes;
// Create the surface material.
hRes = lpd3d->lpVtbl->CreateMaterial(lpd3d, &lpd3dMaterial, NULL);
if (FAILED(hRes))
return hRes;
ZeroMemory(&d3dMaterial, sizeof(d3dMaterial));
d3dMaterial.dwSize = sizeof(d3dMaterial);
// Base green with white specular.
d3dMaterial.dcvDiffuse.r = D3DVAL(0.0);
d3dMaterial.dcvDiffuse.g = D3DVAL(1.0);
d3dMaterial.dcvDiffuse.b = D3DVAL(0.0);
d3dMaterial.dcvAmbient.r = D3DVAL(0.0);
d3dMaterial.dcvAmbient.g = D3DVAL(0.4);
d3dMaterial.dcvAmbient.b = D3DVAL(0.0);
d3dMaterial.dcvSpecular.r = D3DVAL(1.0);
d3dMaterial.dcvSpecular.g = D3DVAL(1.0);
d3dMaterial.dcvSpecular.b = D3DVAL(1.0);
d3dMaterial.dvPower = D3DVAL(20.0);
d3dMaterial.dwRampSize = 16;
hRes = lpd3dMaterial->lpVtbl->SetMaterial(lpd3dMaterial,
&d3dMaterial);
if (FAILED(hRes))
return hRes;
hRes = lpd3dMaterial->lpVtbl->GetHandle(lpd3dMaterial, lpd3dDevice,
&hd3dSurfaceMaterial);
if (FAILED(hRes))
return hRes;
// Build the execute buffer.
dwVertexSize = (NUM_VERTICES * sizeof(D3DVERTEX));
dwInstructionSize = (NUM_INSTRUCTIONS * sizeof(D3DINSTRUCTION)) +
(NUM_STATES * sizeof(D3DSTATE)) +
(NUM_PROCESSVERTICES *
sizeof(D3DPROCESSVERTICES)) +
(NUM_TRIANGLES * sizeof(D3DTRIANGLE));
dwExecuteBufferSize = dwVertexSize + dwInstructionSize;
ZeroMemory(&d3dExecuteBufferDesc, sizeof(d3dExecuteBufferDesc));
d3dExecuteBufferDesc.dwSize = sizeof(d3dExecuteBufferDesc);
d3dExecuteBufferDesc.dwFlags = D3DDEB_BUFSIZE;
d3dExecuteBufferDesc.dwBufferSize = dwExecuteBufferSize;
hRes = lpd3dDevice->lpVtbl->CreateExecuteBuffer(lpd3dDevice,
&d3dExecuteBufferDesc, &lpd3dExecuteBuffer, NULL);
if (FAILED(hRes))
return hRes;
// Fill the execute buffer with the required vertices, state
// instructions and drawing primitives.
hRes = FillExecuteBuffer();
if (FAILED(hRes))
return hRes;
// Set the execute data so Direct3D knows how many vertices are in
// the buffer and where the instructions start.
ZeroMemory(&d3dExecuteData, sizeof(d3dExecuteData));
d3dExecuteData.dwSize = sizeof(d3dExecuteData);
d3dExecuteData.dwVertexCount = NUM_VERTICES;
d3dExecuteData.dwInstructionOffset = dwVertexSize;
d3dExecuteData.dwInstructionLength = dwInstructionSize;
hRes = lpd3dExecuteBuffer->lpVtbl->SetExecuteData
(lpd3dExecuteBuffer, &d3dExecuteData);
if (FAILED(hRes))
return hRes;
return DD_OK;
}