Oynadığımız oyunlarda ki ışıklandırmalar gerçek dünyadakilerden çok farklıdır. Gerçek dünyada ışık çok karmaşık bir yapıdadır. Işık direk olarak cisimlerin üstüne düşmez, ışık gelir havada ki birçok bileşen(toz vs.) ile etkileşime girer ve cisimlerin üstüne düşen ışık çok farklı şekillerde olabilir. Bu hesaplamaları bilgisayar oyunlara yapmaya kalksak sanırım Quantum bilgisayarlara ihtiyacımız olur.
Oyunlar gerçek dünya’nın aynısı olmasada ona yakın olan ışıklandırma teknikleri kullanırlar.
—IŞIK ÇEŞİTLERİ—
Gerçek dünyadakilere yakın 3 tip ışık çeşiti vardır. Bunlar ;
- Diffuse Lighting (Dağıtılmış ışık)
- Ambient Lighting (Ortam ışığı)
- Specular Lighting (Speküler ışık)
—Diffuse Lighting—
Bu ışık türünde ışık doğrudan yüzeye çarpar. Örneğin elinize karanlık bir odada el feneri ile ışık tutarsanız elinizin aydınlanmış tarafı diffuse lighting olarak adlandırılır.
—Ambient Lighting—
Elinize bir odada tek bir ışık kaynağından (el feneri vs.) ışık tuttuğunuzda daha karanlık olan (tamamen değil) taraftır.
—Specular Lighting—
Speküler ışık genelde yansımayı ifade eder. Örneğin bir topun üzerine bir ışık kaynağı yansıtırsanız ışık topun bir kısmında çok yoğunlaşacak ve burada bir parlaklık oluşturacaktır. Buna Specular Lighting denir.
—IŞIK KAYNAĞI ÇEŞİTLERİ—
Bu üç ışık tipini oluşturmak için çeşitli ışık kaynakları vardır. Bunlar ışıkları çıkarış rengine ve parlaklığına göre farklılık gösterir. Bu ışık kaynakları birlikte kullanılarak gerçekçi bir görüntü elde edilir.
- Ambient Lights (Ortam ışık kaynağı)
- Directional Lights (Doğrudan ışık kaynağı)
- Paint Lights (Boya ışık kaynağı)
- Spot Lights (Nokta ışık kaynağı)
—Ambient Lights—
Beyaz ve gri renkten oluşur. Gri renk karanlık tarafı, beyaz renk ise ışığın vurduğu açık kısmı temsil eder.
—Directional Lights—
Ambient Lights’ lara benzerler. Ambient Lights’ lar ile tek farkı adı üstünde olduğu gibi bu ışık kaynağı tek bir yerden doğrudan gelir. Bu ışıklandırma tekniği oyunlarda ki güneş ışığı için kullanılır.
—Paint Lights—
Belli bir yörüngesi olmayan her tarafa ışığı eşit dağıtan kaynak tipleridir.
—Spot Lights—
El feneri, araba farı vs. de kullanılır.
Kodumuz
Burada öncelikle söylemem gereken bir şey var. Bazı genel kodları “genel.h isimli bir header dosyasında topladım çünkü bunları ne yaparsak yapalım kullanıyoruz ve kodun bu tarafında değişiklik neredeyse olmuyor.
—“genel.h” dosyamın içi—
#include <Windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#define SCREEN_WIDTH 1152
#define SCREEN_HEIGHT 864
DWORD dx_style=WS_EX_TOPMOST|WS_VISIBLE|WS_POPUP;
LPDIRECT3D9 pD3D;
LPDIRECT3DDEVICE9 pDevice;
LPDIRECT3DVERTEXBUFFER9 pVertexBuffer;
LPDIRECT3DINDEXBUFFER9 pIndex;
bool dx_kur(HWND hWnd);
void dx_temizle();
void dx_serbestBirak();
void dx_vertexBufferKur();
void dx_isigiBaslat();
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,
WPARAM wParam,LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd;
WNDCLASSEX wndCEx;
ZeroMemory(&wndCEx,sizeof(WNDCLASSEX));
wndCEx.style=CS_HREDRAW|CS_VREDRAW;
wndCEx.lpfnWndProc=WndProc;
wndCEx.cbClsExtra=0;
wndCEx.cbWndExtra=0;
wndCEx.hInstance=hInstance;
wndCEx.hIcon=LoadIcon(0,IDI_APPLICATION);
wndCEx.hCursor=LoadCursor(0,IDC_ARROW);
wndCEx.hbrBackground=(HBRUSH)COLOR_WINDOW;
wndCEx.lpszClassName=L"Hulucplusplus";
wndCEx.cbSize=sizeof(WNDCLASSEX);
RegisterClassEx(&wndCEx);
hWnd=CreateWindowEx(NULL,L"Hulucplusplus",
L"directX",dx_style,0,0,
SCREEN_WIDTH,SCREEN_HEIGHT,
NULL,NULL,hInstance,NULL);
ShowWindow(hWnd,nCmdShow);
MSG message;
dx_kur(hWnd);
while(TRUE)
{
if(PeekMessage(&message,NULL,NULL,NULL,PM_REMOVE))
{
if(message.message==WM_QUIT)
break;
TranslateMessage(&message);
DispatchMessage(&message);
}
dx_temizle();
}
dx_serbestBirak();
return (int)message.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd,
UINT message,WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
case WM_KEYDOWN:
{
switch(wParam)
{
case VK_ESCAPE:
{
PostQuitMessage(0);
return 0;
}
}
}
}
return DefWindowProc(hWnd,message,wParam,lParam);
}
void dx_serbestBirak()
{
if(pD3D!=NULL)
pD3D->Release();
if(pDevice!=NULL)
pDevice->Release();
if(pVertexBuffer!=NULL)
pVertexBuffer->Release();
if(pIndex!=NULL)
pIndex->Release();
}
---Kodumuzun Tamamı---
#include "genel.h"
DWORD fvf_style=D3DFVF_NORMAL|D3DFVF_XYZ;
struct CUSTOMVERTEX
{
FLOAT x,y,z;
D3DVECTOR NORMAL;
};
bool dx_kur(HWND hWnd)
{
pD3D=Direct3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERS present;
ZeroMemory(&present,sizeof(D3DPRESENT_PARAMETERS));
present.SwapEffect=D3DSWAPEFFECT_DISCARD;
present.hDeviceWindow=hWnd;
present.Windowed=FALSE;
present.BackBufferCount=1;
present.BackBufferFormat=D3DFMT_X8R8G8B8;
present.BackBufferHeight=SCREEN_HEIGHT;
present.BackBufferWidth=SCREEN_WIDTH;
present.AutoDepthStencilFormat=D3DFMT_D16;
present.EnableAutoDepthStencil=TRUE;
if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&present,&pDevice)))
return FALSE;
dx_vertexBufferKur();
dx_isigiBaslat();
pDevice->SetRenderState(D3DRS_LIGHTING,TRUE);
pDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
pDevice->SetRenderState(D3DRS_ZENABLE,TRUE);
pDevice->SetRenderState(D3DRS_AMBIENT,D3DCOLOR_XRGB(50,50,50));
return TRUE;
}
void dx_temizle()
{
pDevice->Clear(NULL,NULL,D3DCLEAR_TARGET,
D3DCOLOR_XRGB(0,0,0),1.0f,0);
pDevice->Clear(NULL,NULL,D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(0,0,0),1.0f,0);
pDevice->BeginScene();
pDevice->SetFVF(fvf_style);
D3DXMATRIX mView;
D3DXMatrixLookAtLH(&mView,
&D3DXVECTOR3(0.0f,8.0f,25.0f),
&D3DXVECTOR3(0.0f,0.0f,0.0f),
&D3DXVECTOR3(0.0f,1.0f,0.0f));
pDevice->SetTransform(D3DTS_VIEW,&mView);
D3DXMATRIX mProjection;
D3DXMatrixPerspectiveFovLH(&mProjection,
D3DXToRadian(45),
(FLOAT)SCREEN_WIDTH/SCREEN_HEIGHT,
1.0f,100.0f);
pDevice->SetTransform(D3DTS_PROJECTION,&mProjection);
static float index=0.0f; index+=0.003f;
D3DXMATRIX mRotateY;
D3DXMatrixRotationY(&mRotateY,index);
pDevice->SetTransform(D3DTS_WORLD,&mRotateY);
pDevice->SetStreamSource(0,pVertexBuffer,0,
sizeof(CUSTOMVERTEX));
pDevice->SetIndices(pIndex);
pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,
0,10,0,6);
pDevice->EndScene();
pDevice->Present(NULL,NULL,NULL,NULL);
}
void dx_vertexBufferKur()
{
CUSTOMVERTEX vertices[] =
{
{ 3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ 0.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 0.0f, 0.0f, 10.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ -3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255), },
{ 3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ 2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ -3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
};
pDevice->CreateVertexBuffer(10*sizeof(CUSTOMVERTEX),
0,fvf_style,D3DPOOL_MANAGED,&pVertexBuffer,NULL);
VOID *pVoid;
pVertexBuffer->Lock(0,0,(void**)&pVoid,0);
memcpy(pVoid,vertices,sizeof(vertices));
pVertexBuffer->Unlock();
short indices[] =
{
0, 1, 2,
2, 1, 3,
3, 1, 0,
0, 2, 3,
4, 5, 6,
7, 8, 9,
};
pDevice->CreateIndexBuffer(18*sizeof(short),
0,D3DFMT_INDEX16,D3DPOOL_MANAGED,&pIndex,NULL);
pIndex->Lock(0,0,(void**)&pVoid,0);
memcpy(pVoid,indices,sizeof(indices));
pIndex->Unlock();
}
void dx_isigiBaslat()
{
D3DLIGHT9 light;
D3DMATERIAL9 material;
ZeroMemory(&light,sizeof(D3DLIGHT9));
light.Type=D3DLIGHT_DIRECTIONAL;
light.Diffuse=D3DXCOLOR(0.5f,0.5f,0.5f,1.0f);
light.Direction=D3DXVECTOR3(-1.0f,-0.3f,-1.0f);
pDevice->SetLight(0,&light);
pDevice->LightEnable(0,TRUE);
ZeroMemory(&material,sizeof(D3DMATERIAL9));
material.Diffuse=D3DXCOLOR(1.0f,1.0f,1.0f,1.0f);
material.Ambient=D3DXCOLOR(1.0f,1.0f,1.0f,1.0f);
pDevice->SetMaterial(&material);
}