Aprende a desarrollar aplicaciones gráficas 2D y 3D paso a paso.
Programacion Grafica: Desarrollo 2D/3D con C++ y DirectX/OpenGL/GLUT/SDL - Windows/Linux


  Crear una cuenta
 • Portada • Descargas • Tu Cuenta • 
Menú
 Portada
 Noticias
 Archivo de Noticias
 Temas
 Descargas
 Inicio
 Ver Nuevas
 Más Popular
 Más Votadas
 Contenido
 Contenido
 Secciones
 Enciclopedia
 Revisiones
 FAQ
 Tus Opciones
 Tu Cuenta
 Mensajes Privados
 Recomiéndenos
 Buscar
 Diarios
 Contacto
 Enlaces Web
 Inicio
 Enviar Enlace
 Ver Nuevos
 Más Popular
 Más Valorados
 Estadísticas
 Inicio
 Detalladas
 Top 10
 
Estadísticas
 
Tutorial 10 - Luces, normales, materiales 
DirectX/Opengl

En este tutorial vamos a añadir luz a nuestro mundo 3-D. Con ello podremos recrear objetos sólidos con sombreado.



En primer lugar hemos cambiado la estructura que define nuestro cubo de forma que almacenaremos lo que se denominan normales.

Una normal es un vector perpendicular a un plano cuya longitud es uno. Se utilizan vectores normales para calcular cómo debe renderizarse una cara, para calcular cómo incide la luz en ella en función de su inclinación respecto a la fuente de luz. Dado un vértice, que comparte caras, puede asociarse un vector normal a un vértice como el que resulta de la suma y normalización de los vectores de las caras a las que pertecede el vértice.

Así que ahora, para cada cara del cubo, tendremos un vector normal a ésta más los íncides que referenciarán a los vértices que componen la cara del cubo.


    //
    //      v7     v6
    //      *------*
    //   v4/.  v5 /|
    //    *-----*  |
    //   v|3*...|..* v2
    //    |.    | /
    //    *-----*/
    //   v0     v1
    //
    MeshCube GraphicApplication::m_Cube =
    {
        /* Vertex */
        {
            {-0.5f,-0.5f, 0.5f},    /* v0 */
            { 0.5f,-0.5f, 0.5f},    /* v1 */
            { 0.5f,-0.5f,-0.5f},    /* v2 */
            {-0.5f,-0.5f,-0.5f},    /* v3 */
            {-0.5f, 0.5f, 0.5f},    /* v4 */
            { 0.5f, 0.5f, 0.5f},    /* v5 */
            { 0.5f, 0.5f,-0.5f},    /* v6 */
            {-0.5f, 0.5f,-0.5f}     /* v7 */
        } ,

        /* Faces */
        {
            { { 0, 0, 1 }, {4,0,5,1} }, /* frontal   */
            { { 1, 0, 0 }, {5,1,6,2} }, /* derecha   */
            { { 0, 0,-1 }, {6,2,7,3} }, /* trasera   */
            { {-1, 0, 0 }, {7,3,4,0} }, /* izquierda */
            { { 0, 0, 1 }, {4,5,7,6} }, /* superior  */
            { { 0, 0,-1 }, {3,2,0,1} }  /* inferior  */
        }
    };

Para trabajar con luces, hemos definido la estructura Light que define una fuente de luz. Las habrá de tres tipos, direcciónal, puntual o cónica. También hemos definido la estructura Material para especificar cómo refleja la luz un objeto en función del material que lo compone.


    ///////////////////////////////////////////////////////////////////////////////
    /// enum   e_LIGHT_TYPE Tipos de luces.
    ///////////////////////////////////////////////////////////////////////////////
    enum e_LIGHT_TYPE
    {
        ePointLight,                        ///< Fuente puntual que emite luz de 360º.
        eSpotLight,                         ///< Fuente puntual que emite luz cónica (como una linterna).
        eDirectionalLight                   ///< Fuente de luz situada en el infinito (no importa su posición).
    };

    ///////////////////////////////////////////////////////////////////////////////
    /// struct   LIGHT Estructura que define las propiedades de la luz.
    ///
    /// rief   
    /// author  Antonio Lucas Moreno version 1.0 date 28/09/2005 9:26:20
    ///////////////////////////////////////////////////////////////////////////////
    struct Light
    {
        unsigned int    id;                 ///< Identificador de la luz.
        e_LIGHT_TYPE    type;               ///< Tipo de luz.
        Vector3         position;           ///< Posición (sólo para Point y Spot).
        Vector3         direction;          ///< Dirección.

        // Polinomio que describe como se atenúa la iluminación con la distancia
        //  atenuación= attenuation2*x^2 + attenuation0*x + attenuation0
        float           attenuation0;
        float           attenuation1;
        float           attenuation2;

        float           theta;              ///< Ángulo en grados del cono de iluminación.
        float           phi;                ///< Ángulo en grados del cono de penumbra.
        float           fallOff;            ///< Cómo varía de la zona de ilumación a menumbra (0 a x).
        float           range;              ///< Distancia máxima de alcance de la luz (para Point y Spot).
        fColorRGBA      ambient;            ///< Color ambiente(RGBA)
        fColorRGBA      diffuse;            ///< Color difuso(RGBA)
        fColorRGBA      specular;           ///< Color especular(RGBA)
    };

    ///////////////////////////////////////////////////////////////////////////////
    /// struct   MATERIAL Estructura que define las propiedades del material.
    ///
    /// rief   
    /// author  Antonio Lucas Moreno version 1.0 date 28/09/2005 9:26:27
    ///////////////////////////////////////////////////////////////////////////////
    struct Material
    {
        char            name[256];              ///< Nombre del material.
        fColorRGBA      ambient;                ///< Color ambiente(RGBA).
        fColorRGBA      diffuse;                ///< Color difuso(RGBAA).
        fColorRGBA      specular;               ///< Color especular(RGBA).
        fColorRGBA      emissive;               ///< Color emisivo(RGBA).
    };

En el método OnCreateWindow() crearemos una fuente de luz (ver funciones SetDirectionalLight(), SetPointLight() y SetSpotLight()) direccional. Esto es equivalente a una luz situada en el infinito (por ejemplo el Sol) cuyos rayos de luz inciden con la misma inclinación.


    ///////////////////////////////////////////////////////////////////////////////
    ///     OnCreateWindow: Función invocada al iniciarse el programa y DESPUÉS de crear la ventana.
    ///
    ///     @param  nada
    ///
    ///     @return  nada
    ///////////////////////////////////////////////////////////////////////////////
    void GraphicApplication::OnCreateWindow( WindowProps windowProps )
    {
        if ( m_pVideoDriver )
        {
            m_pVideoDriver->Init( windowProps );
            m_pVideoDriver->SetDepthBufferSize( MIN_DEPTH_BUFFER, MAX_DEPTH_BUFFER );

    // ********************************* NEW **************************************
            // Luz direccional.
            memset( &m_Light, 0, sizeof(Light) );
            m_Light.id          = ID_LIGHT;
            m_Light.type        = eDirectionalLight;
            m_Light.direction   = Vector3( -1.0f, -0.5f, -0.2f);

            m_Light.ambient.r   = 0.2f;
            m_Light.ambient.g   = 0.2f;
            m_Light.ambient.b   = 0.2f;
            m_Light.ambient.a   = 1.0f;

            m_Light.diffuse.r   = 1.0f;
            m_Light.diffuse.g   = 1.0f;
            m_Light.diffuse.b   = 1.0f;
            m_Light.diffuse.a   = 1.0f;

            m_Light.specular.r  = 0.0f;
            m_Light.specular.g  = 0.0f;
            m_Light.specular.b  = 0.0f;
            m_Light.specular.a  = 1.0f;

            m_pVideoDriver->SetLight    ( m_Light );
            m_pVideoDriver->EnableLight ( m_Light.id, true );

    // ****************************************************************************
        }
    }

Cada fuente de luz creada se identifica con un valor, ID_LIGHT en este caso, la cual habrá que activar así como es uso de iluminación y el uso de materiales.

Posteriormente en la función OnRender(), antes de renderizar nuestro cubo, definiremos el color del material usado así como sus propiedades en cuánto a cómo refleja la luz dicho material.


    ///////////////////////////////////////////////////////////////////////////////
    ///     OnRender: Esta función es invocada cuando el sistema está listo para renderizar.
    ///
    ///     @param  nada
    ///
    ///     @return  nada
    ///////////////////////////////////////////////////////////////////////////////
    void GraphicApplication::OnRender()
    {
        fColorRGBA clearColor   = { 0.0f, 0.0f, 0.8f, 1.0f };   // Color de fondo.

    // ********************************* NEW **************************************
        fColorRGBA yellowColor  = { 1.0f, 1.0f, 0.0f, 0.0f };   // Amarillo
        Material yellowMaterial;

        memset( &yellowMaterial, 0, sizeof(Material) );
        yellowMaterial.ambient  = yellowColor;
        yellowMaterial.diffuse  = yellowColor;
        yellowMaterial.specular = yellowColor;
    // ****************************************************************************

        if ( m_pVideoDriver )
        {
            // Limpiamos la pantalla.
            m_pVideoDriver->ClearColor( clearColor );
            m_pVideoDriver->ClearZBuffer();

            // Proyección en perspectiva
            m_pVideoDriver->SetPerspective( FOV, m_WindowProps.width, m_WindowProps.height );

            m_pVideoDriver->LookAt( Vector3(2.0f,1.0f,3.0f) ,   // Posición de la cámara.
                                    Vector3(0.0f,0.0f,0.0f) ,   // A dónde mira.
                                    Vector3(0.0f,1.0f,0.0f) );  // Dónde se encuentra el "techo", eje Y. 

            m_pVideoDriver->BeginRender();

            if ( m_bWireframe )
            {
                m_pVideoDriver->SetRenderMode ( eWireFrame );   // Renderizado wireframe
                m_pVideoDriver->SetCullFaces  ( eCullNone  );   // Desactivamos la selección de caras a renderizar.
    // ********************************* NEW **************************************
                m_pVideoDriver->EnableLighting( false      );   // Desactivamos la iluminación.
    // ****************************************************************************
            }
            else
            {
                m_pVideoDriver->SetRenderMode ( eSolid     );   // Renderizado sólido.
                m_pVideoDriver->SetCullFaces  ( eCullBack  );   // No se renderizarán las caras traseras.
    // ********************************* NEW **************************************
                m_pVideoDriver->EnableLighting( true       );   // Activamos la iluminación.
    // ****************************************************************************
            }

    // ********************************* NEW **************************************
            m_pVideoDriver->SetMaterial  ( yellowMaterial );           // Fijamos el material
    // ****************************************************************************

            RenderObjects();

            m_pVideoDriver->EndRender();
        }
    }

El método RenderObjects() varía ahora ligeramente, se ha añadido a la estructura Vertex las coordenadas que definen una normal.


    ///////////////////////////////////////////////////////////////////////////////
    /// struct  Vertex Estructura del vértice.
    ///
    /// rief   
    /// author  Antonio Lucas Moreno version 1.02 date 30/08/2005 9:24:19
    ///////////////////////////////////////////////////////////////////////////////
    struct Vertex
    {
        float           x , y , z ;         ///< Coordenadas del vértice.
        ulColorRGBA     color;              ///< Color del vértice.
    // ********************************* NEW **************************************
        float           nx, ny, nz;         ///< Normal del vértice.
    // ****************************************************************************
        float           tu, sv;             ///< Coordenadas de textura.
    };
	
	
    ///////////////////////////////////////////////////////////////////////////////
    ///     RenderObjects: Dibuja las geometrías.
    ///
    ///     @param  nada
    ///
    ///     @return  nada
    ///////////////////////////////////////////////////////////////////////////////
    void GraphicApplication::RenderObjects()
    {
        Vertex vertexArray[4];

        if ( m_pVideoDriver )
        {
    // ********************************* NEW **************************************

            // Para todas las caras
            for (int f=0; f<6; f++)
            {
                // Renderizamos los vértices de la cara
                for (int i=0; i<4; i++)
                {
                    vertexArray[i].nx= m_Cube.faces[f].normal[0];
                    vertexArray[i].ny= m_Cube.faces[f].normal[1];
                    vertexArray[i].nz= m_Cube.faces[f].normal[2];

                    vertexArray[i].x= m_Cube.vertex[ m_Cube.faces[f].index[i] ][0];
                    vertexArray[i].y= m_Cube.vertex[ m_Cube.faces[f].index[i] ][1];
                    vertexArray[i].z= m_Cube.vertex[ m_Cube.faces[f].index[i] ][2];

                    vertexArray[i].color.rgba= 0xffffff;
                }

                if ( m_bWireframe )
                    m_pVideoDriver->RenderVertexArray( eTriangleStrip, (BYTE*)vertexArray,
                                                       sizeof(Vertex), 0, 4, eFVF_XYZ|eFVF_DIFFUSE );
                else
                    m_pVideoDriver->RenderVertexArray( eTriangleStrip, (BYTE*)vertexArray, 
                                                       sizeof(Vertex), 0, 4, eFVF_XYZ|eFVF_DIFFUSE|eFVF_NORMAL|eFVF_TEX1 );
            }

    // ****************************************************************************
        }
    }

Podéis descargaros el ejemplo: tutorial-10.zip



Nota: Compartir en Facebook
Enviado el Miércoles, 05 septiembre a las 20:20:58 por administrador
 
Enlaces Relacionados
· Más Acerca de DirectX/Opengl
· Noticias de administrador


Noticia más leída sobre DirectX/Opengl:
Tutorial 16 - Movimiento-3D - (Tercera Persona)

 
Votos del Artículo
Puntuación Promedio: 0
votos: 0
Por favor tómate un segundo y vota por este artículo:
Excelente
Muy Bueno
Bueno
Regular
Malo

 
Opciones

 Versión Imprimible  Versión Imprimible

 
"Tutorial 10 - Luces, normales, materiales" | Entrar / Crear Cuenta | 0 Comentarios
Los comentarios son propiedad de quien los envió. No somos responsables por su contenido.

No se permiten comentarios Anónimos, Regístrese por favor

Sitio potenciado por NukeProjects.Net        NukeStilo 1.0 se basa en PHP-Nuke        Theme Diseñado por NukeMods

© Antonio Lucas Moreno