14.04.2013 Views

Tema 6. Gráficos 3D con DirectX

Tema 6. Gráficos 3D con DirectX

Tema 6. Gráficos 3D con DirectX

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Introducción a la<br />

Programación Lúdica<br />

<strong>Tema</strong> <strong>6.</strong> <strong>Gráficos</strong> <strong>3D</strong> <strong>con</strong> <strong>DirectX</strong>


Esquema<br />

• Comenzando <strong>con</strong> Direct<strong>3D</strong><br />

• Proceso de renderizado<br />

• Representación de escenas <strong>3D</strong> <strong>con</strong> D<strong>3D</strong><br />

• Realismo de escenas<br />

• Shaders


Esquema<br />

• Comenzando <strong>con</strong> Direct<strong>3D</strong><br />

–Descripción<br />

– Inicialización<br />

– Bucle del juego<br />

– Función de renderización<br />

– Programa principal<br />

• Proceso de renderizado<br />

• Representación de escenas <strong>3D</strong> <strong>con</strong> D<strong>3D</strong><br />

• Realismo de escenas<br />

• Shaders


Comenzando <strong>con</strong> Direct<strong>3D</strong><br />

• Descripción:<br />

– <strong>DirectX</strong> es un <strong>con</strong>junto de interfaces de programación (APIs) para el desarrollo<br />

de aplicaciones multimedia sobre la plataforma Windows.<br />

– Creada y distribuida por Microsoft.<br />

– Consta de dos partes: SDK, Runtime.<br />

– Basado en COM (Component Object Model).<br />

– Desde la versión 9, puede utilizarse desde programas en lenguajes CRL: C++,<br />

C#, Visual Basic, etc.<br />

– Componentes (versión 9):<br />

• Direct<strong>3D</strong> (gráficos)<br />

• DirectSound (efectos)<br />

• DirectMusic (música)<br />

• DirectInput (entrada)<br />

• DirectPlay (comunicaciones)<br />

• DirectShow (reproducción de vídeo)<br />

• DirectSetup (instalación)<br />

– Ejemplos: http://www.moon-labs.com/samples/BookPart2Code.zip (Introduction<br />

to <strong>3D</strong> Game Programming with <strong>DirectX</strong> 9, Frank D. Luna. Wordware, 2003)


Comenzando <strong>con</strong> Direct<strong>3D</strong><br />

• Inicialización:<br />

1. Obtener un puntero a una interfaz<br />

IDirect<strong>3D</strong>9.<br />

2. Comprobar las características del<br />

dispositivo (D<strong>3D</strong>CAPS9) para determinar si la<br />

tarjeta gráfica principal soporta<br />

procesamiento de vértices por hardware.<br />

3. Inicializar una instancia de la estructura<br />

D<strong>3D</strong>PRESENT_PARAMETERS.<br />

4. Crear el objeto IDirect<strong>3D</strong>Device9.


Comenzando <strong>con</strong> Direct<strong>3D</strong><br />

• Inicialización (1, 2):<br />

// Obtener puntero a IDirect<strong>3D</strong>9<br />

IDirect<strong>3D</strong>9* d3d9;<br />

d3d9 = Direct<strong>3D</strong>Create9(D<strong>3D</strong>_SDK_VERSION);<br />

// Comprobar características del dispositivo<br />

D<strong>3D</strong>CAPS9 caps;<br />

d3d9->GetDeviceCaps(<br />

D<strong>3D</strong>ADAPTER_DEFAULT,<br />

D<strong>3D</strong>DEVTYPE_HAL,<br />

&caps);<br />

int vp = 0;<br />

if( caps.DevCaps & D<strong>3D</strong>DEVCAPS_HWTRANSFORMANDLIGHT ) {<br />

vp = D<strong>3D</strong>CREATE_HARDWARE_VERTEXPROCESSING;<br />

} else {<br />

vp = D<strong>3D</strong>CREATE_SOFTWARE_VERTEXPROCESSING;<br />

}


Comenzando <strong>con</strong> Direct<strong>3D</strong><br />

• Inicialización (3):<br />

// Crear estructura D<strong>3D</strong>PRESENT_PARAMETERS<br />

D<strong>3D</strong>PRESENT_PARAMETERS d3dpp;<br />

d3dpp.BackBufferWidth = 800;<br />

d3dpp.BackBufferHeight = 600;<br />

d3dpp.BackBufferFormat = D<strong>3D</strong>FMT_A8R8G8B8; //pixel format<br />

d3dpp.BackBufferCount = 1;<br />

d3dpp.MultiSampleType = D<strong>3D</strong>MULTISAMPLE_NONE;<br />

d3dpp.MultiSampleQuality = 0;<br />

d3dpp.SwapEffect = D<strong>3D</strong>SWAPEFFECT_DISCARD;<br />

d3dpp.hDeviceWindow = hwnd;<br />

d3dpp.Windowed = false; // fullscreen<br />

d3dpp.EnableAutoDepthStencil = true;<br />

d3dpp.AutoDepthStencilFormat = D<strong>3D</strong>FMT_D24S8; // depth format<br />

d3dpp.Flags = 0;<br />

d3dpp.FullScreen_RefreshRateInHz = D<strong>3D</strong>PRESENT_RATE_DEFAULT;<br />

d3dpp.PresentationInterval = D<strong>3D</strong>PRESENT_INTERVAL_IMMEDIATE;


Comenzando <strong>con</strong> Direct<strong>3D</strong><br />

• Inicialización (4):<br />

// Crear el objeto IDirect<strong>3D</strong>Device9<br />

IDirect<strong>3D</strong>Device9* device = 0;<br />

hr = d3d9->CreateDevice(<br />

D<strong>3D</strong>ADAPTER_DEFAULT, // primary adapter<br />

D<strong>3D</strong>DEVTYPE_HAL, // device type<br />

hwnd, // window associated with device<br />

D<strong>3D</strong>CREATE_HARDWARE_VERTEXPROCESSING, // vertex processing type<br />

&d3dpp, // present parameters<br />

&device); // returned created device<br />

if( FAILED(hr) ) {<br />

::MessageBox(0, "CreateDevice() - FAILED", 0, 0);<br />

return 0;<br />

}


Comenzando <strong>con</strong> Direct<strong>3D</strong><br />

• Bucle del juego:<br />

– Por defecto, cualquier aplicación en Windows se<br />

ejecuta en un bucle (MessageLoop) donde se<br />

atienden los mensajes o eventos que se han<br />

producido sobre la interfaz gráfica.<br />

– Para ello, se utiliza un método GetMessage(…), que<br />

suspende la ejecución hasta que se realiza una<br />

entrada.<br />

– En programación de videojuegos no puede detenerse<br />

la ejecución porque es necesario actualizar la<br />

pantalla: uso de método PeekMessage(…).


Comenzando <strong>con</strong> Direct<strong>3D</strong><br />

• MessageLoop:<br />

// Estructura del bucle del juego en <strong>DirectX</strong><br />

int d3d::EnterMsgLoop( bool (*ptr_display)(float timeDelta) ) {<br />

MSG msg;<br />

::ZeroMemory(&msg, sizeof(MSG));<br />

static float lastTime = (float)timeGetTime();<br />

}<br />

while(msg.message != WM_QUIT) {<br />

if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {<br />

::TranslateMessage(&msg);<br />

::DispatchMessage(&msg);<br />

} else {<br />

float currTime = (float)timeGetTime();<br />

float timeDelta = (currTime - lastTime)*0.001f;<br />

ptr_display(timeDelta); // Render function<br />

lastTime = currTime;<br />

}<br />

}<br />

return msg.wParam;


Comenzando <strong>con</strong> Direct<strong>3D</strong><br />

• Render function:<br />

// Ejemplo de funcion de renderizado<br />

bool Display(float timeDelta) {<br />

if( Device ) {<br />

Device->Clear(0, 0, D<strong>3D</strong>CLEAR_TARGET | D<strong>3D</strong>CLEAR_ZBUFFER,<br />

0x00000000, 1.0f, 0);<br />

Device->Present(0, 0, 0, 0); // present backbuffer<br />

}<br />

return true;<br />

}


Comenzando <strong>con</strong> Direct<strong>3D</strong><br />

• Programa principal:<br />

// Ejemplo de programa principal (utiliza d3dUtility.h)<br />

int WINAPI WinMain(HINSTANCE hinstance,<br />

HINSTANCE prevInstance,<br />

PSTR cmdLine,<br />

int showCmd) {<br />

}<br />

if(!d3d::InitD<strong>3D</strong>(hinstance,<br />

800, 600, true, D<strong>3D</strong>DEVTYPE_HAL, &Device)) {<br />

::MessageBox(0, "InitD<strong>3D</strong>() - FAILED", 0, 0);<br />

return 0;<br />

}<br />

if(!Setup()) {<br />

::MessageBox(0, "Setup() - FAILED", 0, 0);<br />

return 0;<br />

}<br />

d3d::EnterMsgLoop( Display );<br />

Cleanup();<br />

Device->Release();<br />

return 0;


Comenzando <strong>con</strong> Direct<strong>3D</strong><br />

• Ejemplo completo:<br />

– Chapter 1/D<strong>3D</strong>9 Init/*


Esquema<br />

• Comenzando <strong>con</strong> Direct<strong>3D</strong><br />

• Proceso de renderizado<br />

– Modelos<br />

– Cámara<br />

– Fases<br />

• Coordenadas locales<br />

• Coordenadas de mundo<br />

• Coordenadas de vista<br />

• Eliminación de caras ocultas<br />

• Iluminación<br />

• Recorte<br />

• Proyección<br />

• Coordenadas de viewport<br />

• Rasterización<br />

• Representación de escenas <strong>3D</strong> <strong>con</strong> D<strong>3D</strong><br />

• Realismo de escenas<br />

• Shaders


Proceso de renderizado<br />

• Modelos:<br />

– Vértices: Punto donde se unen dos aristas.<br />

• Definen la forma de los objetos.<br />

• Propiedades: Posición, Color, Normal, Textura.<br />

• Pueden crearse a medida (FVF: Flexible Vertex Flags).<br />

– Triángulos: Elemento básico.<br />

– Mallas: Conjunto de triángulos que determina la<br />

forma de un modelo.<br />

– Índices: Referencias a los vértices que forman una<br />

malla.<br />

• Evitan duplicar las definiciones de vértices de un objeto.


Proceso de renderizado<br />

• Modelos:<br />

–Vértices:<br />

struct NormalTexVertex {<br />

float _x, _y, _z; // position<br />

float _nx, _ny, _nz; // normal vector<br />

float _u, _v; // texture coordinates<br />

}<br />

#define FVF_NORMAL_TEX (D<strong>3D</strong>FVF_XYZ | D<strong>3D</strong>FVF_NORMAL | D<strong>3D</strong>FVF_TEX1)<br />

–Malla:<br />

Vertex rectangle[6] = { v0, v1, v2, // triangle0<br />

– Índices:<br />

v0, v2, v3}; // triangle1<br />

Vertex vertexList[4] = {v0, v1, v2, v3};<br />

WORD indexList[6] = { 0, 1, 2, // triangle0<br />

0, 2, 3}; // triangle1


Proceso de renderizado<br />

• Cámara:<br />

– Definición de frustrum, que determina qué objetos<br />

son visibles y los parámetros de la proyección.<br />

Ángulo de Campo de<br />

Visión Horizontal<br />

Centro de proyección<br />

Ventana de Proyección<br />

Ángulo de Campo de Visión Vertical<br />

Plano Lejano<br />

Plano Cercano


Proceso de renderizado<br />

• Fases del Proceso de Renderización:<br />

– Renderizado: Procedimiento por el cual se crea una imagen 2D<br />

que representa un mundo <strong>3D</strong>, dada una descripción de la<br />

geometría del escenario y una cámara virtual que determina la<br />

posición y la orientación del observador.<br />

– Etapas:


Proceso de renderizado<br />

• Coordenadas locales:<br />

– Para simplificar, los<br />

modelos se definen en<br />

su propio sistema de<br />

coordenadas.<br />

– Para posicionarlos<br />

dentro del espacio de<br />

coordenadas del<br />

mundo es necesario<br />

aplicarles una<br />

transformación<br />

geométrica.


Proceso de renderizado<br />

• Coordenadas de mundo:<br />

– Sistema de coordenadas<br />

de referencia para los<br />

objetos del escenario que<br />

se pretende representar.<br />

– Transformada de mundo:<br />

transformación geométrica<br />

de las coordenadas locales<br />

a las coordenadas de<br />

mundo.<br />

– D<strong>3D</strong>: Transformada<br />

D<strong>3D</strong>TS_WORLD


Proceso de renderizado<br />

• Coordenadas de mundo:<br />

// Ejemplo de transformada de mundo<br />

// Build the cube world matrix that only <strong>con</strong>sists of a translation.<br />

D<strong>3D</strong>XMATRIX cubeWorldMatrix;<br />

D<strong>3D</strong>XMatrixTranslation(&cubeWorldMatrix, -3.0f, 2.0f, <strong>6.</strong>0f);<br />

// Build the sphere world matrix that only <strong>con</strong>sists of a translation.<br />

D<strong>3D</strong>XMATRIX sphereWorldMatrix;<br />

D<strong>3D</strong>XMatrixTranslation(&sphereWorldMatrix, 5.0f, 0.0f, -2.0f);<br />

// Set the cube’s transformation<br />

Device->SetTransform(D<strong>3D</strong>TS_WORLD, &cubeWorldMatrix);<br />

drawCube(); // draw the cube<br />

// Now since the sphere uses a different world transformation, we<br />

// must change the world transformation to the sphere’s. If we<br />

// don’t change this, the sphere would be drawn using the previously<br />

// set world matrix – the cube’s.<br />

Device->SetTransform(D<strong>3D</strong>TS_WORLD, &sphereWorldMatrix);<br />

drawSphere(); // draw the sphere


Proceso de renderizado<br />

• Coordenadas de vista:<br />

– La cámara debe situarse utilizando el sistema de<br />

coordenadas de mundo.<br />

– Es interesante posicionar arbitrariamente la cámara,<br />

pero difícil de implementar.<br />

– Solución: transformar los objetos del mundo respecto<br />

de la cámara, de forma que ésta siempre esté situada<br />

en el origen de coordenadas mirando hacia Z+.<br />

– D<strong>3D</strong> calcula automáticamente la transformada de<br />

vista (D<strong>3D</strong>TS_VIEW) <strong>con</strong> D<strong>3D</strong>XMatrixLookAtLH.


Proceso de renderizado<br />

• Coordenadas de vista:<br />

// Ejemplo de transformada de vista<br />

D<strong>3D</strong>XVECTOR3 position(5.0f, 3.0f, –10.0f); // posicion<br />

D<strong>3D</strong>XVECTOR3 targetPoint(0.0f, 0.0f, 0.0f); // direccion<br />

D<strong>3D</strong>XVECTOR3 worldUp(0.0f, 1.0f, 0.0f); // vertical<br />

D<strong>3D</strong>XMATRIX V;<br />

D<strong>3D</strong>XMatrixLookAtLH(&V, &position, &targetPoint, &worldUp);<br />

Device->SetTransform(D<strong>3D</strong>TS_VIEW, &V);


Proceso de renderizado<br />

• Eliminación de caras ocultas:<br />

– Cada polígono delimita dos caras, una visible y otra<br />

que no debe mostrarse.<br />

– D<strong>3D</strong> no muestra las caras ocultas de un modelo.<br />

– Por defecto, D<strong>3D</strong> <strong>con</strong>sidera visibles los triángulos<br />

cuyos vértices han sido enumerados en el sentido de<br />

las agujas del reloj (en coordenadas de vista).<br />

– Este comportamiento puede modificarse <strong>con</strong> el<br />

método:<br />

Device->SetRenderState(D<strong>3D</strong>RS_CULLMODE,<br />

Value).


Proceso de renderizado<br />

• Iluminación:<br />

– Modifica el aspecto de un objeto según la luz<br />

que incida sobre él.<br />

– D<strong>3D</strong> permite definir fuentes de iluminación en<br />

coordenadas de mundo.


Proceso de renderizado<br />

• Recorte:<br />

– Procedimiento por el cual se segmentan los<br />

objetos que no caben completamente en el<br />

espacio visible, eliminando las partes que<br />

quedan fuera y presentando las que quedan<br />

dentro.<br />

– D<strong>3D</strong> se encarga automáticamente de realizar<br />

el recorte de los objetos de la escena.


Proceso de renderizado<br />

• Proyección:<br />

– Transformación por la cual<br />

se obtiene una<br />

representación 2D de la<br />

escena <strong>3D</strong>.<br />

– En este caso, interesa una<br />

proyección de perspectiva.<br />

– Para obtener la<br />

transformada de<br />

proyección<br />

(D<strong>3D</strong>TS_PROJECTION) se<br />

utiliza<br />

D<strong>3D</strong>XMatrixPerspectiv<br />

eFovLH.


Proceso de renderizado<br />

• Proyección:<br />

// Ejemplo de transformada de proyección<br />

D<strong>3D</strong>XMATRIX proj;<br />

D<strong>3D</strong>XMatrixPerspectiveFovLH(<br />

&proj, // Matriz resultado<br />

PI * 0.5f, // Ángulo de apertura<br />

(float)width / (float)height, // Ratio anchura/altura<br />

1.0, // Distancia plano delantero<br />

1000.0f); // Distancia plano trasero<br />

Device->SetTransform(D<strong>3D</strong>TS_PROJECTION, &proj);


Proceso de renderizado<br />

• Transformada de viewport:<br />

– Transformación que traslada la ventana 2D de proyección a una<br />

sección rectangular de la pantalla.<br />

– D<strong>3D</strong> utiliza una estructura D<strong>3D</strong>VIEWPORT9 <strong>con</strong> los parámetros<br />

del viewport y el método Device->SetViewPort para asignarlo.<br />

⎡ width<br />

⎤<br />

⎢<br />

0 0 0<br />

2<br />

⎥<br />

⎢ ⎥<br />

⎢ height<br />

0 −<br />

0 0⎥<br />

⎢ 2<br />

⎥<br />

⎢ 0 0 max Z − min Z 0⎥<br />

⎢ ⎥<br />

⎢ width height<br />

⎥<br />

⎢x + y +<br />

min Z 1<br />

⎣ 2 2<br />

⎥⎦


Proceso de renderizado<br />

• Transformada de viewport:<br />

// Ejemplo de transformada de viewport<br />

D<strong>3D</strong>VIEWPORT9 vp {<br />

0, // Posicion X del vp respecto de la ventana de dibujo<br />

0, // Posicion Y del vp respecto de la ventana de dibujo<br />

640, // Anchura del vp<br />

480, // Altura del vp<br />

0, // Valor minimo del Z-buffer<br />

1 }; // Valor maximo del Z-buffer<br />

Device->SetViewport(&vp);


Proceso de renderizado<br />

• Rasterización:<br />

– Una vez realizada la transformada de viewport se<br />

obtiene una lista de vértices de triángulos<br />

posicionados en pantalla.<br />

– La fase de rasterización calcula el color <strong>con</strong> el que<br />

debe dibujarse cada uno de los píxeles del triángulo.<br />

– Esta fase tiene un coste computacional alto y debe<br />

realizarse, en la medida de lo posible, en la tarjeta<br />

gráfica.<br />

– El resultado final se envía al monitor, que presenta<br />

los resultados.


Esquema<br />

• Comenzando <strong>con</strong> Direct<strong>3D</strong><br />

• Proceso de renderizado<br />

• Representación de escenas <strong>3D</strong> <strong>con</strong> D<strong>3D</strong><br />

– Vertex / Index Buffers<br />

– Estados de renderización<br />

– Preparación para el dibujo<br />

– Dibujado de Vertex / Index Buffers<br />

– Objetos geométricos en D<strong>3D</strong><br />

• Realismo de escenas<br />

• Shaders


Representación de escenas <strong>3D</strong><br />

• Vertex / Index Buffers<br />

– Vertex Buffer<br />

• Zona de memoria <strong>con</strong>tigua que almacena información sobre<br />

vértices.<br />

• Interfaz: IDirect<strong>3D</strong>VertexBuffer9.<br />

• Creación: IDirect<strong>3D</strong>Device9::CreateVertexBuffer<br />

– Index Buffer<br />

• Zona de memoria <strong>con</strong>tigua que almacena información sobre índices<br />

a vértices.<br />

• Interfaz: IDirect<strong>3D</strong>IndexBuffer9.<br />

• Creación: IDirect<strong>3D</strong>Device9::CreateIndexBuffer<br />

– Se utilizan estas interfaces en lugar de arrays.<br />

– Se trata de memoria compartida.<br />

– Pueden almacenarse en memoria de vídeo (static) o en<br />

memoria interna (dynamic).


Representación de escenas <strong>3D</strong><br />

• Vertex / Index Buffers:<br />

// Creacion de buffers<br />

IDirect<strong>3D</strong>VertexBuffer9* vb;<br />

Device->CreateVertexBuffer(<br />

8 * sizeof( Vertex ), // Tamaño reservado (8 vertices)<br />

0, // Uso (no asignado)<br />

D<strong>3D</strong>FVF_XYZ, // Formato de la estructura Vertex<br />

D<strong>3D</strong>POOL_MANAGED, // Pool de memoria donde se ubicará<br />

&vb, // Estructura resultado<br />

0); // Identificador compartido<br />

IDirect<strong>3D</strong>IndexBuffer9* ib;<br />

Device->CreateIndexBuffer(<br />

36 * sizeof( WORD ), // Tamaño (36 indices de 16 bits)<br />

D<strong>3D</strong>USAGE_DYNAMIC | D<strong>3D</strong>USAGE_WRITEONLY, // Uso<br />

D<strong>3D</strong>FMT_INDEX16, // Tamaño de los índices<br />

D<strong>3D</strong>POOL_MANAGED, // Pool de memoria donde se ubicará<br />

&ib, // Estructura resultado<br />

0); // Identificador compartido


Representación de escenas <strong>3D</strong><br />

• Vertex / Index Buffers<br />

– Acceso:<br />

• Necesario obtener un puntero a la memoria del<br />

búfer.<br />

• Métodos Lock() / Unlock(…).<br />

– Recuperación de información:<br />

• Estructura D<strong>3D</strong>VERTEXBUFFER.<br />

• Método GetDesc().


Representación de escenas <strong>3D</strong><br />

• Vertex / Index Buffers:<br />

// Acceso a buffers<br />

// Bloquear buffer completo<br />

Vertex* vertices;<br />

vb->Lock(<br />

0, // Offset (comienzo)<br />

0, // Longitud<br />

(void**)&vertices, // Vector resultado<br />

0); // Modo de acceso<br />

// Asignar valores al buffer<br />

vertices[0] = Vertex(-1.0f, 0.0f, 2.0f);<br />

vertices[1] = Vertex( 0.0f, 1.0f, 2.0f);<br />

vertices[2] = Vertex( 1.0f, 0.0f, 2.0f);<br />

// Desbloquear buffer<br />

vb->Unlock();


Representación de escenas <strong>3D</strong><br />

• Estados de renderización:<br />

– Direct<strong>3D</strong> permite renderizar una escena de diferentes<br />

formas.<br />

– El renderizado por defecto suele ser el apropiado.<br />

– Metodo IDirect<strong>3D</strong>Device9::SetRenderState<br />

– Ejemplo: Renderización en modo “alambres”<br />

device->SetRenderState(<br />

D<strong>3D</strong>RS_FILLMODE, // Propiedad a cambiar<br />

D<strong>3D</strong>FILL_WIREFRAME); // Nuevo valor


Representación de escenas <strong>3D</strong><br />

• Preparación para el dibujo:<br />

– Asignar flujo de datos<br />

(IDirect<strong>3D</strong>Device9::SetStreamSource):<br />

Asocia al dispositivo un vertex buffer, que <strong>con</strong>tendrá<br />

la geometría de las figuras que se van a renderizar.<br />

– Asignar formato de vértices<br />

(IDirect<strong>3D</strong>Device9::SetFVF): Especifica el<br />

formato de los vértices que se utilizarán en las<br />

siguientes llamadas.<br />

– Asignar índices de datos<br />

(IDirect<strong>3D</strong>Device9::SetIndices): Asocia al<br />

dispositivo un <strong>con</strong>junto de índices.


Representación de escenas <strong>3D</strong><br />

• Dibujo de Index / Vertex Buffers:<br />

– IDirect<strong>3D</strong>Device9::BeginScene: Comenzar a<br />

dibujar escena.<br />

– IDirect<strong>3D</strong>Device9::DrawPrimitive: Dibuja<br />

primitivas (D<strong>3D</strong>PRIMITIVETYPE) sin utilizar índices.<br />

– IDirect<strong>3D</strong>Device9::DrawIndexedPrimitive:<br />

Dibuja primitivas (D<strong>3D</strong>PRIMITIVETYPE) utilizando un<br />

buffer de índices.<br />

– IDirect<strong>3D</strong>Device9::EndScene: Finalizar dibujo<br />

de escena.


Representación de escenas <strong>3D</strong><br />

• Preparación y dibujo de buffers:<br />

// Preparacion<br />

// Asociar vertex buffer completo como fuente de informacion<br />

Device->SetStreamSource( 0, vb, 0, sizeof( Vertex ) );<br />

// Asignar formato de vertices según estructura Vertex definida<br />

Device->SetFVF( D<strong>3D</strong>FVF_XYZ | D<strong>3D</strong>FVF_DIFFUSE | D<strong>3D</strong>FVF_TEX1 );<br />

// Asociar index buffer<br />

Device->SetIndices( ib );<br />

// Dibujar<br />

Device->BeginScene();<br />

// Dibujar 4 triángulos<br />

Device->DrawPrimitive( D<strong>3D</strong>PT_TRIANGLELIST, 0, 4);<br />

// Dibujar 12 triángulos usando buffer de indices<br />

Device->DrawIndexedPrimitive(D<strong>3D</strong>PT_TRIANGLELIST, 0, 0, 8, 0, 12);<br />

Device->EndScene();


Representación de escenas <strong>3D</strong><br />

• Dibujo de objetos geométricos:<br />

– Definir figuras completas utilizando sólo triángulos<br />

puede ser complicado.<br />

– D<strong>3D</strong> ofrece primitivas para la creación de mallas de<br />

triángulos (ID<strong>3D</strong>XMesh) que componen objetos<br />

geométricos más complicados: prisma, esfera,<br />

cilindro, polígono, toro, teterea.<br />

– Estas primitivas asocian directamente la malla al<br />

dispositivo Direct<strong>3D</strong>.<br />

– Las mallas se dibujan <strong>con</strong><br />

ID<strong>3D</strong>XMesh::DrawSubset.


Representación de escenas <strong>3D</strong><br />

• Dibujo de objetos geométricos:<br />

// Crear malla tetera<br />

ID<strong>3D</strong>XMesh* mesh = 0;<br />

D<strong>3D</strong>XCreateTeapot(Device, &mesh, 0);<br />

// Dibujar tetera<br />

Device->BeginScene();<br />

mesh->DrawSubset(0);<br />

Device->EndScene();<br />

// Liberar malla<br />

mesh->Release();<br />

mesh = 0;


Representación de escenas <strong>3D</strong><br />

• Ejemplo completo: Dibujo de una tetera<br />

– Chapter 3\Teapot


Esquema<br />

• Comenzando <strong>con</strong> Direct<strong>3D</strong><br />

• Proceso de renderizado<br />

• Representación de escenas <strong>3D</strong> <strong>con</strong> D<strong>3D</strong><br />

• Realismo de escenas:<br />

– Color<br />

–Texturas<br />

– Iluminación<br />

– Blending<br />

– Stenciling<br />

• Shaders


Realismo de escenas<br />

• Color:<br />

– Modelo Alfa-RGB : D<strong>3D</strong>COLOR (32 bits, [0, 255]);<br />

D<strong>3D</strong>COLORVALUE, D<strong>3D</strong>XCOLOR (128 bits, [0, 1]).<br />

– La información de color puede incluirse en la<br />

estructura de vértices definida por el programador.<br />

– Shading: Cálculo del color de los píxeles de una<br />

primitiva durante el proceso de renderizado.<br />

• El color determinado por los colores asignados a sus vértices<br />

(D<strong>3D</strong>COLOR).<br />

• Dos tipos: plano (color del primer vértice) y Gouraud<br />

(suavizado).<br />

• Puede modificarse <strong>con</strong><br />

IDirect<strong>3D</strong>Device9::SetRenderState.


Realismo de escenas<br />

• Color:<br />

// Vertice <strong>con</strong> color<br />

struct ColorVertex {<br />

float _x, _y, _z;<br />

D<strong>3D</strong>COLOR _color;<br />

static <strong>con</strong>st DWORD FVF;<br />

}<br />

<strong>con</strong>st DWORD ColorVertex::FVF = D<strong>3D</strong>FVF_XYZ | D<strong>3D</strong>FVF_DIFFUSE;<br />

…<br />

// Asignación de colores a un vertice (rojo, verde, azul)<br />

ColorVertex t[3];<br />

t[0]._color = D<strong>3D</strong>COLOR_XRGB(255, 0, 0);<br />

t[1]._color = D<strong>3D</strong>COLOR_XRGB(0, 255, 0);<br />

t[2]._color = D<strong>3D</strong>COLOR_XRGB(0, 0, 255);


Realismo de escenas<br />

• Ejemplo completo: Coloreado de<br />

triángulos<br />

– Chapter 4\Colore Triangle


Realismo de escenas<br />

• Iluminación:<br />

– Cuando se define una iluminación, D<strong>3D</strong> calcula<br />

automáticamente el color de un objeto basándose en:<br />

• Material de que está <strong>con</strong>stituido<br />

• Posición y orientación de las caras<br />

• Fuentes de luz<br />

– No se utiliza el valor de color de los vértices.<br />

– La luz emitida por un objeto tiene tres componentes:<br />

• Ambiental: Luz reflejada por otros objetos, no directa, que<br />

ilumina un objeto aunque no esté iluminado.<br />

• Difundida: Haz de luz direccional que se refleja en todas<br />

direcciones sobre los objetos. Independiente del observador.<br />

• Especular: Haz de luz direccional que se refleja en una sola<br />

dirección. Depende del observador.


Realismo de escenas<br />

• Iluminación:<br />

– Materiales:<br />

• Modelan la forma en que la luz se refleja en un objeto y, en<br />

<strong>con</strong>secuencia, su color.<br />

• Estructura D<strong>3D</strong>MATERIAL9. Componentes:<br />

– Valoración para cada tipo de reflexión (Ambiental, Difundida,<br />

Especular).<br />

– Brillo propio.<br />

– Potencia del reflejo especular.<br />

• La información de material no se codifica <strong>con</strong> la información<br />

geométrica de vértice, debe asignarse antes de dibujar <strong>con</strong><br />

IDirect<strong>3D</strong>Device9::SetMaterial.


Realismo de escenas<br />

• Iluminación:<br />

– Normales de los vértices:<br />

• Se utilizan para determinar el ángulo de incidencia<br />

de la luz sobre una superficie.<br />

• Se calculan como la media de las normales de las<br />

caras a las que pertenece un vértice.<br />

• La normal sí se incorpora a la estructura Vértice<br />

definida por el programador (y se elimina la<br />

información de color).


Realismo de escenas<br />

• Iluminación:<br />

– Fuentes de luz:<br />

• Estructura D<strong>3D</strong>LIGHT9.<br />

• Tres tipos: Puntual (todas direcciones), Direccional<br />

(una dirección, rayos paralelos), Orientada (una<br />

dirección, rayos en forma de <strong>con</strong>o).<br />

• Asignar fuentes de luz de la escena:<br />

IDirect<strong>3D</strong>Device9::SetLight,<br />

IDirect<strong>3D</strong>Device9::EnableLight.


Realismo de escenas<br />

• Ejemplo completo: Iluminación<br />

– Chapter 5\directional light


Realismo de escenas<br />

• Texturas:<br />

– Imagen 2D que se proyecta sobre un triángulo para<br />

definir el aspecto de una cara.<br />

– Texel: Posición (u, v) dentro del espacio de<br />

coordenadas de una textura ([0, 1]).<br />

– Cada vértice de un triángulo <strong>3D</strong> se asocia a un texel,<br />

estableciéndose una correspondencia que mapea la<br />

textura sobre el triángulo.<br />

– La posición del espacio de texturas asociada al<br />

vértice se añade a la estructura Vértice definida por el<br />

programador.


Realismo de escenas


Realismo de escenas<br />

• Texturas:<br />

– Gestión de texturas:<br />

• Estructura IDirect<strong>3D</strong>texture9.<br />

• Crear textura: D<strong>3D</strong>XCreateTextureFromFile.<br />

• Asignar textura: IDirect<strong>3D</strong>Device9::SetTexture.<br />

– Filtros: Mejoran la apariencia de las texturas cuando<br />

se produce distorsión (punto más cercano, lineal,<br />

anisotrópico).<br />

– Mipmaps: Uso de varias texturas de diferente tamaño<br />

para reducir la distorsión.<br />

– Direccionamiento: Comportamiento cuando los<br />

valores en el espacio de texturas salen del rango [0,<br />

1] (wrap, clamp, border color, mirror).


Realismo de escenas<br />

• Ejemplo completo: Texturas<br />

– Chapter 6\TexCube


Realismo de escenas<br />

• Blending:<br />

– Combinar píxeles que se están rasterizando<br />

en este momento <strong>con</strong> otros que se han<br />

rasterizado previamente.<br />

• Stenciling:<br />

– Uso de un buffer adicional para realizar<br />

efectos de iluminación que requieren<br />

renderizar selectivamente ciertos objetos<br />

(espejos, proyección de sombras, etc.)


Esquema<br />

• Comenzando <strong>con</strong> Direct<strong>3D</strong><br />

• Proceso de renderizado<br />

• Representación de escenas <strong>3D</strong> <strong>con</strong> D<strong>3D</strong><br />

• Realismo de escenas<br />

• Shaders<br />

–Descripción<br />

– Programación<br />

– Vertex shaders<br />

– Pixel shaders


Shaders<br />

• Los shaders son piezas de código que permiten<br />

modificar la forma en que se realiza alguna de<br />

las fases del proceso de renderizado.<br />

• Se ejecutan directamente sobre el hardware de<br />

la GPU (Graphics Processing Unit).<br />

• Aumentan la flexibilidad y la eficiencia en el<br />

proceso de generación de gráficos <strong>3D</strong>.<br />

• Lenguajes:<br />

– Ensamblador de bajo nivel específico de la GPU.<br />

– Lenguajes de alto nivel para shaders: Cg, GLSL,<br />

<strong>DirectX</strong> HLSL.


Shaders<br />

• Programación de shaders:<br />

– Crear fichero de texto <strong>con</strong> código shader.<br />

– Compilar shader:<br />

• Estática (en tiempo de compilación)<br />

• Dinámica (en tiempo de ejecución)<br />

– Cargar shader<br />

– Activar shader<br />

– Ejecutar shader


Shaders<br />

• Vertex shaders:<br />

– Reemplazan las fases de transformación e iluminación en el proceso de<br />

renderización.<br />

– Suelen ejecutarse en la GPU de la tarjeta gráfica, aunque puede<br />

emularse por software.<br />

– Permiten implementar nuevos algoritmos de iluminación y modificar la<br />

posición de los vértices (sistemas de partículas, morphing, etc.).<br />

Espacio de<br />

Coordenadas<br />

Locales<br />

Espacio de<br />

Coordenadas de<br />

Mundo<br />

Recorte Proyección<br />

Espacio de<br />

Coordenadas de<br />

Vista<br />

Espacio de<br />

Coordenadas de<br />

Viewport<br />

Eliminación de<br />

Caras Ocultas<br />

Rasterización<br />

Vertex Shader<br />

Iluminación


Shaders<br />

• Pixel Shaders:<br />

– Reemplazan la fase de rasterización durante el proceso de<br />

renderización.<br />

– No se emulan por software.<br />

– Permiten acceder directamente a píxeles y texturas (multi-texturing,<br />

iluminación píxel a píxel, simulación de nubes, sombreado, etc.).<br />

Espacio de<br />

Coordenadas<br />

Locales<br />

Espacio de<br />

Coordenadas de<br />

Mundo<br />

Recorte Proyección<br />

Espacio de<br />

Coordenadas de<br />

Vista<br />

Espacio de<br />

Coordenadas de<br />

Viewport<br />

Eliminación de<br />

Caras Ocultas<br />

Rasterización<br />

Pixel Shader<br />

Iluminación


Recursos<br />

• Introduction to <strong>3D</strong> Game Programming<br />

with <strong>DirectX</strong> 9. F. D. Luna. Wordware,<br />

2003.<br />

• Beginning <strong>DirectX</strong> 9. W. Jones. Premier<br />

Press, 2004.<br />

• Computer Graphics: Principles and<br />

Practice. J. D. Foley et. al. Addison-<br />

Wesley Professional, 1990.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!