Добавление динамического неба в ваш мод

Материал из Valve Developer Community
Перейти к: навигация, поиск
English (en)Русский (ru)
Править
Icon-broom.png
Эта статья или раздел требует улучшения, чтобы соответствовать более высокому стандарту качества потому что:
Перевод можно было сформулировать лучше
Для получения помощи, обратитесь к руководству по редактированию на VDC и процессу очистки на Wikipedia. Также не забудьте проверить наличие заметок, оставленных отмечающим на странице обсуждения этой статьи.
Динамичное небо


Эта статья покажет вам как реализовать динамическое небо в вашем Source 2013 Source 2013 моде.

Note.pngПримечание:Это руководство использует код из отмененного мода Vance
Warning.pngПредупреждение:Этот шейдер очень требовательный и снижает частоту кадров в секунду на 25-40. Поэтому лучше использовать его только на мощных компьютерах

Требования

  • Умение компилировать шейдеры.
  • Умение компилировать решения.


Note.pngПримечание:Если вы не знаете как компилировать шейдеры или еще не работали с ними в Source Source, рекомендуется сначала прочитать и осмыслить эти статьи: Разработка шейдеров & Ваш первый шейдер

Реализация

Прежде чем что-то делать, нам нужно скачать файлы. Они внутри zip-архива.


Когда вы загрузите zip-файл, извлеките файлы из shaders в: 🖿src/materialsystem/stdshaders/, а файлы из code в: 🖿src/game/


Откройте Filesrc/game/client/client_base.vpc Перейдите к строке $File "$SRCDIR\game\client\c_vote_controller.cpp" и под ней добавьте:

$File "c_env_skydome.cpp" $File "c_env_skydome.h"

Далее откройте Filesrc/game/server/server_base.vpc и под $File "$SRCDIR\game\server\vote_controller.cpp" добавьте:

$file "env_skydome.cpp"


И после этого, пересоберите свое Filegames.sln решение.

Теперь мы можем перейти к реализации кода отрисовки.


Код отрисовки

Сначала нам нужно отредактировать код клиента для динамического неба.

Откройте Filesrc/game/client/view.cpp

В функции void CViewRender::Init( void ), под m_ModulateSingleColor.Init( "engine/modulatesinglecolor", TEXTURE_GROUP_OTHER ); добавьте:

m_SkydomeMaterial.Init("shaders/skydome", TEXTURE_GROUP_MODEL);

Теперь откройте Filesrc/game/client/viewrender.h

И под функцией void SetWaterOverlayMaterial( IMaterial *pMaterial ) добавьте:

void DrawSky(const CViewSetup& view);

Найдите CMaterialReference m_UnderWaterOverlayMaterial; и под этим добавьте:

CMaterialReference m_SkydomeMaterial;


Теперь нам нужно создать купол. Чтобы сделать это, откройте Filesrc/game/client/viewrender.cpp

Под #include "sourcevr/isourcevirtualreality.h" добавьте:

#include "c_env_skydome.h"
Note.pngПримечание:Это должно исправить все ошибки с отсутствием определения для g_pSkyDome


Под функцией void CViewRender::DrawViewModels( const CViewSetup &view, bool drawViewmodel ) добавьте:

  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.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78.  
  79.  
  80.  
  81.  
  82.  
  83.  
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
void CViewRender::DrawSky(const CViewSetup& view) { float flRadius = 32.0f; int nTheta = 8; int nPhi = 8; CMatRenderContextPtr pRenderContext(materials); pRenderContext->OverrideDepthEnable(true, false); int nTriangles = 2 * nTheta * (nPhi - 1); // Two extra degenerate triangles per row (except the last one) int nIndices = 2 * (nTheta + 1) * (nPhi - 1); pRenderContext->Bind(m_SkydomeMaterial); CMeshBuilder meshBuilder; IMesh* pMesh = pRenderContext->GetDynamicMesh(); meshBuilder.Begin(pMesh, MATERIAL_TRIANGLE_STRIP, nTriangles, nIndices); // // Build the index buffer. // int i, j; for (i = 0; i < nPhi; ++i) { for (j = 0; j < nTheta; ++j) { float u = j / (float)(nTheta - 1); float v = i / (float)(nPhi - 1); float theta = 2.0f * M_PI * u; float phi = M_PI * v; Vector vecPos; vecPos.x = flRadius * sin(phi) * cos(theta); vecPos.y = flRadius * sin(phi) * sin(theta); vecPos.z = flRadius * cos(phi); Vector vecNormal = vecPos; VectorNormalize(vecNormal); meshBuilder.Position3f(vecPos.x, vecPos.y, vecPos.z); meshBuilder.AdvanceVertex(); } } // // Emit the triangle strips. // int idx = 0; for ( i = 0; i < nPhi - 1; ++i ) { for ( j = 0; j < nTheta; ++j ) { idx = nTheta * i + j; meshBuilder.Index( idx ); meshBuilder.AdvanceIndex(); meshBuilder.Index( idx + nTheta ); meshBuilder.AdvanceIndex(); } // // Emit a degenerate triangle to skip to the next row without // a connecting triangle. // if ( i < nPhi - 2 ) { meshBuilder.Index( idx + nTheta ); meshBuilder.AdvanceIndex(); meshBuilder.Index( ( i + 1 ) * nTheta ); meshBuilder.AdvanceIndex(); } } pRenderContext->MatrixMode(MATERIAL_MODEL); pRenderContext->PushMatrix(); pRenderContext->LoadIdentity(); pRenderContext->Translate(view.origin.x, view.origin.y, view.origin.z); meshBuilder.End(); pMesh->Draw(); pRenderContext->MatrixMode(MATERIAL_MODEL); pRenderContext->PopMatrix(); pRenderContext->OverrideDepthEnable(false, true); }


Теперь для включения и отключения отрисовки вам нужно перейти к функции void CRendering3dView::DrawWorld( float waterZAdjust ) и

выше unsigned long engineFlags = BuildEngineDrawWorldListFlags( m_DrawFlags ); добавить:

if ((m_DrawFlags & DF_DRAWSKYBOX) && (g_pSkyDome && g_pSkyDome->IsDynamicSkyEnabled())) { m_DrawFlags &= ~DF_DRAWSKYBOX; // dont render engine sky, we have our own sky now m_pMainView->DrawSky(*this); }


Шейдеры

Note.pngПримечание:Удалите все файлы из Filestdshader_dx9_30.txt и убедитесь, что в вашем Filestdshader_dx9_30.txt файле есть только skydome_ps30 и skydome_vs30, чтобы ускорить компиляцию шейдеров (НЕ ЗАБУДЬТЕ ОЧИСТИТЬ Filestdshader_dx9_20b.txt)

А теперь откройте Filegame_shader_dx9_base.vpc

И под $File "screenspace_general.cpp" добавьте:

$File "skydome_atmosphere.cpp" $File "skydome_atmosphere_helper.cpp" $File "skydome_atmosphere_helper.h"


Скомпилируйте шейдер динамического неба и пересоберите ваше решение.

Хорошо, а сейчас нам нужно сделать наше динамическое небо доступным через Hammer Hammer.

Для этого вам понадобиться пользовательский fgd файл.

skydome.fgd
  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
@include "halflife2.fgd" //------------------------------------------------------------------------- // Environment (Global Light copy, also handles dynamic sky) //------------------------------------------------------------------------- @PointClass base(Targetname) iconsprite("editor/shadow_control.vmt") = env_skydome : "An entity to control the sky dynamic sky." [ sunpos(vector) : "Pitch Yaw Roll (Y Z X)" : "1 1 1 5" : "This is the light cast direction. Pitch is rotation around the Y axis, yaw is the rotation around the Z axis, and roll is the rotation around the X axis. THE LAST 0 IS FOR HOW BRIGHT THE SUN IS!!!!" coverage(float) : "Coverage of clouds" : "0.50" : "How much of the clouds cover the sky" thickness(float) : "Thickness of clouds" : "3" : "How thicker, how weirder the sky looks, DON'T GO ABOVE 100!" windspeed(string) : "Dir and clearity of wind (X Y Z Clear)" : "0 0 0 5" : "Using stuff like .01 is a good habit as it is the most realistic" // Inputs input SetSunPos(vector) : "Set the position of the sun." input SetWindSpeed(vector) : "Set the ambient color." input InputSetThicknes(float) : "Set the thickness of the clouds." input InputSetCoverage(float) : "Set how many clouds cover the sky." input EnableDynamicSky(integer) : "Set if the sky is on or off" ]


Заключение

Теперь вам нужна последняя деталь и это - материал.

Перейдите в вашу директорию 🖿materials и создайте поддиректорию с названием 🖿shaders

После этого, создайте файл Fileskydome.vmt и вставьте это внутрь:

skydome.vmt
  1.  
  2.  
  3.  
  4.  
  5.  
"SKYDOME_ATMOSPHERE" { "$lut" "skybox/sky_fake_white" "$ALPHATESTREFERENCE" 1 }


Создайте карту с сущностью env_skydome и вот оно! Теперь в вашем моде должно быть динамическое небо.