www.xbdev.net xbdev - software development
Monday December 10, 2018
home | about | contact | Donations


PrtX. Lighting...
by bkenwright@xbdev.net

Using a few lines of code it is possible to create the illusion of lighting...(download source code).

 

What we have this time is a rotating square with a texture applied to it... as the square rotates you can see the texture become darker and lighter and the square moves away from the light etc.

Two main parts of this code are:

[1] - Setting the material texture.... this can be called once at the beginning of your directX code...and never bothered with again...or for each material to get different effects with it.  As if you dont' set it, your shading will just be a dark cement colour... because the default settings are set that way.

[2]... well if you want light, you have to have a light...lol...

And coding begins... it may look like a lot of code... but there's nothing new... only the SetMaterial()and SetLight() functions... I've kept all the new stuff in the new functions!  So again, its not very efficient... and would probably be set up once... instead being called all the time from the loop.  But you can easily see the way in setting up a light easily.

/***************************************************************************/

/*                                                                         */

/* File: game.cpp                                                          */

/*                                                                         */

/***************************************************************************/

#include <d3dx8.h>

#include <d3d8.h>

 

 

void SetCamera()

{

      //camera

      D3DXMATRIX view_matrix, matProj;

      D3DXMatrixLookAtLH(&view_matrix,&D3DXVECTOR3( 0.0f, 0.0f,-5.0f),

                                   &D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),

                                   &D3DXVECTOR3( 0.0f, 1.0f, 0.0f ));

      g_pD3DDevice->SetTransform(D3DTS_VIEW,&view_matrix);

      D3DXMatrixPerspectiveFovLH(&matProj, //Result Matrix

                              D3DX_PI/4,//Field of View, in radians. (PI/4) is typical

                              1,     //Aspect ratio

                              1.0,     //Near view plane

                              500.0f); // Far view plane

      g_pD3DDevice->SetTransform( D3DTS_PROJECTION, &matProj );

      //end camera

}

 

/***************************************************************************/

/*                                                                         */

/* lighting code                                                           */

/*                                                                         */

/***************************************************************************/

 

void setmaterial()

{

      D3DMATERIAL8 matMaterial;

     

      D3DCOLORVALUE rgbaDiffuse  = {1.0, 1.0, 1.0, 0.0};  //RGBA

      D3DCOLORVALUE rgbaAmbient  = {1.0, 1.0, 1.0, 0.0};

      D3DCOLORVALUE rgbaSpecular = {0.0, 0.0, 0.0, 0.0};

      // emissive is for a glow effect

      D3DCOLORVALUE rgbaEmissive = {0.0, 0.0, 0.0, 0.0};

 

      matMaterial.Diffuse = rgbaDiffuse;

      matMaterial.Ambient = rgbaAmbient;

      matMaterial.Specular = rgbaSpecular;

      matMaterial.Emissive = rgbaEmissive;

      matMaterial.Power = 100.0f;

 

      g_pD3DDevice->SetMaterial(&matMaterial);

}

 

void setlight()

{

    //Set a light up?

      D3DLIGHT8 d3dLight;

 

      //Initialize the light structure.

      ZeroMemory(&d3dLight, sizeof(D3DLIGHT8));

 

      //Set up a white point light at (0, 0, -10).

      d3dLight.Type = D3DLIGHT_POINT;

 

      // Actual colour of the light. (e.g. white).

      d3dLight.Diffuse.r = 1.0f;

      d3dLight.Diffuse.g = 1.0f;

      d3dLight.Diffuse.b = 1.0f;

     

      // Colour when no light hits the object.

      d3dLight.Ambient.r = 0.0f;

      d3dLight.Ambient.g = 0.0f;

      d3dLight.Ambient.b = 0.0f;

     

      // Shiny effect.

      d3dLight.Specular.r = 0.0f;

      d3dLight.Specular.g     = 0.0f;

      d3dLight.Specular.b     = 0.0f;

 

      d3dLight.Position.x     = 0.0f;

      d3dLight.Position.y     = 0.0f;

      d3dLight.Position.z     = -5.0f;

 

      d3dLight.Attenuation0 = 1.0f;

      d3dLight.Attenuation1 = 0.0f;

      d3dLight.Attenuation2 = 0.0f;

      d3dLight.Range = 100.0f;

 

 

      g_pD3DDevice->SetLight(0, &d3dLight);

      g_pD3DDevice->LightEnable(0,TRUE);

      //Turn on lighting

      g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);

 

      g_pD3DDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(5,100,32));

}

 

void DrawTexturedSquare()

{

      // Well beleive it or not we have to have a normal for our shape to use

      // shading!  As the normal is the direction the face (e.g. triangle) is

      // facing.  If the normal is facing away from us its colour is ambient!..

      // when its facing into the light, depending on its angle we generate its

      // brightness!

      struct CUSTOMVERTEX

      {

            FLOAT x, y, z;

            FLOAT nx,ny,nz;

            FLOAT tu, tv;

      };

 

      UINT  D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1);

 

      LPDIRECT3DVERTEXBUFFER8 pVertexBuffer = NULL; // vertex buffer.

      LPDIRECT3DTEXTURE8            pTexture      = NULL; // texture buffer.

 

      CUSTOMVERTEX cvVertices[] =

      {

            //x  y  z       nx   ny    nz       tu    tv

            {-1, -1, 1,    0.0f,0.0f,-1.0f,    0.0f, 1.0f,},            //

            {-1,  1, 1,    0.0f,0.0f,-1.0f,    0.0f, 0.0f,},            //

            { 1,  1, 1,    0.0f,0.0f,-1.0f,    1.0f, 0.0f,},            //

           

            { 1, -1, 1,    0.0f,0.0f,-1.0f,    1.0f, 1.0f,},            //

            {-1, -1, 1,    0.0f,0.0f,-1.0f,    0.0f, 1.0f,},            //

            { 1,  1, 1,    0.0f,0.0f,-1.0f,    1.0f, 0.0f,}

      };

           

      g_pD3DDevice->CreateVertexBuffer(sizeof(cvVertices)*sizeof(CUSTOMVERTEX), D3DUSAGE_WRITEONLY,

                                                                        D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT, &pVertexBuffer);

      VOID* pVertices;

      pVertexBuffer->Lock(0, 0, (BYTE**)&pVertices,  0);

      memcpy(pVertices, cvVertices, sizeof(cvVertices));

      pVertexBuffer->Unlock();

 

      D3DXCreateTextureFromFile(g_pD3DDevice, "image.bmp", &pTexture);

      g_pD3DDevice->SetTexture(0,pTexture);

 

      g_pD3DDevice->SetVertexShader(D3DFVF_CUSTOMVERTEX);

      g_pD3DDevice->SetStreamSource(0, pVertexBuffer, sizeof(CUSTOMVERTEX));

 

     

      g_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);

      g_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);

    // A bit of a note here!!! ****arrgggg**** small shout to get your attention... this

      // baby is what creates the lighting effect..modulating our texture with the diffuse

      // colour... because I didn't specify any diffuse colours ...it is automatically set

      // to Red=255, Green=255 and Blue=255.

      g_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);

 

      g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);

     

      pTexture->Release();

      pVertexBuffer->Release();

}

 

/////////////////////////////////////////////////////////////////////////////////////////

 

 

// Display code

void Render()

{

      if(!g_pD3DDevice)return;

 

      setlight();

      setmaterial();

 

      // Clear the back buffer to a blue color

      g_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,255,0), 1.0f, 0 );

      // Begin the scene.

      g_pD3DDevice->BeginScene();

 

      //g_pD3DDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(255, 255, 32));

 

      SetCamera();

 

      static float angle = 0.0f;

      angle += 0.05f;

      //~~~*~~~~ Create a matrix

      D3DXMATRIX mx;

      //~~~*~~~~ Do somthing to our empty matrix.

      D3DXMatrixRotationY(&mx, angle ); // angle in radians...eg. 1 degree = PI/180

      //~~~*~~~~ Use the matrix! No use having a matrix if we don't use it!

      g_pD3DDevice->SetTransform(D3DTS_WORLD, &mx);

     

      DrawTexturedSquare();

 

      // End the scene.

      g_pD3DDevice->EndScene();

      // After rendering the scene we display it.

      g_pD3DDevice->Present( NULL, NULL, NULL, NULL );

}

 

 

void mainloop()

{

      Render();

}

 

Well if you just glimps at the code, you'll probably wonder why there is so much of it just to set the lighting up!  The only  DirectX API's you should be looking at are:

      g_pD3DDevice->SetLight(0, &d3dLight);

      g_pD3DDevice->LightEnable(0,TRUE);

      //Turn on lighting

      g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);

"and"

      g_pD3DDevice->SetMaterial(&matMaterial);

 

We set up a light... its usually got an integer value, in this case 0.. then we switch it on and enable it in our device.  Next we tell our device how materials will react to light, if we dont' tell it, its got the craziest idea that everything is a cementy colour!  So we fill in a D3DMATERIAL8 structure and pass it to our device... you can do this all the time for the various materials.. eg. some materials might look a greeny colour, other materials will ignore the light etc.

 

 
 Visitor: 9534626  { 209.237.238.175 } Copyright (c) 2002-2017 xbdev.net - All rights reserved.
Designated tutorial and software are the property of their respective owners.