www.xbdev.net
xbdev - software development
Sunday March 26, 2023
home | about | contact | Donations

     
 

ShaderX..

Making our graphics card work for us..

 

Basic Effect Files with Directx

by bkenwright@xbdev.net

 

Vertex and Pixel shaders, and higher level languages such as Cg and HLSL can be combined into a single editable fx file, usually called Effect Files.  The Effect Files can be opened in notepad and are basic text.  We can set constants, variables, functions, define various techniques for different effects, even define which version of pixel or vertex shader it should be compiled to.

 

Effect files are a form of C language, slightly different though, but if you know C/C++ then it shouldn't be to hard to follow the codes workings.

 

 

basic.fx

int    BCLR = 0xff009900;          // background - AARRGGBB

 

// transformations

float4x4 World      : WORLD;

float4x4 View       : VIEW;

float4x4 Projection : PROJECTION;

 

//--------------------------------------------------------------

 

struct VS_IN

{

    float3 Pos    : POSITION;

    float4 Colour : COLOR0;

};

 

struct VS_OUTPUT

{

    float4 Pos    : POSITION;

    float4 Colour : COLOR0;

};

 

VS_OUTPUT VS( VS_IN vs_in )

{

    VS_OUTPUT Out = (VS_OUTPUT)0;

 

    float4x4 WorldView = mul(World, View);

 

    float3 P = mul(float4(vs_in.Pos, 1), (float4x3)WorldView);  // position (view space)

 

    Out.Pos  = mul(float4(P, 1), Projection);             // position (projected)

    Out.Colour = vs_in.Colour;                                // diffuse colour 

    return Out;

}

 

//---------------------------------------------------------------

 

float4 PS( VS_OUTPUT ps_in ) : COLOR

{

    //return tex2D(Sampler, Tex) * Diff + Spec;

    return ps_in.Colour;

}

 

//---------------------------------------------------------------

 

technique BasicShader

{

    pass P0

    {

         // shaders

        VertexShader = compile vs_1_1 VS();

        PixelShader  = compile ps_1_1 PS();

 

    }

}

 

 

main.cpp

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

/*

   main.cpp

   www.xbdev.net

   Simple Effect (fx) Demo with DirectX

*/

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

 

//-----------------------------------------------------------------------------

 

#define STRICT

#define WIN32_LEAN_AND_MEAN

 

#include <windows.h>

#include <assert.h>

#include <d3d9.h>

#include <d3dx9.h>

 

#pragma comment(lib, "d3dx9.lib")

#pragma comment(lib, "d3d9.lib")

 

 

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

/*

   GLOBALS

   As much as we all hate them, its sometimes a little easier...so we've got

   a few globals for the essential of our code.

/*

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

 

HWND                    g_hWnd          = NULL;

LPDIRECT3D9             g_pD3D          = NULL;

LPDIRECT3DDEVICE9       g_pd3dDevice    = NULL;

LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer = NULL;

 

 

struct Vertex

{

    float x, y, z;

    DWORD color;

 

      enum FVF

      {

            FVF_Flags = D3DFVF_XYZ | D3DFVF_DIFFUSE

      };

};

 

Vertex g_quadVertices[] =

{

   //  x     y     z       color

   { -1.0f,-1.0f, 0.0f, 0xffffff00, }, // Bottom-Left,  color = yellow

   {  1.0f,-1.0f, 0.0f, 0xff00ff00, }, // Bottom-Right, color = green

   {  1.0f, 1.0f, 0.0f, 0xffff0000, }, // Top-Right,    color = red

   { -1.0f, 1.0f, 0.0f, 0x000000ff, }  // Top-Left,     color = blue

};

 

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

// PROTOTYPES                                                              //

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

void init(void);         // - called at the start of our program

void render(void);       // - our mainloop..called over and over again

void shutDown(void);     // - last function we call before we end!

 

 

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

/*                                                                         */

/* Handle all messages for the main window here                            */

/*                                                                         */

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

long _stdcall MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

    if(uMsg == WM_DESTROY)

    {

            // We destroy any directx memory we allocated etc,

            // Tidy up before leaving.

                shutDown();

 

            //UnregisterClass( "DirectX3D", winClass.hInstance );

            PostQuitMessage(0);

                  return 0;

    }

 

    return (long)DefWindowProc(hWnd, uMsg, wParam, lParam);

}

 

 

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

/*                                                                         */

/* Program entry point.                                                    */

/*                                                                         */

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

int _stdcall WinMain(HINSTANCE i, HINSTANCE, char* k, int)

{

    MSG msg;

    char szname[] = "DirectX3D";

    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,

                      GetModuleHandle(NULL), NULL, NULL, NULL, NULL,

                      szname, NULL };

    RegisterClassEx( &wc );

    g_hWnd = CreateWindowEx(WS_EX_APPWINDOW,

                              szname, "Basic Bones Sample",

                              WS_OVERLAPPEDWINDOW,//for fullscreen make into WS_POPUP

                              50, 50, 500,500,    //for full screen GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),

                              GetDesktopWindow(), NULL, wc.hInstance, NULL);

   

    // Initilise or directX code here!

      init();

 

    ShowWindow(g_hWnd, SW_SHOW);

    UpdateWindow(g_hWnd);    

 

    // Message loop. Note that this has been modified to allow

    // us to execute if no messages are being processed.

    while(1)

    {

        if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))

        {

            if (!GetMessage(&msg, NULL, 0, 0))

                break;

 

            DispatchMessage(&msg);

        }

            else

                  // Idle-time processing - do our work here!

                  render();

    }

    return 0;

}// End WinMain(..)

 

 

 

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

/*                                                                         */

/* init()                                                                  */

/* Called once at the start of our program to setup directx.               */

/*                                                                         */

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

void init( void )

{

    g_pD3D = Direct3DCreate9( D3D_SDK_VERSION );

 

    D3DDISPLAYMODE d3ddm;

 

    g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm );

 

    D3DPRESENT_PARAMETERS d3dpp;

    ZeroMemory( &d3dpp, sizeof(d3dpp) );

 

    d3dpp.Windowed               = TRUE;

    d3dpp.SwapEffect             = D3DSWAPEFFECT_DISCARD;

    d3dpp.BackBufferFormat       = d3ddm.Format;

    d3dpp.EnableAutoDepthStencil = TRUE;

    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

    d3dpp.PresentationInterval   = D3DPRESENT_INTERVAL_IMMEDIATE;

 

#if(0) // HAL or REF

     

    g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd,

                          D3DCREATE_SOFTWARE_VERTEXPROCESSING,

                          &d3dpp, &g_pd3dDevice );

     

#else

     

      g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, g_hWnd,

                          D3DCREATE_SOFTWARE_VERTEXPROCESSING,

                          &d3dpp, &g_pd3dDevice );

#endif

 

      g_pd3dDevice->CreateVertexBuffer( 4*sizeof(Vertex), D3DUSAGE_WRITEONLY,

                                          Vertex::FVF_Flags, D3DPOOL_DEFAULT,

                                      &g_pVertexBuffer, NULL );

    void *pVertices = NULL;

 

    g_pVertexBuffer->Lock( 0, sizeof(g_quadVertices), (void**)&pVertices, 0 );

    memcpy( pVertices, g_quadVertices, sizeof(g_quadVertices) );

    g_pVertexBuffer->Unlock();

 

      g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );

      g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

 

 

      // Lets enable alpha blending so we can have transparency

      g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );

      g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );

      g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );

 

 

}//End init(..)

 

 

 

 

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

/*                                                                         */

/* shutDown()                                                              */

/* Release any allocated memory, andy directx api's, resources etc before  */

/* our program finally terminates.                                         */

/*                                                                         */

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

void shutDown( void )

{

      g_pVertexBuffer->Release();

    g_pVertexBuffer = NULL;

 

    g_pd3dDevice->Release();

    g_pd3dDevice = NULL;

 

    g_pD3D->Release();

    g_pD3D = NULL;

}// End shutDown(..)

 

 

 

void render()

{

      ID3DXEffect * pEffect;

      LPD3DXBUFFER pBufferErrors;

      DWORD dwShaderFlags = 0;

      DWORD iPass = 0;

      UINT cPasses = 0;

 

      if(FAILED(

            D3DXCreateEffectFromFile( g_pd3dDevice, "basic.fx",

                                  NULL, // CONST D3DXMACRO* pDefines

                                            NULL, // LPD3DXINCLUDE pInclude

                                            dwShaderFlags, NULL, &pEffect, &pBufferErrors)

               ))

      {

            LPVOID pCompileErrors = pBufferErrors->GetBufferPointer();

            MessageBox(NULL, (const char*)pCompileErrors, "Compile Error",

            MB_OK|MB_ICONEXCLAMATION);

            PostQuitMessage(WM_DESTROY);

      }

 

      //LPVOID pCompilErrors = pBufferErrors->GetBufferPointer();

 

      LPDIRECT3DVERTEXDECLARATION9 pVertexDeclaration = NULL;

 

      const D3DVERTEXELEMENT9 declaration[] =

      {

            { 0, 0 * sizeof(float),D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION, 0 },

            { 0, 3 * sizeof(float),D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },

            D3DDECL_END()

      };

     

      g_pd3dDevice->CreateVertexDeclaration( declaration, &pVertexDeclaration );

     

      pEffect->SetTechnique("BasicShader");

      //g_pEffect->SetTechnique("TVertexShaderOnly");

      //g_pEffect->SetTechnique("TNoShader");

      //g_pEffect->SetTechnique("TVertexAndPixelShader");

 

      // Setting Shader Constants

      {

            /*

            float4x4 World      : WORLD;

            float4x4 View       : VIEW;

            float4x4 Projection : PROJECTION;

            */

           

            D3DXMATRIX matTrans;

            D3DXMATRIX matRot;

        D3DXMATRIX matProj,matView,matWorld;

 

            D3DXMatrixTranslation( &matTrans, 0.0f, 0.0f, 4.0f );

            D3DXMatrixRotationYawPitchRoll( &matRot, 0.0f, 0.0f, 0.0f );

           

            D3DXMatrixPerspectiveFovLH( &matProj, D3DXToRadian( 45.0f ),

                                640.0f / 480.0f, 0.1f, 100.0f );

         

            g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );

 

            matWorld = matRot * matTrans;

 

            D3DXMatrixIdentity( &matView ); // This sample is not really making use of a view matrix

 

            D3DXMATRIX worldViewProj = matWorld * matView * matProj;

            D3DXMatrixTranspose( &worldViewProj, &worldViewProj );

 

            // g_pEffect->SetValue( "noiseAnim", D3DXVECTOR3(0.2,1,0), sizeof(D3DXVECTOR3) );

            // or SetFloat(..), SetMatrix(..), SetTexture(..)

            pEffect->SetMatrix("World", &matWorld);

            pEffect->SetMatrix("View",  &matView);

            pEffect->SetMatrix("Projection", &matProj);

            //g_pEffect->SetMatrix("Projection", &worldViewProj);

 

      }

 

     

      DWORD dwColour  = D3DCOLOR_COLORVALUE(0.0f,0.5f,0.0f,1.0f);

      HRESULT hrError = pEffect->GetValue( "BCLR", &dwColour, sizeof(DWORD) );

      // if( hrError = 0x0 ) // If "BCLR" isn't set in our fx file, set it to light green

 

      g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,

                         dwColour, 1.0f, 0 );

 

    g_pd3dDevice->BeginScene();

 

      g_pd3dDevice->SetVertexDeclaration( pVertexDeclaration );

     

 

      g_pd3dDevice->SetStreamSource( 0, g_pVertexBuffer, 0, sizeof(Vertex) );

 

      // Starting Rendering of our effect

      {

            pEffect->Begin(&cPasses, 0);

            for(iPass=0; iPass<cPasses; iPass++)

            {

                  pEffect->BeginPass(iPass);

                  //g_Mesh->MeshData.pMesh->DrawSubset(0);

                 

                  g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );

                  pEffect->EndPass();

            }

            pEffect->End();

      }

 

     

 

    g_pd3dDevice->EndScene();

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

 

      pVertexDeclaration->Release();

      pEffect->Release();

 

}//End Render()

 

 

 

 
 Visitor:
Copyright (c) 2002-2023 xbdev.net - All rights reserved.
Designated articles, tutorials and software are the property of their respective owners.