Exemple #1
0
void WorldRenderer::RenderPrep(const corgi::CameraInterface& camera,
                               fplbase::Renderer& renderer, World* world) {
  if (world->config->rendering_config()->create_shadow_map()) {
    CreateShadowMap(camera, renderer, world);
  }
  world->render_mesh_component.RenderPrep(camera);
}
///----------------------------------------------------------------------------
///Overriden Render function (draws the scene).
///----------------------------------------------------------------------------
void GLApp::Render()
{
	static GLfloat angle = 0.0;

	//lock the framerate to 60 FPS
	m_Timer.Tick(60.0f);

	//update the angle for animation
	angle += 50.0f * m_Timer.GetTimeElapsed();

	//1st pass, create shadow map & texture coordinates
	CreateShadowMap(angle);
	CreateTextureMatrix();

	//2nd pass, render from camera point of view
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glViewport(0,0, m_Width, m_Height);

	glMatrixMode(GL_PROJECTION);
	glLoadMatrixd(m_CameraProjectionMatrix);

	glMatrixMode(GL_MODELVIEW);
	glLoadMatrixd(m_CameraViewMatrix);

	glEnable(GL_ALPHA_TEST);
	glAlphaFunc(GL_GREATER, 0.0);

	//bind and enable shadow map texture
	glBindTexture(GL_TEXTURE_2D, m_Geometry.GetShadowTexObj());

	//Tell OpenGL to perform depth comparison
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);

	//Tell OpenGL what to do with the boolean result
	glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);

	//Specify the operators, depth comparison should be true (i.e. lit) if r<texture
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LESS);

	//render lit fragments
	glEnable(GL_LIGHT0);
	m_Geometry.Draw(angle);

	//Do the contrary: depth comparison should be true if r >= texture (i.e. shadow)
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_GEQUAL);

	//render shadowed fragments
	glDisable(GL_LIGHT0);
	m_Geometry.Draw(angle);

	SwapBuffers(m_hDC);
}
Exemple #3
0
	void SkyLight::ResizeShadowMap()
	{
		if(m_pShadowMap)
		{
			m_pShadowMap->Release();
			m_pShadowMap.reset();
		}
		if(CreateShadowMap(m_shadowMapWidth, m_shadowMapHeight, G_FORMAT_R32_FLOAT) == false)
		{
			return;
		}
		return;
	}
void COutdoorLightScatteringSample::Create()
{
#ifdef NOT_READY_YET
	//std::string ConfigPath = "Default_Config.txt";
	ParseConfigurationFile( ConfigPath );

	// Create shadow map before other assets!!!
	HRESULT hResult = CreateShadowMap(mpD3dDevice);
#endif /* NOT_READY_YET */

	m_pLightSctrPP->OnCreateDevice();

#ifdef NOT_READY_YET
	// Create data source
	try
	{
		m_pElevDataSource.reset(new CElevationDataSource(m_strRawDEMDataFile.c_str()));
		m_pElevDataSource->SetOffsets(m_TerrainRenderParams.m_iColOffset, m_TerrainRenderParams.m_iRowOffset);
		m_fMinElevation = m_pElevDataSource->GetGlobalMinElevation() * m_TerrainRenderParams.m_TerrainAttribs.m_fElevationScale;
		m_fMaxElevation = m_pElevDataSource->GetGlobalMaxElevation() * m_TerrainRenderParams.m_TerrainAttribs.m_fElevationScale;
	}
	catch (const std::exception &)
	{
		LOG_ERROR(_T("Failed to create elevation data source"));
		return;
	}

	LPCTSTR strTileTexPaths[CEarthHemsiphere::NUM_TILE_TEXTURES], strNormalMapPaths[CEarthHemsiphere::NUM_TILE_TEXTURES];
	for (int iTile = 0; iTile < _countof(strTileTexPaths); ++iTile)
	{
		strTileTexPaths[iTile] = m_strTileTexPaths[iTile].c_str();
		strNormalMapPaths[iTile] = m_strNormalMapTexPaths[iTile].c_str();
	}

	V(m_EarthHemisphere.OnD3D11CreateDevice(m_pElevDataSource.get(), m_TerrainRenderParams, mpD3dDevice, mpContext, m_strRawDEMDataFile.c_str(), m_strMtrlMaskFile.c_str(), strTileTexPaths, strNormalMapPaths));
#endif
}
Exemple #5
0
BOOL CWndOptVideo::OnChildNotify( UINT message, UINT nID, LRESULT* pLResult ) 
{ 
	CWndButton* pWndButton		= (CWndButton*)*pLResult;
	CWndButton* pWndZoomLimit   = (CWndButton*)GetDlgItem( WIDC_CHECK1 );
#if __VER >= 12 // __UPDATE_OPT
	CWndButton* pWndCamearaLock = (CWndButton*)GetDlgItem( WIDC_CHECK5 );
#endif
	switch( nID )
	{
	case WIDC_OBJECT_LOD_HIGH:
		g_Option.m_nObjectDetail = 0;
		break;
	case WIDC_OBJECT_LOD_MID:
		g_Option.m_nObjectDetail = 1;
		break;
	case WIDC_OBJECT_LOD_LOW:
		g_Option.m_nObjectDetail = 2;
		break;

	case WIDC_OBJECT_DISTANT_HIGH:
		g_Option.m_nObjectDistant = 0;
		break;
	case WIDC_OBJECT_DISTANT_MID:
		g_Option.m_nObjectDistant = 1;
		break;
	case WIDC_OBJECT_DISTANT_LOW:
		g_Option.m_nObjectDistant = 2;
		break;

	case WIDC_TERRAIN_LOD_HIGH:
		g_Option.m_nViewArea = 0;
		SetLODDetail( g_Option.m_nViewArea );
		break;
	case WIDC_TERRAIN_LOD_MID:
		g_Option.m_nViewArea = 1;
		SetLODDetail( g_Option.m_nViewArea );
		break;
	case WIDC_TERRAIN_LOD_LOW:
		g_Option.m_nViewArea = 2;
		SetLODDetail( g_Option.m_nViewArea );
		break;

	case WIDC_SHADOW_HIGH:
		g_Option.m_nShadow = 0;
		CreateShadowMap( m_pApp->m_pd3dDevice, g_Neuz.m_d3dpp.BackBufferFormat );
		break;
	case WIDC_SHADOW_MID:
		g_Option.m_nShadow = 1;
		CreateShadowMap( m_pApp->m_pd3dDevice, g_Neuz.m_d3dpp.BackBufferFormat );
		break;
	case WIDC_SHADOW_LOW:
		g_Option.m_nShadow = 2;
		break;
#ifdef __SFX_OPT
	case WIDC_CHECK4:
		if( g_Neuz.m_bFakeFullMode && ::GetLanguage() != LANG_KOR)
		{
			pWndButton = (CWndButton*)GetDlgItem( WIDC_CHECK4 );
			if(pWndButton)
			{
				g_Option.m_bStartFullScreen = !(pWndButton->GetCheck());
				g_WndMng.OpenMessageBox( prj.GetText(TID_GAME_GAME_RESETTING), MB_OK, this );
			}
		}
		break;
#else
	case WIDC_GLOWON:
		if( g_Neuz.m_d3dCaps.PixelShaderVersion >= D3DPS_VERSION(1,1) )
		{
			g_Option.m_nBloom = 1; 
			g_Glare.Create( D3DDEVICE, D3DFMT_R5G6B5, g_Option.m_nResWidth, g_Option.m_nResHeight - 48 );
		}
		break;
	case WIDC_GLOWOFF:
		g_Option.m_nBloom = 0;
		break;
	case WIDC_VOICEON:
		g_Option.m_bVoice = 1;
		break;
	case WIDC_VOICEOFF:
		g_Option.m_bVoice = 0;
		break;
	case WIDC_CHECK5:
		pWndButton = (CWndButton*)GetDlgItem( WIDC_CHECK5 );
		g_Option.m_bSFXRenderOff = !pWndButton->GetCheck();
		break;
	case WIDC_MOUSE_HIGH:
		g_Option.m_MouseSpeed = 0;
		break;
	case WIDC_MOUSE_MID:
		g_Option.m_MouseSpeed = 1;
		break;
	case WIDC_MOUSE_LOW:
		g_Option.m_MouseSpeed = 2;
		break;
	case WIDC_CHECK4:
		if( g_Neuz.m_bFakeFullMode )
		{
			pWndButton = (CWndButton*)GetDlgItem( WIDC_CHECK4 );
			g_Option.m_bStartFullScreen = !(pWndButton->GetCheck());
			g_WndMng.OpenMessageBox( prj.GetText(TID_GAME_GAME_RESETTING), MB_OK, this );
		}
		break;
#endif
#ifdef __YENV
	case WIDC_SEPCBUMPCHECK:
		// ¼³Á¤°ªÀ» ¹Ù·Î Àû¿ëÇϴ°ÍÀÌ ¾Æ´Ï¶ó Á¾·áÇÒ¶§ Àû¿ëÇÑ´Ù
		// ¿É¼ÇÁß ´Ù½Ã ½ÃÀÛÇØ¾ß Àû¿ëµÇ´Â°ÍµéÀ» À§ÇÑ º¯¼ö..( ¹üÇÁ¸Ê... )
		pWndButton = (CWndButton*)GetDlgItem( WIDC_SEPCBUMPCHECK );
		if( pWndButton->GetCheck() != g_Option.m_bSpecBump )
		{
			g_Option.m_bExitChange = TRUE;
			g_WndMng.OpenMessageBox( prj.GetText(TID_GAME_GAME_RESETTING), MB_OK, this );
		}
		else
			g_Option.m_bExitChange = FALSE;
		break;
#endif //__YENV
	case WIDC_CHECK2:
		pWndButton = (CWndButton*)GetDlgItem( WIDC_CHECK2 );
		g_Option.m_bDamageRender = pWndButton->GetCheck();
		break;

	case WIDC_CHECK6:
		pWndButton = (CWndButton*)GetDlgItem( WIDC_CHECK6 );
		g_Option.m_nPlayerName = pWndButton->GetCheck();
		break;
	case WIDC_CHECK7:
		pWndButton = (CWndButton*)GetDlgItem( WIDC_CHECK7 );
		g_Option.m_nOtherPlayerName = pWndButton->GetCheck();
		break;
	case WIDC_CHECK8:
		pWndButton = (CWndButton*)GetDlgItem( WIDC_CHECK8 );
		g_Option.m_nMonName = pWndButton->GetCheck();
		break;
#if __VER >= 12 // __UPDATE_OPT
	case WIDC_CHECK1:
	{
		if( pWndZoomLimit->GetCheck() )
			g_Option.m_bZoomLimit = FALSE;
		else
			g_Option.m_bZoomLimit = TRUE;			
	}	
	break;
	case WIDC_VIEWMASK:
		pWndButton = (CWndButton*)GetDlgItem( WIDC_VIEWMASK );
		g_Option.m_bViewMask = pWndButton->GetCheck();
		g_DPlay.SendOptionEnableRenderMask( pWndButton->GetCheck() );
		break;
	case WIDC_CHECK5:
		{
			if( pWndCamearaLock->GetCheck() )
				g_Option.m_bCameraLock = TRUE;
			else
				g_Option.m_bCameraLock = FALSE;			
		}
		break;
#else
	case WIDC_VISIBLEKEEPTIME:
		pWndButton = (CWndButton*)GetDlgItem( WIDC_VISIBLEKEEPTIME );
		g_Option.m_bVisibleBuffTimeRender = pWndButton->GetCheck();
		break;
#endif
	case WIDC_CHECK3:
		pWndButton = (CWndButton*)GetDlgItem( WIDC_CHECK3 );
		if(pWndButton) g_Option.m_nWeatherEffect = pWndButton->GetCheck();
		break;
	/*
	case WIDC_EFFECTONOFF:
		{
			CWndButton* pButton = (CWndButton*)GetDlgItem(WIDC_EFFECTONOFF);
			g_Option.m_bEffect = pButton->GetCheck();
			pButton->SetCheck( g_Option.m_bEffect );
		}
		break;
	case WIDC_BMGONOFF:
		{
			CWndButton* pButton = (CWndButton*)GetDlgItem(WIDC_BMGONOFF);
			g_Option.m_bMusic = pButton->GetCheck();
			pButton->SetCheck( g_Option.m_bMusic );

			// À½¾Ç ²ô°í Äѱâ
			SetOn( g_Option.m_bMusic );
		}
		break;
	*/
		
/*		
	case WIDC_SOUND_ON:
		g_Option.m_nSoundEffect = g_SoundMng.m_nSoundVolume = 1;
		break;
	case WIDC_SOUND_OFF:
		g_Option.m_nSoundEffect = g_SoundMng.m_nSoundVolume = 0;
		break;

	case WIDC_MUSIC_ON:
		g_Option.m_fMusicVolume = 1.0f;
		SetVolume( 1.0f );
		break;
	case WIDC_MUSIC_OFF:
		g_Option.m_fMusicVolume = 0.0f;
		SetVolume( 0.0f );
		break;
*/
	case WIDC_OK:
		Destroy();
	}
	return CWndNeuz::OnChildNotify( message, nID, pLResult ); 
} 
void AtmosphereSample::Initialize(IRenderDevice *pDevice, IDeviceContext **ppContexts, Uint32 NumDeferredCtx, ISwapChain *pSwapChain)
{
    const auto& deviceCaps = pDevice->GetDeviceCaps();
    if(!deviceCaps.bComputeShadersSupported)
    {
        throw std::runtime_error("Compute shaders are required to run this sample");
    }

    SampleBase::Initialize(pDevice, ppContexts, NumDeferredCtx, pSwapChain);

    m_bIsDXDevice = deviceCaps.DevType == DeviceType::D3D11 ||  deviceCaps.DevType == DeviceType::D3D12;
    if( pDevice->GetDeviceCaps().DevType == DeviceType::OpenGLES )
    {
        m_uiShadowMapResolution = 512;
        m_PPAttribs.m_iFirstCascade = 2;
        m_PPAttribs.m_uiSingleScatteringMode = SINGLE_SCTR_MODE_LUT;
        m_TerrainRenderParams.m_iNumShadowCascades = 4;
        m_TerrainRenderParams.m_iNumRings = 10;
        m_TerrainRenderParams.m_TexturingMode = RenderingParams::TM_MATERIAL_MASK;
    }

    m_f4CustomRlghBeta = m_PPAttribs.m_f4CustomRlghBeta;
    m_f4CustomMieBeta = m_PPAttribs.m_f4CustomMieBeta;

	m_strRawDEMDataFile = "Terrain\\HeightMap.tif";
    m_strMtrlMaskFile = "Terrain\\Mask.png";
    m_strTileTexPaths[0] = "Terrain\\Tiles\\gravel_DM.dds";
    m_strTileTexPaths[1] = "Terrain\\Tiles\\grass_DM.dds";
    m_strTileTexPaths[2] = "Terrain\\Tiles\\cliff_DM.dds";
    m_strTileTexPaths[3] = "Terrain\\Tiles\\snow_DM.dds";
    m_strTileTexPaths[4] = "Terrain\\Tiles\\grassDark_DM.dds";
    m_strNormalMapTexPaths[0] = "Terrain\\Tiles\\gravel_NM.dds";
    m_strNormalMapTexPaths[1] = "Terrain\\Tiles\\grass_NM.dds";
    m_strNormalMapTexPaths[2] = "Terrain\\Tiles\\cliff_NM.dds";
    m_strNormalMapTexPaths[3] = "Terrain\\Tiles\\Snow_NM.jpg";
    m_strNormalMapTexPaths[4] = "Terrain\\Tiles\\grass_NM.dds";

    // Create data source
    try
    {
		m_pElevDataSource.reset( new ElevationDataSource(m_strRawDEMDataFile.c_str()) );
        m_pElevDataSource->SetOffsets(m_TerrainRenderParams.m_iColOffset, m_TerrainRenderParams.m_iRowOffset);
        m_fMinElevation = m_pElevDataSource->GetGlobalMinElevation() * m_TerrainRenderParams.m_TerrainAttribs.m_fElevationScale;
        m_fMaxElevation = m_pElevDataSource->GetGlobalMaxElevation() * m_TerrainRenderParams.m_TerrainAttribs.m_fElevationScale;
    }
    catch(const std::exception &)
    {
        LOG_ERROR("Failed to create elevation data source");
        return;
    }

	const Char *strTileTexPaths[EarthHemsiphere::NUM_TILE_TEXTURES], *strNormalMapPaths[EarthHemsiphere::NUM_TILE_TEXTURES];
	for(int iTile=0; iTile < _countof(strTileTexPaths); ++iTile )
    {
		strTileTexPaths[iTile] = m_strTileTexPaths[iTile].c_str();
        strNormalMapPaths[iTile] = m_strNormalMapTexPaths[iTile].c_str();
    }
    
    CreateUniformBuffer( pDevice, sizeof( CameraAttribs ), "Camera Attribs CB", &m_pcbCameraAttribs );
    CreateUniformBuffer( pDevice, sizeof( LightAttribs ), "Light Attribs CB", &m_pcbLightAttribs );

    const auto &SCDesc = pSwapChain->GetDesc();
    m_pLightSctrPP.reset( new LightSctrPostProcess(m_pDevice, m_pImmediateContext, SCDesc.ColorBufferFormat, SCDesc.DepthBufferFormat, TEX_FORMAT_R11G11B10_FLOAT) );
    auto *pcMediaScatteringParams = m_pLightSctrPP->GetMediaAttribsCB();

    m_EarthHemisphere.Create(m_pElevDataSource.get(), 
                             m_TerrainRenderParams, 
                             m_pDevice, 
                             m_pImmediateContext, 
                             m_strMtrlMaskFile.c_str(), 
                             strTileTexPaths, 
                             strNormalMapPaths, 
                             m_pcbCameraAttribs,
                             m_pcbLightAttribs,
                             pcMediaScatteringParams );

    CreateShadowMap();

    // Create a tweak bar
    TwBar *bar = TwNewBar("Settings");
    TwDefine(" GLOBAL fontsize=3 ");
    int barSize[2] = {300, 900};
#ifdef ANDROID
    barSize[0] = 800;
    barSize[1] = 1000;
#endif
    TwSetParam(bar, NULL, "size", TW_PARAM_INT32, 2, barSize);

    // Add variables to the tweak bar
#if 0
    float3 axis(-1, 1, 0);
    m_SpongeRotation = RotationFromAxisAngle(axis, FLOAT_PI/4);
    TwAddVarRW(bar, "Rotation", TW_TYPE_QUAT4F, &m_SpongeRotation, "opened=true axisz=-z group=Sponge");
#endif

    TwAddVarRW(bar, "FPS", TW_TYPE_FLOAT, &m_fFPS, "readonly=true");

    TwAddVarRW(bar, "Light direction", TW_TYPE_DIR3F, &m_f3LightDir, "opened=true axisz=-z showval=false");
    TwAddVarRW(bar, "Camera direction", TW_TYPE_DIR3F, &m_f3CameraDir, "opened=true axisz=-z showval=false");
    TwAddVarRW( bar, "Camera altitude", TW_TYPE_FLOAT, &m_f3CameraPos.y, "min=2000 max=100000 step=100 keyincr=PGUP keydecr=PGDOWN" );

    // Shadows
    {
        // Define a new enum type for the tweak bar
        TwEnumVal ShadowMapRes[] = // array used to describe the shadow map resolution
        {
            { 512, "512" },
            { 1024, "1024" },
            { 2048, "2048" },
            { 4096, "4096" }
        };
        TwType modeType = TwDefineEnum( "Shadow Map Resolution", ShadowMapRes, _countof( ShadowMapRes ) );  // create a new TwType associated to the enum defined by the ShadowMapRes array
        TwAddVarCB( bar, "Shadow map resolution", modeType, SetShadowMapResCB, GetShadowMapResCB, this, "group=Shadows" );

        TwAddVarRW( bar, "Show cascades", TW_TYPE_BOOLCPP, &m_bVisualizeCascades, "group=Shadows" );
        TwAddVarRW( bar, "Partitioning factor", TW_TYPE_FLOAT, &m_fCascadePartitioningFactor, "min=0 max=1 step=0.01 group=Shadows" );
        TwAddVarRW( bar, "Find best cascade", TW_TYPE_BOOLCPP, &m_TerrainRenderParams.m_bBestCascadeSearch, "group=Shadows" );
        TwAddVarRW( bar, "Smooth shadows", TW_TYPE_BOOLCPP, &m_TerrainRenderParams.m_bSmoothShadows, "group=Shadows" );
        TwAddVarCB( bar, "Num cascades", TW_TYPE_INT32, SetNumCascadesCB, GetNumCascadesCB, this, "min=1 max=8 group=Shadows" );
    }

    TwAddVarRW( bar, "Enable Light Scattering", TW_TYPE_BOOLCPP, &m_bEnableLightScattering, "" );

    // Light scattering GUI controls
    {
        TwAddVarRW( bar, "Enable light shafts", TW_TYPE_BOOLCPP, &m_PPAttribs.m_bEnableLightShafts, "group=Scattering" );

        // Define a new enum type for the tweak bar
        TwEnumVal LightSctrTech[] = // array used to describe the shadow map resolution
        {
            { LIGHT_SCTR_TECHNIQUE_EPIPOLAR_SAMPLING, "Epipolar" },
            { LIGHT_SCTR_TECHNIQUE_BRUTE_FORCE, "Brute force" }
        };
        TwType LightSctrTechType = TwDefineEnum( "Light scattering tech", LightSctrTech, _countof( LightSctrTech ) );
        TwAddVarRW( bar, "Light scattering tech", LightSctrTechType, &m_PPAttribs.m_uiLightSctrTechnique, "group=Scattering" );

        TwEnumVal Pow2Values[] =
        {
            { 1, "1" },
            { 2, "2" },
            { 4, "4" },
            { 8, "8" },
            { 16, "16" },
            { 32, "32" },
            { 64, "64" },
            { 128, "128" },
            { 256, "256" },
            { 512, "512" },
            { 1024, "1024" },
            { 2048, "2048" }
        };
        TwType BigPow2Enum = TwDefineEnum( "Large powers of two", Pow2Values + 7, 5 );
        TwAddVarRW( bar, "NumSlices", BigPow2Enum, &m_PPAttribs.m_uiNumEpipolarSlices, "group=Scattering label=\'Num slices\'" );
        TwAddVarRW( bar, "MaxSamples", BigPow2Enum, &m_PPAttribs.m_uiMaxSamplesInSlice, "group=Scattering label=\'Max samples\'" );
        TwType SmallPow2Enum = TwDefineEnum( "Small powers of two", Pow2Values+2, 5 );
        TwAddVarRW( bar, "IntialStep", SmallPow2Enum, &m_PPAttribs.m_uiInitialSampleStepInSlice, "group=Scattering label=\'Initial step\'" );
        
        TwAddVarRW( bar, "ShowSampling", TW_TYPE_BOOLCPP, &m_PPAttribs.m_bShowSampling, "group=Scattering label=\'Show Sampling\'" );
        TwAddVarRW( bar, "RefinementThreshold", TW_TYPE_FLOAT, &m_PPAttribs.m_fRefinementThreshold, "group=Scattering label=\'Refinement Threshold\' min=0.01 max=0.5 step=0.01" );
        TwAddVarRW( bar, "1DMinMaxOptimization", TW_TYPE_BOOLCPP, &m_PPAttribs.m_bUse1DMinMaxTree, "group=Scattering label=\'Use 1D min/max trees\'" );
        TwAddVarRW( bar, "OptimizeSampleLocations", TW_TYPE_BOOLCPP, &m_PPAttribs.m_bOptimizeSampleLocations, "group=Scattering label=\'Optimize Sample Locations\'" );
        TwAddVarRW( bar, "CorrectScattering", TW_TYPE_BOOLCPP, &m_PPAttribs.m_bCorrectScatteringAtDepthBreaks, "group=Scattering label=\'Correct Scattering At Depth Breaks\'" );
        TwAddVarRW( bar, "ShowDepthBreaks", TW_TYPE_BOOLCPP, &m_PPAttribs.m_bShowDepthBreaks, "group=Scattering label=\'Show Depth Breaks\'" );
        TwAddVarRW( bar, "LightingOnly", TW_TYPE_BOOLCPP, &m_PPAttribs.m_bShowLightingOnly, "group=Scattering label=\'Lighting Only\'" );
        //TwAddVarRW( bar, "ScatteringScale", TW_TYPE_FLOAT, &m_fScatteringScale, "group=Scattering label=\'Scattering scale\' min=0 max=2 step=0.1" );

        TwAddVarRW( bar, "NumIntegrationSteps", TW_TYPE_UINT32, &m_PPAttribs.m_uiInstrIntegralSteps, "min=5 max=100 step=5 group=Advanced label=\'Num Integrtion Steps\'" );
        TwDefine( "Settings/Advanced group=Scattering" );

        {
            TwType EpipoleSamplingDensityEnum = TwDefineEnum( "Epipole sampling density enum", Pow2Values, 4 );
            TwAddVarRW( bar, "EpipoleSamplingDensity", EpipoleSamplingDensityEnum, &m_PPAttribs.m_uiEpipoleSamplingDensityFactor, "group=Advanced label=\'Epipole sampling density\'" );
        }
        {
            TwEnumVal SinglSctrMode[] =
            {
                { SINGLE_SCTR_MODE_NONE, "None" },
                { SINGLE_SCTR_MODE_INTEGRATION, "Integration" },
                { SINGLE_SCTR_MODE_LUT, "Look-up table" }
            };
            TwType SinglSctrModeEnum = TwDefineEnum( "Single scattering mode enum", SinglSctrMode, _countof(SinglSctrMode) );
            TwAddVarRW( bar, "SingleSctrMode", SinglSctrModeEnum, &m_PPAttribs.m_uiSingleScatteringMode, "group=Advanced label=\'Single scattering\'" );
        }
        {
            TwEnumVal MultSctrMode[] =
            {
                { MULTIPLE_SCTR_MODE_NONE, "None" },
                { MULTIPLE_SCTR_MODE_UNOCCLUDED, "Unoccluded" },
                { MULTIPLE_SCTR_MODE_OCCLUDED, "Occluded" }
            };
            TwType MultSctrModeEnum = TwDefineEnum( "Higher-order scattering mode enum", MultSctrMode, _countof( MultSctrMode ) );
            TwAddVarRW( bar, "MultipleSctrMode", MultSctrModeEnum, &m_PPAttribs.m_uiMultipleScatteringMode, "group=Advanced label=\'Higher-order scattering\'" );
        }
        {
            TwEnumVal CascadeProcessingMode[] =
            {
                { CASCADE_PROCESSING_MODE_SINGLE_PASS, "Single pass" },
                { CASCADE_PROCESSING_MODE_MULTI_PASS, "Multi-pass" },
                { CASCADE_PROCESSING_MODE_MULTI_PASS_INST, "Multi-pass inst" }
            };
            TwType CascadeProcessingModeEnum = TwDefineEnum( "Cascade processing mode enum", CascadeProcessingMode, _countof( CascadeProcessingMode ) );
            TwAddVarRW( bar, "CascadeProcessingMode", CascadeProcessingModeEnum, &m_PPAttribs.m_uiCascadeProcessingMode, "group=Advanced label=\'Cascade processing mode\'" );
        }
        TwAddVarRW( bar, "FirstCascadeToRayMarch", TW_TYPE_INT32, &m_PPAttribs.m_iFirstCascade, "min=0 max=8 step=1 group=Advanced label=\'Start cascade\'" );
        TwAddVarRW( bar, "Is32BitMinMaxShadowMap", TW_TYPE_BOOLCPP, &m_PPAttribs.m_bIs32BitMinMaxMipMap, "group=Advanced label=\'Use 32-bit float min/max SM\'" );
        {
            TwEnumVal RefinementCriterion[] =
            {
                { REFINEMENT_CRITERION_DEPTH_DIFF, "Depth difference" },
                { REFINEMENT_CRITERION_INSCTR_DIFF, "Scattering difference" }
            };
            TwType CascadeProcessingModeEnum = TwDefineEnum( "Refinement criterion enum", RefinementCriterion, _countof( RefinementCriterion ) );
            TwAddVarRW( bar, "RefinementCriterion", CascadeProcessingModeEnum, &m_PPAttribs.m_uiRefinementCriterion, "group=Advanced label=\'Refinement criterion\'" );
        }
        {
            TwEnumVal ExtinctionEvalMode[] =
            {
                { EXTINCTION_EVAL_MODE_PER_PIXEL, "Per pixel" },
                { EXTINCTION_EVAL_MODE_EPIPOLAR, "Epipolar" }
            };
            TwType ExtinctionEvalModeEnum = TwDefineEnum( "Extinction eval mode enum", ExtinctionEvalMode, _countof( ExtinctionEvalMode ) );
            TwAddVarRW( bar, "ExtinctionEval", ExtinctionEvalModeEnum, &m_PPAttribs.m_uiExtinctionEvalMode, "group=Advanced label=\'Extinction eval mode\'" );
        }
        TwAddVarRW( bar, "AerosolDensity", TW_TYPE_FLOAT, &m_PPAttribs.m_fAerosolDensityScale, "group=Advanced label=\'Aerosol density\' min=0.1 max=5.0 step=0.1" );
        TwAddVarRW( bar, "AerosolAbsorption", TW_TYPE_FLOAT, &m_PPAttribs.m_fAerosolAbsorbtionScale, "group=Advanced label=\'Aerosol absorption\' min=0.0 max=5.0 step=0.1" );
        TwAddVarRW( bar, "UseCustomSctrCoeffs", TW_TYPE_BOOLCPP, &m_PPAttribs.m_bUseCustomSctrCoeffs, "group=Advanced label=\'Use custom scattering coeffs\'" );

        #define RLGH_COLOR_SCALE 5e-5f
        #define MIE_COLOR_SCALE 5e-5f
        TwAddVarCB(bar, "RayleighColor", TW_TYPE_COLOR4F, 
            []( const void *value, void * clientData )
            {
                AtmosphereSample *pTheSample = reinterpret_cast<AtmosphereSample*>( clientData );
                pTheSample->m_f4CustomRlghBeta = *reinterpret_cast<const float4 *>(value) * RLGH_COLOR_SCALE;
                if( (float3&)pTheSample->m_f4CustomRlghBeta == float3( 0, 0, 0 ) )
                {
                    pTheSample->m_f4CustomRlghBeta = float4( 1, 1, 1, 1 ) * RLGH_COLOR_SCALE / 255.f;
                }
            },
            [](void *value, void * clientData)
            {
                AtmosphereSample *pTheSample = reinterpret_cast<AtmosphereSample*>( clientData );
                float4 RlghColor = pTheSample->m_f4CustomRlghBeta / RLGH_COLOR_SCALE;
                RlghColor.w = 1;
                *reinterpret_cast<float4*>(value) = RlghColor;
            },
            this, "group=Advanced label=\'Rayleigh color\' colormode=rgb");

        TwAddVarCB(bar, "MieColor", TW_TYPE_COLOR4F, 
            []( const void *value, void * clientData )
            {
                AtmosphereSample *pTheSample = reinterpret_cast<AtmosphereSample*>( clientData );
                pTheSample->m_f4CustomMieBeta = *reinterpret_cast<const float4 *>(value) * MIE_COLOR_SCALE;
                if( (float3&)pTheSample->m_f4CustomMieBeta == float3( 0, 0, 0 ) )
                {
                    pTheSample->m_f4CustomMieBeta = float4( 1, 1, 1, 1 ) * MIE_COLOR_SCALE / 255.f;
                }
            },
            [](void *value, void * clientData)
            {
                AtmosphereSample *pTheSample = reinterpret_cast<AtmosphereSample*>( clientData );
                float4 MieColor = pTheSample->m_f4CustomMieBeta / MIE_COLOR_SCALE;
                MieColor.w = 1;
                *reinterpret_cast<float4*>(value) = MieColor;
            },
            this, "group=Advanced label=\'Mie color\' colormode=rgb");
        #undef RLGH_COLOR_SCALE
        #undef MIE_COLOR_SCALE
        TwAddButton(bar, "UpdateCoeffsBtn", 
                    [](void *clientData)
                    {
                        AtmosphereSample *pTheSample = reinterpret_cast<AtmosphereSample*>( clientData );
                        pTheSample->m_PPAttribs.m_f4CustomRlghBeta = pTheSample->m_f4CustomRlghBeta;
                        pTheSample->m_PPAttribs.m_f4CustomMieBeta = pTheSample->m_f4CustomMieBeta;
                    }, 
                    this, "group=Advanced label=\'Update coefficients\'");
    }

    // Tone mapping GUI controls
    {
        {
            TwEnumVal ToneMappingMode[] =
            {
                {TONE_MAPPING_MODE_EXP,          "Exp"},
                {TONE_MAPPING_MODE_REINHARD,     "Reinhard"},
                {TONE_MAPPING_MODE_REINHARD_MOD, "Reinhard Mod"},
                {TONE_MAPPING_MODE_UNCHARTED2,   "Uncharted 2"},
                {TONE_MAPPING_FILMIC_ALU,        "Filmic ALU"},
                {TONE_MAPPING_LOGARITHMIC,       "Logarithmic"},
                {TONE_MAPPING_ADAPTIVE_LOG,      "Adaptive log"}
            };
            TwType ToneMappingModeEnum = TwDefineEnum( "Tone mapping mode enum", ToneMappingMode, _countof( ToneMappingMode ) );
            TwAddVarRW( bar, "ToneMappingMode", ToneMappingModeEnum, &m_PPAttribs.m_uiToneMappingMode, "group=ToneMapping label=\'Mode\'" );
        }
        TwAddVarRW( bar, "WhitePoint", TW_TYPE_FLOAT, &m_PPAttribs.m_fWhitePoint, "group=ToneMapping label=\'White point\' min=0.01 max=10.0 step=0.1" );
        TwAddVarRW( bar, "LumSaturation", TW_TYPE_FLOAT, &m_PPAttribs.m_fLuminanceSaturation, "group=ToneMapping label=\'Luminance saturation\' min=0.01 max=2.0 step=0.1" );
        TwAddVarRW( bar, "MiddleGray", TW_TYPE_FLOAT, &m_PPAttribs.m_fMiddleGray, "group=ToneMapping label=\'Middle Gray\' min=0.01 max=1.0 step=0.01" );
        TwAddVarRW( bar, "AutoExposure", TW_TYPE_BOOLCPP, &m_PPAttribs.m_bAutoExposure, "group=ToneMapping label=\'Auto exposure\'" );
        TwAddVarRW( bar, "LightAdaptation", TW_TYPE_BOOLCPP, &m_PPAttribs.m_bLightAdaptation, "group=ToneMapping label=\'Light adaptation\'" );
    }

    const auto& RG16UAttribs = pDevice->GetTextureFormatInfoExt( TEX_FORMAT_RG16_UNORM );
    const auto& RG32FAttribs = pDevice->GetTextureFormatInfoExt( TEX_FORMAT_RG32_FLOAT );
    bool RG16USupported = RG16UAttribs.Supported && RG16UAttribs.ColorRenderable;
    bool RG32FSupported = RG32FAttribs.Supported && RG32FAttribs.ColorRenderable;
    if( !RG16USupported && !RG32FSupported )
    {
        int32_t IsVisible = 0;
        TwSetParam( bar, "1DMinMaxOptimization", "visible", TW_PARAM_INT32, 1, &IsVisible );
        m_PPAttribs.m_bUse1DMinMaxTree = FALSE;
    }

    if( !RG16USupported || !RG32FSupported )
    {
        int32_t IsVisible = 0;
        TwSetParam( bar, "Is32BitMinMaxShadowMap", "visible", TW_PARAM_INT32, 1, &IsVisible );

        if( RG16USupported && !RG32FSupported )
            m_PPAttribs.m_bIs32BitMinMaxMipMap = FALSE;

        if( !RG16USupported && RG32FSupported )
            m_PPAttribs.m_bIs32BitMinMaxMipMap = TRUE;
    }
}
void FGLRenderBuffers::BindShadowMapTexture(int texunit)
{
	CreateShadowMap();
	glActiveTexture(GL_TEXTURE0 + texunit);
	glBindTexture(GL_TEXTURE_2D, mShadowMapTexture.handle);
}
void FGLRenderBuffers::BindShadowMapFB()
{
	CreateShadowMap();
	glBindFramebuffer(GL_FRAMEBUFFER, mShadowMapFB.handle);
}