lunes, 7 de junio de 2010

Currar de un solo lado es plagio, pero de varios es creatividad.

La mayor parte de los algoritmos, implementaciones, código y demas fruta que voy a publicar aca , estan basadas en cosas que encontre en la web. Sin embargo, tambien hay ideas que se me ocurrieron espontaneamente, pero estoy seguro que tambien están en internet, (o estan mal, o las dos cosas).

Al poco tiempo que empece a estudiar el directx llegue a la conclusión que la verdad de la milanesa esta en los shaders: basicamente son pequeños fragmentos de código que se ejecutan directamente en la placa de video. El vertex shader se ejecuta por cada vértice, lo mínimo que hace es recibir la posición (sin transformar) del vértice y genera como salida la posición transformada. El pixel shader por su parte se ejecuta por cada pixel, y recibe ciertos valores calculados por el vertex shader (por ejemplo la normal, el color, el uv de la textura, etc) interpolados en el polígono, generando en la salida usualmente el color final del pixel.

Aca hay un link donde esta todo explicado cortito y al pie
http://www.toymaker.info/Games/html/shaders.html

Para escribir estos fragmentos se puede usar una especie de asembler de la placa, o lo que es más habitual: usar HLSL, que es un lenguaje especialmente diseñado para escribir los shaders. Es de sintaxis similar al C, cuenta con decenas de funciones intrínsicas, operaciones vectoriales, etc etc. Viene bien un vistazo a la ayuda del directx, busquen "HLSL Language Basics" que está todo explicado.
Estos programas usualmente se graban en un archivo de efectos (.fx) y se pueden compilar en runtime con una función del DX: D3DXCreateEffectFromFile

Hay que tener en cuenta que estos fragmentos de código se ejecutan en forma paralela de a varios pixeles o vértices a la vez dependiendo de la arquitectura de la placa. Este es uno de los motivos por los cuales hay toda un área de investigación orientada a resolver problemas NO gráficos con la GPU. Generalmente son problemas donde hay un alto grado de paralelismo, por ejemplo la dinámica de fluidos, sistemas de partículas, gases, etc. Aca hay un link de CUDA (que es de nvidea) http://www.nvidia.es/object/cuda_home_new_es.html

Dejando de lado esto del CUDA, para aplicaciones gráficas comunes y corrientes, tambien hay que pensar en el problema desde otro punto de vista. La forma de resolver un problema con la GPU es bastante diferente a como se haría habitualmente.
Es común usar las texturas como matrices o vectores para almacenar datos. Para esto se utiliza la técnica de renderizar en una textura: es decir que la salida en vez de ir a la pantalla como es habitual, se almacena en una textura. Tambien es habitual que la salida en lugar de ser el color pp dicho (un RGBA) sea algún otro valor numérico que necesitamos calcular y que se alamacerá en dicha textura. Por este motivo el DX soporta varios formatos de texturas además del RGBA que se usa para dibujar en pantalla, por ejemplo hay varios formatos de texturas en punto flotante, como el D3DFMT_R32F que almacena en cada pixel un float de 32 bits en el canal Red.
El pixel shader (y con ciertas limitaciones el vertex shader tambien), pueden acceder a los datos de la textura. Usualmente lo hacen para obtener el color del pixel (texture mapping) y a esto aplicarle algun factor de iluminación. Pero tambien puede ser para usar datos previamente grabados por el pixel shader o escritos por el programa de la CPU. En estos casos se renderiza varias veces, antes de hacer el render a pantalla final.

De esta manera, con ciertas limitaciones, las texturas actuan como la memoria en el modelo standard de CPU, pero se trata de una memoria de sólo lectura. Para escribir a la textura la única forma es ponerla como RenderTarget, es decir redireccionar la salida de pantalla a esa textura.

La próxima un ejemplo concreto.

No hay comentarios:

Publicar un comentario