0

Revised, actual Base And Derived Class I am working with plus the function that instantiates it and uses the non virtual function call

ShaderClass.h

    #ifndef SHADERCLASS_H
    #define SHADERCLASS_H

    #include <D3D11.h>
    #include <D3DX10math.h>
    #include <D3DX11async.h>
    #include <fstream>
    using namespace std;

    class ShaderClass {
    protected:
        struct MatrixBufferType {
            D3DXMATRIX world;
            D3DXMATRIX view;
            D3DXMATRIX projection;
        };

        ID3D11Device*           m_pDevice;
        ID3D11DeviceContext*    m_pDeviceContext;
        HWND m_hWnd;

        ID3D11VertexShader* m_pVertexShader;
        ID3D11PixelShader*  m_pPixelShader;
        ID3D11InputLayout*  m_pLayout;
        ID3D11Buffer*       m_pMatrixBuffer;
        ID3D11SamplerState* m_pSampleState;

        WCHAR*    m_vsFilename;
        WCHAR*    m_psFilename;

    public:
        ShaderClass();
        //ShaderClass( const ShaderClass& other );
        virtual ~ShaderClass();

        bool initialize( ID3D11Device* pDevice, ID3D11DeviceContext* pDeviceContext, HWND hWnd, WCHAR* vsFilename, WCHAR* psFilename );
        void shutdown();
        bool render( int index, D3DXMATRIX view, D3DXMATRIX world, D3DXMATRIX projection, void* pData );

    protected:
        virtual bool initializeShader() = 0;
        virtual void shutdownShader() = 0;
        virtual bool setShaderParameters( D3DXMATRIX world, D3DXMATRIX view, D3DXMATRIX projection, void* pData ) = 0;
        virtual void renderShader( int index ) = 0;

        void outputShaderErrorMessage( ID3D10Blob* pErrorMessage, WCHAR* shaderFilename );

    }; // ShaderClass

    #endif // SHADERCLASS_H

ShaderClass.cpp

    #include "ShaderClass.h"

    // ------------------------------------------------------------------------------------------
    ShaderClass::ShaderClass() :
      m_pVertexShader( nullptr ),
      m_pPixelShader( nullptr ),
      m_pLayout( nullptr ),
      m_pMatrixBuffer( nullptr ),
      m_pSampleState( nullptr ) {
    } // ShaderClass

    // ----------------------------------------------------------------------------
    // ShaderClass::ShaderClass( const ShaderClass& other ) {
    //} // ShaderClass

    // ----------------------------------------------------------------------------
    ShaderClass::~ShaderClass() {
    } // ~ShaderClass

    // ----------------------------------------------------------------------------
    bool ShaderClass::initialize( ID3D11Device* pDevice, ID3D11DeviceContext* pDeviceContext, HWND hWnd, WCHAR* vsFilename, WCHAR* psFilename ) {
        bool bResult;

        if ( !pDevice ) {
            return false;
        }
        m_pDevice = pDevice;

        if ( !pDeviceContext ) {
            return false;
        }
        m_pDeviceContext = pDeviceContext;

        m_hWnd = hWnd;

        m_vsFilename = vsFilename;
        m_psFilename = psFilename;

        // Initialize The Vertex And Pixel Shaders
        bResult = initializeShader();
        if ( !bResult ) {
            return false;
        }
        return true;
    } // initialize

    // ----------------------------------------------------------------------------
    void ShaderClass::shutdown() {
        // Shutdown Individual Shader Contents
        shutdownShader();
    } // shutdown

    // -----------------------------------------------------------------------------
    bool ShaderClass::render( int indexCount, D3DXMATRIX world, D3DXMATRIX view, D3DXMATRIX projection, void* pData  ) {
        bool bResult;

        bResult = setShaderParameters( world, view, projection, pData );
        if ( !bResult ) {
            return false;
        }

        renderShader( indexCount );

        return true;
    } // render

    // ----------------------------------------------------------------------------
    void ShaderClass::outputShaderErrorMessage( ID3D10Blob* pErrorMessage, WCHAR*   shaderFilename ) {
        char* compileErrors;
        unsigned long bufferSize, i;
        ofstream fout;

        // Get A Pointer To The Error Message Text Buffer
        compileErrors = (char*)(pErrorMessage->GetBufferPointer());

        // Get The Length Of The Message
        bufferSize = pErrorMessage->GetBufferSize();

        // Open A File To Write The Error Message
        fout.open( "shader-error.txt" );

        // Write Out The Error Message
        for ( i = 0; i < bufferSize; i++ ) {
            fout << compileErrors[i];
        }

        // Close The File
        fout.close();

        // Release The Error Message
        pErrorMessage->Release();
        pErrorMessage = nullptr;

        // Pop A Message To Notify The User
        MessageBox( m_hWnd, L"Error compiling shader. Check shader-error.txt for message", shaderFilename, MB_OK );

        return;
    } // outputShaderErrorMessage

LightMapShaderClass.h

    #ifndef LIGHTMAPSHADERCLASS_H
    #define LIGHTMAPSHADERCLASS_H

    #include "ShaderClass.h"

    class LightMapShaderClass : public ShaderClass {    
    public:
        LightMapShaderClass();
        //LightMapShaderClass( const LightMapShaderClass& other );
        ~LightMapShaderClass();

    protected:
        bool    initializeShader();
        void    shutdownShader();
        bool    setShaderParameters( D3DXMATRIX world, D3DXMATRIX view, D3DXMATRIX projection, ID3D11ShaderResourceView** pTextures );
        void    renderShader( int index );

    }; // LightMapShaderCLASS

    #endif // LIGHTMAPSHADERCLASS_H

LightMapShaderClass.cpp

    #include "LightMapShaderClass.h"

    // ----------------------------------------------------------------------------
    LightMapShaderClass::LightMapShaderClass() : ShaderClass() {    
    } // LightMapShaderClass

    // ----------------------------------------------------------------------------
    //LightMapShaderClass::LightMapShaderClass( const LightMapShaderClass& other ) : ShaderClass( other ) {
    //} // LightMapShaderClass

    // ----------------------------------------------------------------------------
    LightMapShaderClass::~LightMapShaderClass() {
    } // ~LightMapShaderClass

    // ----------------------------------------------------------------------------
    bool LightMapShaderClass::initializeShader() {
        HRESULT hr;
        ID3D10Blob* pErrorMessage;
        ID3D10Blob* pVertexShaderBuffer;
        ID3D10Blob* pPixelShaderBuffer;
        D3D11_INPUT_ELEMENT_DESC polygonLayout[2];
        unsigned int uiNumElements;
        D3D11_BUFFER_DESC matrixBufferDesc;
        D3D11_SAMPLER_DESC samplerDesc;

        // Initialize The Pointers
        pErrorMessage = nullptr;
        pVertexShaderBuffer = nullptr;
        pPixelShaderBuffer = nullptr;

        // Compile The Vertex Shader Code
        hr = D3DX11CompileFromFile( m_vsFilename, NULL, NULL, "LightMapVertexShader", "vs_4_1", D3D10_SHADER_ENABLE_STRICTNESS, 0, NULL, &pVertexShaderBuffer, &pErrorMessage, NULL );
        if ( FAILED( hr ) ) {
            // If The Shader Failed To Compile It Should Have Written Something To The Error Message
            if ( pErrorMessage ) {
                outputShaderErrorMessage( pErrorMessage, m_vsFilename );
            }
            // If There Was Nothing In The Error Message It Could Not Find The Shader File
            else {
                MessageBox( m_hWnd, m_vsFilename, L"Missing Shader File", MB_OK );
            }
            return false;
        }

        // Compile The Pixel Shader Code
        hr = D3DX11CompileFromFile( m_psFilename, NULL, NULL, "LightMapPixelShader", "ps_4_1", D3D10_SHADER_ENABLE_STRICTNESS, 0, NULL, &pPixelShaderBuffer, &pErrorMessage, NULL );
        if ( FAILED( hr ) ) {
            // If The Shader Failed To Compile It Should Have Written Something To The Error Message
            if ( pErrorMessage ) {
                outputShaderErrorMessage( pErrorMessage, m_psFilename );
            }
            // If There Was Nothing In The Error Message It Could Not Find The Shader File
            else {
                MessageBox( m_hWnd, m_psFilename, L"Missing Shader File", MB_OK );
            }
            return false;
        }

        // Create The Vertex Shader From The Buffer
        hr = m_pDevice->CreateVertexShader( pVertexShaderBuffer->GetBufferPointer(), pVertexShaderBuffer->GetBufferSize(), NULL, &m_pVertexShader );
        if ( FAILED( hr ) ) {
            return false;
        }

        // Create The Pixel Shader From The Buffer
        hr = m_pDevice->CreatePixelShader( pPixelShaderBuffer->GetBufferPointer(), pPixelShaderBuffer->GetBufferSize(), NULL, &m_pPixelShader );
        if ( FAILED( hr ) ) {
            return false;
        }

        // Create The Vertex Input Layout Description
        // This Setup Needs To Match The VertexType Structure In The ModelClass And In The Shader Buffer
        polygonLayout[0].SemanticName = "POSITION";
        polygonLayout[0].SemanticIndex = 0;
        polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
        polygonLayout[0].InputSlot = 0;
        polygonLayout[0].AlignedByteOffset = 0;
        polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
        polygonLayout[0].InstanceDataStepRate = 0;

        polygonLayout[1].SemanticName = "TEXCOORD";
        polygonLayout[1].SemanticIndex = 0;
        polygonLayout[1].Format = DXGI_FORMAT_R32G32B32_FLOAT;
        polygonLayout[1].InputSlot = 0;
        polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
        polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
        polygonLayout[1].InstanceDataStepRate = 0;

        // Get A Count Of The Elements In The Layout
        uiNumElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]);

        // Create The Vertex Input Layout
        hr = m_pDevice->CreateInputLayout( polygonLayout, uiNumElements, pVertexShaderBuffer->GetBufferPointer(), pVertexShaderBuffer->GetBufferSize(), &m_pLayout );
        if ( FAILED( hr ) ) {
            return false;
        }

        // Release The Vertex Shader Buffer And Pixel Shader Buffer Since They Are No Longer Needed
        pVertexShaderBuffer->Release();
        pVertexShaderBuffer = nullptr;

        pPixelShaderBuffer->Release();
        pPixelShaderBuffer = nullptr;

        // Setup The Description Of The Matrix Dynamic Constant Buffer That Is In The Vertex Shader
        matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
        matrixBufferDesc.ByteWidth = sizeof(MatrixBufferType);
        matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
        matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
        matrixBufferDesc.MiscFlags = 0;
        matrixBufferDesc.StructureByteStride = 0;

        // Create The Matrix Constant Buffer Pointer So We Can Access The Vertex Shader Constant Buffer From Within This Class
        hr = m_pDevice->CreateBuffer( &matrixBufferDesc, NULL, &m_pMatrixBuffer );
        if ( FAILED( hr ) ) {
            return false;
        }

        // Create A Texture Sampler State Description
        samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
        samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
        samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
        samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
        samplerDesc.MipLODBias = 0.0f;
        samplerDesc.MaxAnisotropy = 1;
        samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
        samplerDesc.BorderColor[0] = 0;
        samplerDesc.BorderColor[1] = 0;
        samplerDesc.BorderColor[2] = 0;
        samplerDesc.BorderColor[3] = 0;
        samplerDesc.MinLOD = 0;
        samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;

        // Create The Texture Sampler State
        hr = m_pDevice->CreateSamplerState( &samplerDesc, &m_pSampleState );
        if ( FAILED( hr ) ) {
            return false;
        }

        return true;
    } // initializeShader

    // ----------------------------------------------------------------------------
    void LightMapShaderClass::shutdownShader() {
        // Release The Sampler State
        if ( m_pSampleState ) {
            m_pSampleState->Release();
            m_pSampleState = nullptr;
        }

        // Release The Matrix Constant Buffer
        if ( m_pMatrixBuffer ) {
            m_pMatrixBuffer->Release();
            m_pMatrixBuffer = nullptr;
        }

        // Release The Layout
        if ( m_pLayout ) {
            m_pLayout->Release();
            m_pLayout = nullptr;
        }

        // Release The Pixel Shader
        if ( m_pPixelShader ) {
            m_pPixelShader->Release();
            m_pPixelShader = nullptr;
        }

        // Release The Vertex Shader
        if ( m_pVertexShader ) {
            m_pVertexShader->Release();
            m_pVertexShader = nullptr;
        }

        return;
    } // shutdownShader

    // ----------------------------------------------------------------------------
    bool LightMapShaderClass::setShaderParameters( D3DXMATRIX world, D3DXMATRIX view, D3DXMATRIX projection, ID3D11ShaderResourceView** pTextures ) {
        HRESULT hr;
        D3D11_MAPPED_SUBRESOURCE mappedResource;
        MatrixBufferType* pData;
        unsigned int uiBufferNumber;

        // Transpose The Matrices To Prepare Them For The Shader
        D3DXMatrixTranspose( &world, &world );
        D3DXMatrixTranspose( &view, &view );
        D3DXMatrixTranspose( &projection, &projection );

        // Lock The Matrix Constant Buffer So It Can Be Written To
        hr = m_pDeviceContext->Map( m_pMatrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource );
        if ( FAILED( hr ) )  {
            return false;
        }

        // Get A Pointer To The Data In The Constant Buffer
        pData = (MatrixBufferType*)mappedResource.pData;

        // Copy The Matrices Into The Constant Buffer
        pData->world = world;
        pData->view  = view;
        pData->projection = projection;

        // Unlock The Matrix Constant Buffer
        m_pDeviceContext->Unmap( m_pMatrixBuffer, 0 );

        // Set The Position Of The Matrix Constant Buffer In The Vertex Shader
        uiBufferNumber = 0;

        // Now Set The Matrix Constant Buffer In The Vertex Shader With The Updated Values
        m_pDeviceContext->VSSetConstantBuffers( uiBufferNumber, 1, &m_pMatrixBuffer );

        // Set Shader Texture Array Resource In The Pixel Shader
        m_pDeviceContext->PSSetShaderResources( 0, 2, pTextures );

        return true;
    } // setShaderParameters

    // ----------------------------------------------------------------------------
    void LightMapShaderClass::renderShader( int indexCount ) {
        // Set The Vertex Input Layout
        m_pDeviceContext->IASetInputLayout( m_pLayout );

        // Set The Vertex And Pixel Shaders That Will Be Used To Render This Triangle
        m_pDeviceContext->VSSetShader( m_pVertexShader, NULL, 0 );
        m_pDeviceContext->PSSetShader( m_pPixelShader, NULL, 0 );

        // Set The Sampler State In The Pixel Shader
        m_pDeviceContext->PSSetSamplers( 0, 1, &m_pSampleState );

        // Render The Triangles
        m_pDeviceContext->DrawIndexed( indexCount, 0, 0 );

        return;
    } // renderShader

The Function that uses the base class

    // ----------------------------------------------------------------------------
    bool GraphicsClass::initialize( int iScreenWidth, int iScreenHeight, HWND hWnd ) {
        bool bResult;
        D3DXMATRIX baseViewMatrix;

        // Create The Direct3D Object
        m_pD3D = new D3DClass;
        if ( !m_pD3D ) {
            return false;
        }
        // Initialize The Direct3D Object
        bResult = m_pD3D->initialize( iScreenWidth, iScreenHeight, VSYNC_ENABLED, hWnd, FULL_SCREEN, SCREEN_DEPTH, SCREEN_NEAR );
        if ( !bResult ) {
            MessageBox( hWnd, L"Could not initialize Direct3D", L"Error", MB_OK );
            return false;
        }

        // Create The Camera Object
        m_pCamera = new Camera;
        if ( !m_pCamera ) {
            return false;
        }
        // Initialize The Base View Matrix With The Camera For 2D User Interface Rendering
        m_pCamera->setPosition( 0.0f, 0.0f, -1.0f );
        m_pCamera->render();
        m_pCamera->getViewMatrix( baseViewMatrix );

        // Create The Model Object
        m_pModel = new ModelClass;
        if ( !m_pModel ) {
            return false;
        }
        // Initialize The Model Object
        bResult = m_pModel->initialize( m_pD3D->getDevice(), "../DX11Engine/data/square.txt", L"../DX11Engine/data/stone01.dds", L"../DX11Engine/data/light01.dds" );
        if ( !bResult ) {
            MessageBox( hWnd, L"Could not initialize the model object.", L"Error", MB_OK );
            return false;
        }

        // Create The LightMapTextureShader Object
        m_pShader = new LightMapShaderClass;
        if ( !_pShader ) {
            return false;
        }
        // Initialize The LightMapTextureShader Object
        bResult = _pShader->initialize( _pD3D->getDevice(), _pD3D->getDeviceContext(), hWnd, L"../DX11Engine/lightmap.vs", L"../DX11Engine/lightmap.ps" );
        if ( !bResult ) {
            MessageBox( hWnd, L"Could not initialize the light map shader object.", L"Error", MB_OK );
            return false;
        }
        return true;
    } // initialize
Francis Cugler
  • 7,788
  • 2
  • 28
  • 59
  • The problem here is that there are many ways the above code doesn't compile. Because you gave us pseudo-code instead of code, I cannot tell if it is a transcription error, or the source of your actual problem. When running into compiler errors you do not understand, it is best to submit code that you think should actually compile, but is minimal and demonstrates your problem. Ie, if you don't think the body of a method matters, have an empty body (if it returns `bool`, just return `true`). If you don't care what a parameter is, make it an `int`. Etc. – Yakk - Adam Nevraumont Nov 14 '12 at 05:38
  • -1 irrelevant pseudo-code. show real code. – Cheers and hth. - Alf Nov 14 '12 at 05:39
  • ... and this is important because you have an error you don't understand. That means you don't understand what is important in the code, and what is not. If you knew what was important to causing your error, you wouldn't need to ask here: so don't presume you can safely abstract the essence of the problem. Reproduce it in simpler code, don't give pseudo-code. – Yakk - Adam Nevraumont Nov 14 '12 at 05:40
  • Ok first of all, I went back & added the actual code, second of all the question I was asking was fairly simple, I do understand the compiler errors, I just wasn't 100% sure if the based and derived pure virtuals have to exactly match. I do understand fairly well what is and isn't important, but as you can see from the code above, that is why I was simulating the SAME EXACT scenerio that is equivalent to this code here. The code I know compiles builds and run, I was just adding in a base class for the Shader to seperate all the common work out of each shader type. – Francis Cugler Nov 14 '12 at 08:29

2 Answers2

1

Your doSomethingNotPureVirtual() has different signature in Base class and Derived class

in Base class

bool doSomethingNotPureVirtual( param1, param2, param3, param4, void* pData ); 

in Derived class

bool settingFunctionPureVirtual( param1, param2, param3, DataType** pMyTypes );

I see you are using C++11 as you use nullptr. try to add override in Drived class, compiler will tell you something

bool settingFunctionPureVirtual( param1, param2, param3, DataType** pMyTypes ) override;
billz
  • 44,644
  • 9
  • 83
  • 100
  • not c++11 only 2010, I have windows vista. I tried doing that before you suggested that but the output window just says... 1>c:\users\skilz80\documents\visual studio 2010\projects\dx11engine\dx11engine\lightmapshaderclass.h(35): error C3668: 'LightMapShaderClass::setShaderParameters' : method with override specifier 'override' did not override any base class methods – Francis Cugler Nov 14 '12 at 05:56
  • ok, anyway you have to provide exactly the same function signature from Base in Derived class. – billz Nov 14 '12 at 05:58
  • 1
    @FrancisCugler that is exactly the kind of compiler error you should be getting. – juanchopanza Nov 14 '12 at 07:33
0

In your psuedo code, your derived class has declared new versions of settingFunctionPureVirtual and doingSomethingPureVirtual rather than providing class specific implementations of the virtual functions that match the declarations in the base class.

The declarations in the your derived class are both missing virtual and they are private instead of protected.

Josh Heitzman
  • 1,816
  • 1
  • 14
  • 26
  • Hmm, the idea I am having is these methods are protected in the base class and are purely virtual for every derived class type must implement these methods, but in the derived classes themselves ought to be private, however protected should be just as fine. The only problem here is that the base class setting function for the last parameter will vary from each derived classes version of it. – Francis Cugler Nov 14 '12 at 05:53
  • I do need for every derived class to have to include this function, however the derived class versions may each be different, and from what I have read about the override keyword is that it will change the behavoir of the function or method as long as the signiture is the same. – Francis Cugler Nov 14 '12 at 05:54
  • The override keyword will not change the behavior of a function or method, but it will change the behavior of the compiler. Specifically using the override keyword tells the compiler the function signature is expected to match a virtual function declared in a base class. This is to help prevent errors where typos result in a new virtual method being declared in a derived class when the intent is to override a virtual method that should already be declared in a base class. – Josh Heitzman Nov 14 '12 at 06:06
  • Ahh ok that makes it a little more clear, I do fairly well with Inheritance and virtual methods, I just never used the override before, I did revise the code and posted my actual code. So, im guessing im just gonna have to make the set function specific for each derived class, however is there a way to say to the base class that this function must exist even though each derived classes version could be different ? – Francis Cugler Nov 14 '12 at 08:23
  • oh about the private i changed it to protected, that wasn't that big of a deal. – Francis Cugler Nov 14 '12 at 08:24
  • Oh but the problem I am having is the way the frame work is set up, the setShaderParameters method is called from within the base class's render call. So if I try to remove the declaration out of the base class altogether, then I have no way of using the set function inside of the render function because the base class doesn't know about it and even if I use a class prototype in the base's header file and use the derived class with scope resolution it will not work because it doesn't belong to a specific problem. I might be able to do it that way though if I made the function static... – Francis Cugler Nov 14 '12 at 08:37
  • I'm not sure what you are asking. It could be that this new question is suitable to be posted as question of its own. That said, each derived class can provides its own implementation of a virtual function, but the still signature needs to match the one declared in the base class. – Josh Heitzman Nov 14 '12 at 08:38
  • hmm... [Base] Shader ... does all common set up work for all shaders.. [Derived] LightMap, MultiTexture, ShadowMap etc... Some of these include more then one file, so a basic shader would have a pointer to a texture, where the later would have a textureArray or a pointer to a pointer of textures... this is were im getting into problems with the inheritance – Francis Cugler Nov 14 '12 at 08:42
  • Some shaders may even need the use of more parameters such as D3DXVECTOR3 &/or 4 or even other D3DXMATRIX values for other calculations. – Francis Cugler Nov 14 '12 at 08:47
  • So if this is the case then instead of using a pure virtual function and still keeping it in the base class, should i just write overloaded functions, then if I did I would have to also do the same for my render function as well. – Francis Cugler Nov 14 '12 at 08:50
  • If you don't need to make the calls the different shaders classes via functions that have the same signature (including type), then virtual functions are unnecessary to the solution. – Josh Heitzman Nov 14 '12 at 08:53