⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wmlrenderer.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
📖 第 1 页 / 共 2 页
字号:

    Node* pkNode = WmlDynamicCast(Node,pkScene);
    if ( pkNode )
    {
        for (int i = 0; i < pkNode->GetQuantity(); i++)
        {
            Spatial* pkChild = pkNode->GetChild(i);
            if ( pkChild )
                ReleaseTextures(pkChild);
        }
    }
}
//----------------------------------------------------------------------------
void Renderer::ReleaseShaders (Spatial* pkScene)
{
    Node* pkNode = WmlDynamicCast(Node,pkScene);

    if ( pkNode )
    {
       Geometry* pkGeom = WmlDynamicCast(Geometry, pkScene);
       if ( pkGeom )
        {
            if ( pkGeom->GetVertexShader() )
            {
                ReleaseShader( pkGeom->GetVertexShader() );
            }

            if ( pkGeom->GetPixelShader() )
            {
                ReleaseShader( pkGeom->GetPixelShader() );
            }
        }

        for (int i = 0; i < pkNode->GetQuantity(); i++)
        {
            Spatial* pkChild = pkNode->GetChild(i);
            if ( pkChild )
            {
                ReleaseShaders( pkChild );
            }
        }
    }
}
//----------------------------------------------------------------------------
void Renderer::SetStateConst (float* afData, const Geometry& rkGeom,
    StateConstantType iType, int iTypeNum)
{
    // This handles state that is not specific to the specific renderer.
    // *Renderer should call this function in their own SetStateConst function
    // to handle the rest.

    // If the user asks for some light which does not exist, then
    // it will throw an assert in debug mode and quietly fail with reasonable
    // data (black for colors, the origin for positions, and 
    // UNIT_X for directions, etc...) which shouldn't break any shaders.

    RenderState* pkState;
    Light* pkLight;

    switch( iType )
    {
        // things not handled here, but in the specific renderer
        case RENDERER_MODVIEW:
        case RENDERER_PROJ:
        case RENDERER_MODVIEWPROJ:
        case RENDERER_MOD:

        // Camera State
        case CAMERA_POSITION:
            memcpy(afData, &m_spkCamera->GetLocation(), 3*sizeof(float));
            afData[3] = 1.0f;
            break;
        case CAMERA_UP:
            memcpy(afData, &m_spkCamera->GetUp(), 3*sizeof(float));
            afData[3] = 0.0f;
            break;
        case CAMERA_LEFT:
            memcpy(afData, &m_spkCamera->GetLeft(), 3*sizeof(float));
            afData[3] = 0.0f;
            break;

        // Fog State
        case FOG_COLOR:
            pkState = rkGeom.GetRenderStateArray()[RenderState::RS_FOG];
            memcpy(afData,((FogState*)pkState)->Color(),3*sizeof(float));
            afData[3] = 1.0f;
            break;
        case FOG_PARAMS:
            pkState = rkGeom.GetRenderStateArray()[RenderState::RS_FOG];
            afData[0] = ((FogState*)pkState)->Start();
            afData[1] = ((FogState*)pkState)->End();
            afData[2] = ((FogState*)pkState)->Density();
            afData[3] = (float)((FogState*)pkState)->Enabled();
            break;

        // Material State
        case MATERIAL_EMISSIVE:
            pkState = rkGeom.GetRenderStateArray()[RenderState::RS_MATERIAL];
            memcpy(afData,((MaterialState*)pkState)->Emissive(),3*
                sizeof(float) );
            break;
        case MATERIAL_AMBIENT:
            pkState = rkGeom.GetRenderStateArray()[RenderState::RS_MATERIAL];
            memcpy(afData,((MaterialState*)pkState)->Ambient(),3*
                sizeof(float) );
            break;
        case MATERIAL_DIFFUSE:
            pkState = rkGeom.GetRenderStateArray()[RenderState::RS_MATERIAL];
            memcpy(afData,((MaterialState*)pkState)->Diffuse(),3*
                sizeof(float) );
            break;
        case MATERIAL_SPECULAR:
            pkState = rkGeom.GetRenderStateArray()[RenderState::RS_MATERIAL];
            memcpy(afData,((MaterialState*)pkState)->Specular(),3*
                sizeof(float) );
            break;
        case MATERIAL_SHININESS:
            pkState = rkGeom.GetRenderStateArray()[RenderState::RS_MATERIAL];
            afData[0] = ((MaterialState*)pkState)->Shininess();
            break;

        // Lights
        // Because it's hard (right now) to do conditional statements in
        // shader code, lights that are off will be supported by setting their
        // color to (0,0,0,1), so that they do not emit any light.  If the
        // shader code uses light colors unconventionally, this may
        // cause problems.  Otherwise, you can use the same shader code with
        // arbitrary lights that turn on and off.
        case LIGHT_POSITION:
            pkState = rkGeom.GetRenderStateArray()[RenderState::RS_LIGHT];
            pkLight = ((LightState*)pkState)->Get(iTypeNum);
            if ( !pkLight )
            {
                assert( !"No light to send position from" );
                // For release mode, quietly fail with reasonable data
                memcpy(afData,Vector3f::ZERO,3*sizeof(float));
                afData[3] = 1.0f;
            }
            else if ( pkLight->GetType() == Light::LT_POINT )
            {
                memcpy(afData,((PointLight*)pkLight)->Location(),3*
                    sizeof(float));
                afData[3] = 1.0f;
            }
            else if ( pkLight->GetType() == Light::LT_SPOT )
            {
                memcpy(afData,((SpotLight*)pkLight)->Location(),3*
                    sizeof(float));
                afData[3] = 1.0f;
            }
            else
            {
                assert( !"Light type does not have a position." );
                // For release mode, quietly fail with reasonable data
                memcpy(afData,Vector3f::ZERO,3*sizeof(float));
                afData[3] = 1.0f;
            }
            break;
        case LIGHT_DIRECTION:
            pkState = rkGeom.GetRenderStateArray()[RenderState::RS_LIGHT];
            pkLight = ((LightState*)pkState)->Get(iTypeNum);
            if ( !pkLight )
            {
                assert( !"No light to send direction from" );
                // For release mode, quietly fail with reasonable data
                memcpy(&afData[1],Vector3f::ZERO,3*sizeof(float));
                afData[0] = 1.0f;         
            }
            else if ( pkLight->GetType() == Light::LT_SPOT )
            {
                memcpy(afData,((SpotLight*)pkLight)->Direction(),3*
                    sizeof(float));
                afData[3] = 0.0f;
            }
            else if ( pkLight->GetType() == Light::LT_DIRECTIONAL )
            {
                 memcpy(afData,((DirectionalLight*)pkLight)->Direction(),3*
                    sizeof(float));
                 afData[3] = 0.0f;
            }
            else
            {
                assert( !"Light type does not have a direction." );
                // For release mode, quietly fail with reasonable data
                memcpy(&afData[1],Vector3f::ZERO,3*sizeof(float));
                afData[0] = 1.0f;  
            }
            break;
        case LIGHT_AMBIENT:
            pkState = rkGeom.GetRenderStateArray()[RenderState::RS_LIGHT];
            pkLight = ((LightState*)pkState)->Get(iTypeNum);
            if ( !pkLight )
            {
                assert( !"Light doesn't exist to send ambient from." );
                // In release mode, quietly fail with no color
                memcpy(afData,&ColorRGB::BLACK,3*sizeof(float) );
                afData[3] = 1.0f;
            }
            else if ( pkLight->On() )
            {
                memcpy(afData,pkLight->Ambient(),3*sizeof(float) );
                afData[3] = 1.0f;
            }
            else
            {
                memcpy(afData,&ColorRGB::BLACK,3*sizeof(float) );
                afData[3] = 1.0f;
            }
            break;
        case LIGHT_DIFFUSE:
            pkState = rkGeom.GetRenderStateArray()[RenderState::RS_LIGHT];
            pkLight = ((LightState*)pkState)->Get(iTypeNum);
            if ( !pkLight )
            {
                assert( !"Light doesn't exist to send diffuse from." );
                // In release mode, quietly fail with no color
                memcpy(afData,&ColorRGB::BLACK,3*sizeof(float) );
                afData[3] = 1.0f;
            }
            else if ( pkLight->On() )
            {
                memcpy(afData,pkLight->Diffuse(),3*sizeof(float) );
                afData[3] = 1.0f;
            }
            else
            {
                memcpy(afData,&ColorRGB::BLACK,3*sizeof(float) );
                afData[3] = 1.0f;
            }
            break;
        case LIGHT_SPECULAR:
            pkState = rkGeom.GetRenderStateArray()[RenderState::RS_LIGHT];
            pkLight = ((LightState*)pkState)->Get(iTypeNum);
            if ( !pkLight )
            {
                assert( !"Light doesn't exist to send specular from." );
                // In release mode, quietly fail with no color
                memcpy(afData,&ColorRGB::BLACK,3*sizeof(float) );
                afData[3] = 1.0f;
            }
            else if ( pkLight->On() )
            {
                memcpy(afData,pkLight->Specular(),3*sizeof(float) );
                afData[3] = 1.0f;
            }
            else
            {
                memcpy(afData,&ColorRGB::BLACK,3*sizeof(float) );
                afData[3] = 1.0f;
            }
            break;
        case LIGHT_SPOTCUTOFF:
            pkState = rkGeom.GetRenderStateArray()[RenderState::RS_LIGHT];
            pkLight = ((LightState*)pkState)->Get(iTypeNum);
            if ( !pkLight )
            {
                assert( !"Light doesn't exist to send cut-off from." );
                // Release mode reasonable data
                afData[0] = 0.0f;
                afData[1] = 1.0f;
                afData[2] = 0.0f;
                afData[3] = 1.0f;
            }
            if ( pkLight->GetType() == Light::LT_SPOT )
            {
                afData[0] = ((SpotLight*)pkLight)->GetAngle();
                afData[1] = Mathf::Cos( afData[0] );
                afData[2] = Mathf::Sin( afData[1] );
                afData[3] = ((SpotLight*)pkLight)->Exponent();
            }
            else
            {
                assert( !"Not a spotlight!" );
                // Release mode reasonable data
                afData[0] = 0.0f;
                afData[1] = 1.0f;
                afData[2] = 0.0f;
                afData[3] = 1.0f;
            }
            break;
        case LIGHT_ATTENPARAMS:
            pkState = rkGeom.GetRenderStateArray()[RenderState::RS_LIGHT];
            pkLight = ((LightState*)pkState)->Get(iTypeNum);
            if ( !pkLight )
            {
                afData[0] = 0.0f;
                afData[1] = 0.0f;
                afData[2] = 0.0f;
                afData[3] = 0.0f;
            }
            else
            {
                afData[0] = pkLight->Constant();
                afData[1] = pkLight->Linear();
                afData[2] = pkLight->Quadratic();
                afData[3] = pkLight->Intensity();
            }
            break;

        case USER_DEFINED:
        default:
            // do nothing
            break;
    };
}
//----------------------------------------------------------------------------
void Renderer::SetShaderState (const Geometry* pkGeom)
{
    if ( !pkGeom )
    {
        SetCurrentVertexShader(NULL);
        SetCurrentPixelShader(NULL);
        return;
    }
    
    SetCurrentVertexShader(pkGeom->GetVertexShader());
    SetCurrentPixelShader(pkGeom->GetPixelShader());
}
//----------------------------------------------------------------------------
void Renderer::SetShaderConstants (const Geometry* pkGeom)
{
    if ( !pkGeom )
        return;

    if ( m_pkCurVertexShader != pkGeom->GetVertexShader() )
    {
        // Your graphics card does not support vertex shaders.
        return;
    }

    if ( m_pkCurPixelShader != pkGeom->GetPixelShader() )
    {
        // Your graphics card does not support pixel shaders.
        return;
    }

    if ( m_pkCurVertexShader )
        SetVertexShaderConst(pkGeom->GetVertexShaderConstants(),*pkGeom);

    if ( m_pkCurPixelShader )
        SetPixelShaderConst(pkGeom->GetPixelShaderConstants(),*pkGeom);
}
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
// streaming
//----------------------------------------------------------------------------
Object* Renderer::Factory (Stream&)
{
    // Renderer is abstract, Factory never called.  Renderers cannot be
    // streamed anyway...
    return NULL;
}
//----------------------------------------------------------------------------
void Renderer::Load (Stream&, Stream::Link*)
{
    // Renderers cannot be streamed.
    assert( false );
}
//----------------------------------------------------------------------------
void Renderer::Link (Stream&, Stream::Link*)
{
    // Renderers cannot be streamed.
    assert( false );
}
//----------------------------------------------------------------------------
bool Renderer::Register (Stream&)
{
    // Renderers cannot be streamed.
    assert( false );
    return false;
}
//----------------------------------------------------------------------------
void Renderer::Save (Stream&)
{
    // Renderers cannot be streamed.
    assert( false );
}
//----------------------------------------------------------------------------
StringTree* Renderer::SaveStrings ()
{
    StringTree* pkTree = new StringTree(4,0,2,0);

    // strings
    pkTree->SetString(0,MakeString(&ms_kRTTI,GetName()));
    pkTree->SetString(1,MakeString("width =",m_iWidth));
    pkTree->SetString(2,MakeString("height =",m_iHeight));
    pkTree->SetString(3,MakeString("background color =",
        m_kBackgroundColor));

    // children
    pkTree->SetChild(0,Object::SaveStrings());
    pkTree->SetChild(1,m_spkCamera->SaveStrings());

    return pkTree;
}
//----------------------------------------------------------------------------
int Renderer::GetMemoryUsed () const
{
    int iBaseSize = sizeof(Renderer) - sizeof(Object);
    int iTotalSize = iBaseSize + Object::GetMemoryUsed();
    return iTotalSize;
}
//----------------------------------------------------------------------------
int Renderer::GetDiskUsed () const
{
    // Renderers cannot be streamed.
    assert( false );
    return 0;
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -