Код и комментарии
8.2.3. Код и комментарии
Относящийся к данному примеру код находится в функции RenderMirror, которая сперва визуализирует примитивы зеркала в буфер трафарета, а затем отображает отражение чайника, но только в том случае, если оно находится в зеркале. Мы исследуем функцию RenderMirror строка за строкой и обсудим что и, самое главное, зачем она делает.
Если в качестве путеводителя вы используете список этапов, приведенный в разделе8.2.2, обратите внимание, что мы начинаем обсуждение с этапа 3, поскольку ни первый ни второй этап не влияют на буфер трафарета. И учтите, что в следующем ниже объяснении мы будем обсуждать только визуализацию зеркал.
Обратите внимание, что обсуждение кода разделено на несколько частей - это сделано только для того, чтобы сделать дискуссию более модульной.
D3DXMATRIX S; D3DXMatrixShadow(&S, &lightDirection, &groundPlane);D3DXMATRIX T; D3DXMatrixTranslation(&T, TeapotPosition.x, TeapotPosition.y, TeapotPosition.z);
D3DXMATRIX W = T * S; Device->SetTransform(D3DTS_WORLD, &W);
После этих действий мы устанавливаем черный материал с 50% прозрачностью, запрещаем проверку глубины, визуализируем тень и возвращаем все к исходному состоянию, вновь включая буфер глубины и запрещая альфа-смешивание и проверку трафарета. Мы отключаем буфер глубины чтобы предотвратить z-конфликты (z-fighting), приводящие к возникновению артефактов изображения, когда в буфере глубины у двух различных поверхностей записано одинаковое значение глубины; механизм визуализации не может определить, какая поверхность должна располагаться поверх другой и может отображать то одну поверхность, то другую. Визуализируя сперва пол и только потом, после отключения проверки глубины, тень мы гарантируем, что тень будет нарисована поверх пола.
ПРИМЕЧАНИЕ
Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true); Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
D3DMATERIAL9 mtrl = d3d::InitMtrl(d3d::BLACK, d3d::BLACK, d3d::BLACK, d3d::BLACK, 0.0f); mtrl.Diffuse.a = 0.5f; // 50% прозрачность
// Отключаем буфер глубины, чтобы предотвратить z-конфликты // при визуализации тени поверх пола Device->SetRenderState(D3DRS_ZENABLE, false);
Device->SetMaterial(&mtrl); Device->SetTexture(0, 0); Teapot->DrawSubset(0);
Device->SetRenderState(D3DRS_ZENABLE, true); Device->SetRenderState(D3DRS_ALPHABLENDENABLE, false); Device->SetRenderState(D3DRS_STENCILENABLE, false); } // конец функции RenderShadow()