miércoles, 31 de julio de 2013

Algoritmo de ordenamiento QuickSort

Artículo perteneciente a la sección de algoritmos

Hola a todos,

Si habéis seguido la sección de algoritmos habréis visto ya los algoritmo más fáciles de implementar e ineficientes. Ahora le toca el turno a un algoritmo que es de lo más eficientes que existen sin tener un complejidad excesiva, el algoritmo QuickSort.

Este algoritmo se basa en la teoría de divide y vencerás. Parte el vector a ordenar en dos trozos, en la parte más baja pone los números más bajos y en la parte más alta los números más altos. Después se aplica el mismo procedimiento a cada una de las partes de forma recursiva hasta que no se puede dividir más... en ese momento el vector ya está ordenado.

El problema de este algoritmo más allá de su implementación (que ya veréis que tampoco es tan compleja) es la elección del valor (llamado pivote) que se usa para dividir cada una de las listas. Si el pivote está justo en el medio de la lista, el rendimiento es óptimo, si el pivote está a un extremo de los valores de esa subsección el rendimiento es parecido al del algoritmo de burbuja, el problema es que no es fácil encontrar ese valor. Para lo que nos interesa aquí ( que aprendáis el algoritmo) no nos hace falta decir más, si estáis interesados comentadlo y tal vez me expanda un poco más la explicación.

El código de este algoritmo es el siguiente:

int LPVector::distribuir(int b, int t)
{
    int i;
    int pivote, valor_pivote;
    int temp;

    pivote = b;
    valor_pivote = v[pivote];

    for (i=b+1; i<=t; i++)
{
        if (v[i] < valor_pivote)
{
           pivote++;
           temp=v[i];
           v[i]=v[pivote];
           v[pivote]=temp;
}
    }
    temp=v[b];
    v[b]=v[pivote];
    v[pivote]=temp;
return pivote;
}

void LPVector::RecursiveQuicksort(int b, int t)
{
int pivote;
    if(b < t)
{
pivote=distribuir(b, t);
        RecursiveQuicksort(b, pivote-1);
        RecursiveQuicksort(pivote+1, t);
    }
}

void LPVector::QuickSort(void)
{
RecursiveQuicksort(0,n-1);
}


Espero que os haya servido y hayáis aprendido un poco más sobre los algoritmos de ordenación.

En breve comenzaré con las comparativas entre algoritmos y las implementaciones en asm

Nos vemos

LordPakusBlog

lunes, 29 de julio de 2013

Algoritmo de ordenamiento por selección (Selection Sort)

Artículo perteneciente a la sección de algoritmos

Este artículo es una evolución del algoritmo de ordenación por burbuja

Hola a todos,

Hace poco os explique el algoritmo de ordenación por burbuja y el de ordenación por burbuja bidireccional. Pese a que este segundo es una evolución un poco mejor que el original, el problema de que usa demasiada memoria sigue ocurriendo.

En las arquitecturas hardware (tantos las actuales, como las antiguas, y seguramente también las futuras) lo que más limita la velocidad de ejecución de un programa es el acceso a memoria. Si nuestro algoritmo usa de forma intensiva la memoria lo más normal es que su rendimiento sea bajo.

Con esta premisa nació el algoritmo de ordenación por selección.  La idea es simple. Busco el elemento más pequeño de la lista, y lo intercambio con el elemento de la primera posición... busco el segundo elemento más pequeño y lo intercambio con el elemento de la segunda posición. Con esto se hace más o menos el mismo número de comparaciones que se hacen con el algoritmo de burbuja tradicional, pero con muchos menos movimientos  de memoria, y por lo tanto con un rendimiento claramente superior.

Un ejemplo de código de este algoritmo sería el siguiente:

void LPVector::SelectionSort(void)
{
int i,j,indmin=0;
float min = v[0];

for ( i = 0 ; i < (n-1) ; ++i)
{
indmin = i;
min = v[i];
for( j = i+1 ; j < n ; ++j)
{
if(v[j] < min )
{
indmin = j;
min = v[j];
}
}

v[indmin] = v[i];
v[i] = min;
}
}


No podemos decir que sea un algoritmo eficiente (su coste depende de forma cuadrática con la longitud del vector), pero si que podemos asegurar que solo hará tantos movimientos de memoria como elementos haya en el vector, y esto ya es una clara mejora.

En breve haré una lista comparativa con los costes de cada algoritmo en diferentes situaciones para que os hagáis una idea.

Espero que os sirva de referencia

Nos vemos


LordPakusBlog

domingo, 28 de julio de 2013

Algoritmo de ordenación de Burbuja bidireccional (ordenación por sacudida o Cocktail Sort)

Artículo perteneciente a la sección de algoritmos

Este artículo es una evolución del algoritmo de ordenación por burbuja

Hola a todos,

Si ya habéis visto como funciona el algoritmo de ordenación por burbuja habréis observado que es fácil llevar los números grandes hasta el final de la lista, pero que es complicado llevar los números pequeños al inicio de la lista. Dependiendo de como estén ordenados los números a priori se puede llegar a tardar bastante en ordenarlos.

La solución es sencilla... ordenar con el método de burbuja y cuando llegamos al final de la primera iteración, no volver a realizar el cálculo desde el principio sino que empezaremos desde el final hasta al inicio. De esta manera siempre se consigue que tanto los números pequeños como los números grandes se desplacen a los extremos de la lista lo más rápido posible. Esto otorga el beneficio adicional que la lista cada vez se nos hace más pequeña (en los extremos de la lista vamos almacenando los elementos defnifitivos que nunca más se tendrán que mirar).

El código es tal que así (solo tiene fines educativos, no es una implementación terriblemente eficiente):

void LPVector::CocktailSort(void)
{
int i , j = 0 ;
float temp = 0.0;

do
{
for (i = j ; i < (n-1-j); ++i)
{
if(v[i] > v[i+1])
{
temp = v[i+1];
v[i+1] = v[i];
v[i] = temp;
}
}

if(!this->IsSorted())
{
for (i = ( n - 1 - j ) ; i > j ; --i)
{
if(v[i] < v[i-1])
{
temp = v[i-1];
v[i-1] = v[i];
v[i] = temp;
}
}
}

j++;

}while(!this->IsSorted());
}

Espero que esta idea tan sencilla para mejorar el algoritmo de burbuja os inspire para buscarle más soluciones a vuestros problemas.

Nos vemos
LordPakusBlog

Algoritmo de ordenamiento por burbuja (BubbleSort)

Artículo perteneciente a la sección de algoritmos

Hola a todos,

El método de ordenamiento por burbuja (más conocido como BubbleSort) es uno de los algoritmos más sencillos para ordenar listas de números.

Su funcionamiento es extremadamente simple.
1. Se comparan los dos primeros números de la lista y se ordenan (el menor se pone en la posición más baja y el mayor se pone en la posición más alta de los dos)

2. Se compara el segundo con el tercer elemento y se repite la misma operación. Se aplica este sistema hasta el final de la lista de números.

3. Cuando se llega al final, se vuelve a empezar desde el principio. Cuando en una de estas iteraciones no se tiene que hacer ningún cambio de elementos significa que ya se ha hecho todo el proceso de ordenación.

Para realizar el código de este tutorial he tomado de base el del MathEngine que escribí hace ya unos años. En cuanto tenga un rato arreglaré todo el código antiguo, le daré una buena repasada a la calidad del código de este proyecto y lo subiré al svn.

Aquí tenéis un ejemplo de código de como realizar el BubbleSort (n es el número de elementos del vector y v es el vector como tal):

void LPVector::BubbleSort(void)
{
int i, j = 0 ;
float temp = 0.0;

do
{
for (i = 0 ; i < (n-1-j); ++i)
{
if(v[i] > v[i+1])
{
temp = v[i+1];
v[i+1] = v[i];
v[i] = temp;
}
}
  j++;
}while(!this->IsSorted());
}

char LPVector::IsSorted(void)
{
int i;

for(i = 0 ; i < (n-1); ++i)
{
if( v[i] > v[i+1] )
return 0;
}
return 1;
}

Tal y como he dicho antes es de los algoritmos de ordenación más sencillos de implementar que puedan existir, el problema es que su rendimiento no es demasiado bueno. En capítulos posteriores haremos una comparativa de rendimientos entre diferentes métodos de ordenación.

Si queréis hacer la prueba de que funciona correctamente podéis ejecutar algo de este estilo:

int main (int argc, char* argv[])
{
    LPVector v1;
float vecsorted[5] = { 1.0,2.0,3.0,4.0,5.0 };
float vecinverted[5] = { 5.0,4.0,3.0,2.0,1.0};
float vecrandom[5] = { 2.0, 4.0, 1.0, 5.0, 3.0};

   cout << endl << "Vector ya ordenado " << endl;

v1.Set(5,vecsorted);
v1.print();

cout << endl;

v1.BubbleSort();
v1.print();


cout << endl << "Vector ordenado al reves" << endl;

v1.Set(5,vecinverted);
v1.print();

cout << endl;

v1.BubbleSort();
v1.print();


cout << endl << "Vector totalmente desordenado " << endl;

v1.Set(5,vecrandom);
v1.print();

cout << endl;

v1.BubbleSort();
v1.print();

cout << endl;

    //Eliminamos los vectores
    v1.Delete();

    system("PAUSE");
}

Y la ejecución debería daros algo del estilo de :


Como nota final, si os fijais, el nombre de ordenamiento por burbuja es totalmente correcto debido a que los elementos del vector se van desplazando arriba y abajo como si fueran burbujas.

Espero que os haya gustado

Nos vemos





LordPakusBlog

martes, 23 de julio de 2013

Antipatrones de diseño

Artículo perteneciente a la sección de calidad de código

Hola a todos,

En el capítulo anterior hablamos de los antipatrones de diseño como un tipo de "olor del código",  pero.. que es un antipatrón de diseño??

De la misma manera que un patrón de diseño es una herramienta que usada con moderación y cautela puede disminuir la complejidad del código, el antipatrón de diseño es una manera de diseñar, enfocar el desarrollo y/o implementar el código que conduce con bastante seguridad al desastre.

Lo peor de los antipatrones es que en muchas ocasiones los tenemos tan incrustados en nuestra manera de trabajar que hasta que no nos hacen ver que ahí tenemos un problema no podemos reaccionar.

La lista de antipatrones es larga y abarca numerosos ámbitos del desarrollo del software , así que solo pondré los más representativos para que os hagáis una idea de como va el tema. Además de esto, cada antipatrón tiene un nombre "divertido" para facilitar su aprendizaje ("Pollo sin cabeza" , "Gran bola de lodo" son solo dos ejemplos :) ), yo me abstengo a poner esos nombres, en primer lugar por que al provenir del inglés las traducciones y matices son múltiples y en segundo lugar por que os confundiría más que ayudaría. Recordemos que esto solo es un pequeño tutorial para saber de que va el tema de los antipatrones. Aquí os dejo la lista resumida de antipatrones:

- Antipatrones de gestión: 
      - Buscar la productividad a toca costa, olvidando la calidad del código o la calidad de vida de los trabajadores
       - Responsable que no da la talla: o nunca está localizable, o no gestiona bien, o no da la cara por sus trabajadores o no es justo en el trato a los miembros del equipo,etc...
       -  Trabajadores con demasiada diferencia de nivel, hacen que al final todas las responsabilidades vayan a parar a la misma persona.

- Antipatrones del diseño de software:
        - Concentrar demasiadas responsabilidades en un solo módulo
        - No determinar correctamente las decisiones complejas del proyecto
        - Diseñar un sistema sin una estructura clara
        - Diseñar de una manera extremadamente compleja.

- Antipatrones de programación:
         - No utilizar una nomenclatura clara y veraz
         - Programar con más complejidad de la necesaria para resolver el problema
         - Programar sistemas con una estructura poco clara y enrevesada.
         - Usar hardcodeos sin ninguna explicación de donde vienen.
         - Ocultar errores y parchearlos en vez de solucionarlos realmente.

Hay muchísimos más, si os interesa el tema googlead y encontrareis cientos de ellos.

Si os da pereza googlear o directamente queréis ir a fuentes más serias podéis mirar los siguientes libros especializados en antipatrones del software:


Espero que os haya servido para entender un poco más sobre calidad de código.

Nos vemos



LordPakusBlog

jueves, 18 de julio de 2013

Code Smell: ¿ A que huele el código ?

Artículo perteneciente a la sección de calidad de código

Hola a todos,

En muchas ocasiones no tenemos tiempo para revisar a conciencia el código de otras personas, pero paradójicamente, a medida que vamos ganando experiencia todos los programadores obtenemos un cierto sexto sentido para detectar código que da "mala espina". No se puede explicar y como mucho se puede decir que la nomenclatura de las variables no es demasiado correcta, o que el código está estructurado "raro", o que cuesta de entender... es difícil argumentar esa sensación.

En los 90 Kent Beck (uno de los grandes investigadores de la calidad de código) acuñó el término de Code Smell (Mal olor del código) y propuso una lista básica de factores(que ha sido revisada y ampliada por cientos de personas) que hacen inclinarnos a pensar que el código no está bien del todo:
   - Código duplicado.
   - Código muerto.
   - Funciones grandes.
   - Demasiados parámetros.
   - Uso forzado de patrones de diseño.
   - Nombres de variables y funciones demasiado largos.
   - Nombre de variables y funciones demasiado cortos.
   - Nombres de variables y funciones que no explican lo que realmente hacen.
   - Uso excesivo de hardcodeos (datos que podrían estar en ficheros de configuración en vez de dentro el código)
   - Sentencias switch en exceso.(en lenguajes orientados a objetos, implica un mal diseño de herencia)
   - Excesivos comentarios.
   - Bloques de If's excesivamente grandes
   - Demasiado código preparado "porsiacaso" (cuando no se sabe nunca de lo que realmente pasará en el futuro)
   - Uso excesivo de tipos primitivos
   - Las funciones deberían tener solo una responsabilidad.
   - Encadenamiento excesivo (cuando se tiene una función que solo llama a otra, que llama a otra, que llama a otra.....)
    - Detección de un antipatrón de diseño (ya lo explicaremos con más calma en otro artículo)

El hecho que en el código que revisamos veamos alguna de estas características no significa que haya algo necesariamente mal, pero da bastantes indicios de que seguramente habrá problemas y será una zona de código que se deberá revisar con más detenimiento.

Espero que os haya gustado

Ya como nota final, os comento que el término Code Smell surgió en este libro, por si os interesa:


Nos vemos



LordPakusBlog

lunes, 8 de julio de 2013

DirectX desde 0. Capitulo 3. Shaders en DirectX 11

Artículo perteneciente al tutorial de DirectX desde 0

Hola a todos,

Tal vez poner en una misma frase "tutorial desde 0" y "shaders de Directx11" no es lo más correcto del mundo. De hecho, OpenGL también tiene shaders y cuando hice el tutorial de OpenGL desde 0 creo recordar que ni los mencioné por que me pareció que se escabapaban totalmente del obejtivo del curso, pero DirectX 11 es diferente.

Dentro del paradigma de trabajo de DirectX11 los shaders tienen una importancia vital, hasta el punto que se puede decir que prácticamente todo lo que hagamos serán shaders, así que si que está justificado hablar de ellos aunque estemos en un punto muy inicial del curso.

Pero... ¿que es un shader? Un shader es un programa muy sencillo , pensado para ejecutarse sobre la GPU (tarjeta gráfica) escrito en HLSL ( un pseudoC ). La idea del shader es trabajar directamente en el flujo de proceso de la tarjeta gráfica, obteniendo datos de una etapa anterior para procesarlos y servirlos a una etapa posterior. Una de las ventajas de los shaders es que no se compilan junto con el código, sino en tiempo de carga, esto significa que de cara al desarrollo cuentan como scripts y agilizan mucho el tiempo de creación de nuestras aplicaciones (evitamos recompilar, que cuando el proyecto es grande, puede llegar a ser un tiempo de decenas de mínutos )

En función de en que etapa del proceso está los shaders se llaman de una manera u otra y tienen diferentes ámbitos de trabajo:

- Vertex Shaders: Son shaders que trabajan solamente con los vértices de la escena (se puede modificar posición, color, iluminación, textura, etc...), pero tratan cada vértice por separado, es decir, al ejecutarse el vertex shader no sabemos que vértice estamos manipulando. Es muy usado para transformaciones del espacio ( traslaciones , rotaciones , etc...) y deformación de mallas. Nunca podrá eliminar o crear un vértice, solo modificarlo.

- Geometry Shaders: Son shaders que trabajan con un modelo 3D y que permiten incluir y eliminar vértices a la malla en la que se está trabajando. Muy usados para generar modelos de diferentes niveles de precisión.

- Pixel Shaders: Son shaders que trabajan a nivel de pixel y que por lo tanto son muy útiles para hacer efectos de iluminación y sombreado.

- Compute Shaders: Estos shaders son un caso especial de shader no relacionado directamente con el pintado. Es decir, son shaders (se ejecutan en la GPU) pero su funcionamiento puede ser el que se quiera. Se basa en el aprovechamiento de los múltiples procesadores en paralelo que tienen las tarjetas gráficas para poder hacer cálculos de físicas, IA, etc...

Para que veáis mejor donde se ejecuta cada shader podéis mirar el siguiente gráfico sacado de la mdsn


Espero que os sirva y os haya gustado. A medida que avancemos en el curso iréis viendo más ejemplos de shaders extremadamente útiles. De mientras podéis ver un ejemplo de Vertex y Pixel shader aqui

Nos vemos



LordPakusBlog

domingo, 7 de julio de 2013

DirectX desde 0. Capitulo 2. Pintando con DirectX11 (Triángulos y Shaders)

Artículo perteneciente al tutorial de DirectX desde 0

Hola a todos,

El capítulo de hoy se basa en parte en el capitulo número 4 de rastertek que podréis ver aquí.

Cuando se empieza a aprender una API gráfica lo primero que hay que saber es como se pinta un triangulo. En OpenGL es bastante sencillo (siempre y cuando no nos importe demasiado el rendimiento) mientras que en DirectX es un proceso más tedioso y que generalmente va cambiando su manera de implementarse entre versiones. De hecho, uno de los grandes problemas que hay con DirectX (sobretodo el 11)  es que encontrar un buen tutorial en castellano que explique de forma sencilla como pintar un triangulo casi casi es imposible.

La gracia está en que aunque la curva de aprendizaje de DirectX sea más dura que la de OpenGL nos obliga ya desde el principio a usar la tarjeta gráfica correctamente . Con OpenGL podíamos pintar triángulos mediante primitivas directas aunque fuera ineficiente (ver aquí para más información) mientras que con DirectX hemos de situar toda la información de nuestro pintado en vectores y luego pasarle esos vectores a la tarjeta gráfica ( aunque ahora mismo no os lo pueda parecer es una de las maneras más eficientes de computar gráficos ya que se trabaja directamente con memoria de video.)

A nivel de código el pintado de un cuadrado quedaría tal que así,:

Por un lado la inicialización de la información de pintado
bool ModelClass::InitializeBuffers(ID3D11Device* device)
{
VertexType* vertices;
unsigned long* indices;
D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc;
    D3D11_SUBRESOURCE_DATA vertexData, indexData;
HRESULT result;


NOTA: DirectX 11 nos obliga a pasarle a la tarjeta gráfica un vector con todos los vertices y un vector con todos los indices a esos vértices que usaremos para conformar triángulos  Esto es debido a que normalmente un vértice acostumbra a formar parte de más de un triangulo.

//Seteamos el número de vértices que vamos a pintar (4, por que es un cuadrado)
m_vertexCount = 4;

//Seteamos el número de indices que usaremos (6, por que describimos dos triángulos)
m_indexCount = 6;

// Create the vertex array.
vertices = new VertexType[m_vertexCount];
if(!vertices)
{
return false;
}

// Create the index array.
indices = new unsigned long[m_indexCount];
if(!indices)
{
return false;
}

NOTA: En la lista de vértices no solo pondremos su posición espacial sino que incluiremos todo aquello que puede modificar su pintado, como por ejemplo, el color.
vertices[0].position = D3DXVECTOR3(-1.0f, -1.0f, 0.0f);
vertices[0].color = D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f);

vertices[1].position = D3DXVECTOR3(-1.0f, 1.0f, 0.0f);
vertices[1].color = D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f);

vertices[2].position = D3DXVECTOR3(1.0f, 1.0f, 0.0f);
vertices[2].color = D3DXVECTOR4(0.5f, 0.5f, 0.5f, 0.5f);

vertices[3].position = D3DXVECTOR3(1.0f, -1.0f, 0.0f);
vertices[3].color = D3DXVECTOR4(0.0f, 0.0f, 1.0f, 1.0f);

// Load the index array with data.
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 2;
indices[4] = 3;
indices[5] = 0;

// Set up the description of the static vertex buffer.
    vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    vertexBufferDesc.ByteWidth = sizeof(VertexType) * m_vertexCount;
    vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vertexBufferDesc.CPUAccessFlags = 0;
    vertexBufferDesc.MiscFlags = 0;
vertexBufferDesc.StructureByteStride = 0;

// Give the subresource structure a pointer to the vertex data.
    vertexData.pSysMem = vertices;
vertexData.SysMemPitch = 0;
vertexData.SysMemSlicePitch = 0;

// Now create the vertex buffer.
    result = device->CreateBuffer(&vertexBufferDesc, &vertexData, &m_vertexBuffer);
if(FAILED(result))
{
return false;
}

NOTA: Le pasamos la información de vertices e indices a la tarjeta gráfica
// Set up the description of the static index buffer.
    indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    indexBufferDesc.ByteWidth = sizeof(unsigned long) * m_indexCount;
    indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
    indexBufferDesc.CPUAccessFlags = 0;
    indexBufferDesc.MiscFlags = 0;
indexBufferDesc.StructureByteStride = 0;

// Give the subresource structure a pointer to the index data.
    indexData.pSysMem = indices;
indexData.SysMemPitch = 0;
indexData.SysMemSlicePitch = 0;

// Create the index buffer.
result = device->CreateBuffer(&indexBufferDesc, &indexData, &m_indexBuffer);
if(FAILED(result))
{
return false;
}

// Release the arrays now that the vertex and index buffers have been created and loaded.
delete [] vertices;
vertices = 0;

delete [] indices;
indices = 0;

return true;
}


Por otro lado la petición de que esa información que hay en tarjeta gráfica se pinte de una manera u otra se hace mediante el Render. Al igual que OpenGL, DirectX usa matrices para realizar los cálculos de transformación del espacio, así que el siguiente código os debería resultar minimamente familiar.

bool GraphicsClass::Render()
{
D3DXMATRIX worldMatrix, viewMatrix, projectionMatrix;
bool result;


// Clear the buffers to begin the scene.
m_D3D->BeginScene(0.0f, 0.0f, 0.0f, 1.0f);

// Generate the view matrix based on the camera's position.
m_Camera->Render();

NOTA: Obtenemos las matrices de transformación del espacio y las almacenamos en memoria
// Get the world, view, and projection matrices from the camera and d3d objects.
m_Camera->GetViewMatrix(viewMatrix);
m_D3D->GetWorldMatrix(worldMatrix);
m_D3D->GetProjectionMatrix(projectionMatrix);

// Put the model vertex and index buffers on the graphics pipeline to prepare them for drawing.
m_Model->Render(m_D3D->GetDeviceContext());

NOTA: Usamos un shader para realizar el render. Al final de este artículo explicaremos lo que es un shader de forma rápida.
result = m_ColorShader->Render(m_D3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix);

if(!result)
{
return false;
}

// Present the rendered scene to the screen.
m_D3D->EndScene();

return true;
}

Un shader, concepto nuevo en estos tutoriales, es un pequeño programa usable desde DirectX o desde OpenGL  que se encarga de ejecutarse directamente en la tarjeta gráfica. Hay diferentes tipos de shaders, los más usados: pixel shader y vertex shader. El shader usado en este tutorial es del tipo vertex shader y se encarga de aplicar las matrices de transformación de nuestra escena a nuestro modelo para poderlo renderizar correctamente por pantalla. Este proceso se podría realizar mediante CPU, pero es obvio que va más rápido si se ejecuta en la GPU.

El código del shader usado es el siguiente:
////////////////////////////////////////////////////////////////////////////////
// Filename: color.vs
////////////////////////////////////////////////////////////////////////////////


/////////////
// GLOBALS //
/////////////
cbuffer MatrixBuffer
{
matrix worldMatrix;
matrix viewMatrix;
matrix projectionMatrix;
};


//////////////
// TYPEDEFS //
//////////////
struct VertexInputType
{
    float4 position : POSITION;
    float4 color : COLOR;
};

struct PixelInputType
{
    float4 position : SV_POSITION;
    float4 color : COLOR;
};


////////////////////////////////////////////////////////////////////////////////
// Vertex Shader
////////////////////////////////////////////////////////////////////////////////
PixelInputType ColorVertexShader(VertexInputType input)
{
    PixelInputType output;
 

// Change the position vector to be 4 units for proper matrix calculations.
    input.position.w = 1.0f;

// Calculate the position of the vertex against the world, view, and projection matrices.
    output.position = mul(input.position, worldMatrix);
    output.position = mul(output.position, viewMatrix);
    output.position = mul(output.position, projectionMatrix);
 
// Store the input color for the pixel shader to use.
    output.color = input.color;
 
    return output;
}

En breve haré un capítulo enfocado solamente a shaders para que veais toda la potencia que tienen.

Ya para finalizar, si os bajáis el código del svn, compilad y ejecutad, debería quedaros algo tal que así:


Espero que os haya gustado

Nos vemos


LordPakusBlog

lunes, 1 de julio de 2013

DirectX desde 0. Capitulo 1. Iniciando DirectX

Artículo perteneciente al tutorial de DirectX desde 0

Hola a todos,

Bienvenidos al primer capitulo del tutorial de DirectX 11 desde 0.

DirectX es un conjunto de funcionalidades proporcionadas por Microsoft para crear videojuegos. La ventaja principal respecto a OpenGL es que engloba muchas funcionalidades ( gráficos, sonidos, inputs, textos) que OpenGL no cubre (ya que es solo es una API gráfica). La principal desventaja de DirectX es que solo funciona en productos Microsoft ( es decir, Windows ) con lo que el tema portabilidad queda descartado.

Hay bastantes versiones de DirectX (ahora mismo van por la 11) y no son demasiado compatibles entre si, así que creo que vale la pena empezar directamente por la última versión.

Antes que nada deberemos preparar nuestro PC para que funcione con DirectX:

1. Instalar el SDK de DirectX11. Lo podéis descargar de aqui
2. Es posible que al finalizar la instalación del SDK de DirectX os salga un error s1023. Estad tranquilos que tiene solución, lo mejor que podéis hacer es ir al siguiente link.
3. Si no lo tenéis, bajaos el Visual Studio Express Edition. Para trabajar con DirectX es la mejor opción.
4. Bajaos el código de este tutorial, ya sea por svn  o por descarga.

Para realizar este tutorial me he basado en el tutorial número 3 de rastertek y lo he modificado ligeramente para que funcione en hardware que no admite directamente DirectX11. Un problema del tutorial de rastertek es que si tu tarjeta de video no soportaba nativamente DirectX11 no funcionaba nada, y no creo que sea plan que por un mero tema de hardware nos perdamos un buen tutorial no?

El código lo podéis mirar aquí y la modificación realizada solo ha sido lo siguiente:

if(FAILED(result))
{
result = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_WARP, NULL, 0, &featureLevel, 1, D3D11_SDK_VERSION, &swapChainDesc, &m_swapChain, &m_device, NULL, &m_deviceContext);
}

if(FAILED(result))
{
result = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_SOFTWARE, NULL, 0, &featureLevel, 1, D3D11_SDK_VERSION, &swapChainDesc, &m_swapChain, &m_device, NULL, &m_deviceContext);
}

Por ahora, con que miréis el código del svn y seais capaces de instalaros el SDK y compilar, suficiente.

En cuanto lo tengáis compilado, ejecutad, os debería salir una ventana en gris.

En el siguiente capítulo empezaremos ha hablar realmente de DirectX.

Espero que os haya gustado

Nos vemos


LordPakusBlog

Entradas populares