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

📄 opengl.cpp

📁 虚幻的再开发程序包源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
				}
			}
			if( Xor & PF_Invisible )
			{
				UBOOL Show = ((PolyFlags&PF_Invisible)==0);
				glColorMask( Show, Show, Show, Show );
			}
			if( Xor & PF_Occlude )
			{
				glDepthMask( (PolyFlags&PF_Occlude)!=0 );
			}
			if( Xor & PF_Masked )
			{
				if( PolyFlags & PF_Masked )
					glEnable( GL_ALPHA_TEST );
				else
					glDisable( GL_ALPHA_TEST );
			}
		}
		CurrentPolyFlags = PolyFlags;
		unguardSlow;
	}

	// URenderDevice interface.
	UBOOL Init( UViewport* InViewport, INT NewX, INT NewY, INT NewColorBytes, UBOOL Fullscreen )
	{
		guard(UOpenGLRenderDevice::Init);

		// Driver flags.
		SpanBased			= 0;
		FullscreenOnly		= 0;//!!drv dependent
		SupportsFogMaps		= 1;
		SupportsDistanceFog	= 0;

		// Get list of device modes.
		for( INT i=0; ; i++ )
		{
#if UNICODE
			if( !GUnicodeOS )
			{
				DEVMODEA Tmp;
				appMemzero(&Tmp,sizeof(Tmp));
				Tmp.dmSize = sizeof(Tmp);
				if( !EnumDisplaySettingsA(NULL,i,&Tmp) )
					break;
				Modes.AddUniqueItem( FPlane(Tmp.dmPelsWidth,Tmp.dmPelsHeight,Tmp.dmBitsPerPel,Tmp.dmDisplayFrequency) );
			}
			else
#endif
			{
				DEVMODE Tmp;
				appMemzero(&Tmp,sizeof(Tmp));
				Tmp.dmSize = sizeof(Tmp);
				if( !EnumDisplaySettings(NULL,i,&Tmp) )
					break;
				Modes.AddUniqueItem( FPlane(Tmp.dmPelsWidth,Tmp.dmPelsHeight,Tmp.dmBitsPerPel,Tmp.dmDisplayFrequency) );
			}
		}

		// Init global GL.
		if( NumDevices==0 )
		{
#if DYNAMIC_BIND
			// Find DLL's.
			hModuleGlMain = LoadLibraryA( GL_DLL );
			if( !hModuleGlMain )
			{
				debugf( NAME_Init, LocalizeError("NoFindGL"), appFromAnsi(GL_DLL) );
				return 0;
			}
			hModuleGlGdi = LoadLibraryA( "GDI32.dll" );
			check(hModuleGlGdi);

			// Find functions.
			SUPPORTS_GL = 1;
			FindProcs( 0 );
			if( !SUPPORTS_GL )
				return 0;
#endif
			// Init pyramid compression table.
			for( INT A=0; A<256; A++ )
			{
				for( INT B=0; B<=A; B++ )
				{
					FLOAT F                     = (FLOAT)B/Max(A,1);
					ScaleByteNormal  [PYR(A)+B] = 255.f*F;
					ScaleByteBrighten[PYR(A)+B] = 255.f*Min(1.f,(OVERBRIGHT)*F-(OVERBRIGHT-1.0f)*F*F*F*F*F*F);//!!always saturates, should be better
				}
			}
		}
		NumDevices++;

		// Init this GL rendering context.
		BindMap = ShareLists ? &SharedBindMap : &LocalBindMap;
		Viewport = InViewport;
		hWnd = (HWND)InViewport->GetWindow();
		check(hWnd);
		hDC = GetDC( hWnd );
		check(hDC);
#if 1 /* Print all PFD's exposed */
		INT Count = DescribePixelFormat( hDC, 0, 0, NULL );
		for( i=1; i<Count; i++ )
			PrintFormat( hDC, i );
#endif
		if( !SetRes( NewX, NewY, NewColorBytes, Fullscreen ) )
			return FailedInitf( LocalizeError("ResFailed") );

		return 1;
		unguard;
	}
	void UnsetRes()
	{
		guard(UOpenGLRenderDevice::UnsetRes);
		check(hRC)
		hCurrentRC = NULL;
		verify(wglMakeCurrent( NULL, NULL ));
		verify(wglDeleteContext( hRC ));
		verify(AllContexts.RemoveItem(hRC)==1);
		hRC = NULL;
		if( WasFullscreen )
			TCHAR_CALL_OS(ChangeDisplaySettings(NULL,0),ChangeDisplaySettingsA(NULL,0));
		unguard;
	}
	void PrintFormat( HDC hDC, INT nPixelFormat )
	{
		guard(UOpenGlRenderDevice::PrintFormat);
		TCHAR Flags[1024]=TEXT("");
		PIXELFORMATDESCRIPTOR pfd;
		DescribePixelFormat( hDC, nPixelFormat, sizeof(pfd), &pfd );
		if( pfd.dwFlags & PFD_DRAW_TO_WINDOW )
			appStrcat( Flags, TEXT(" PFD_DRAW_TO_WINDOW") );
		if( pfd.dwFlags & PFD_DRAW_TO_BITMAP )
			appStrcat( Flags, TEXT(" PFD_DRAW_TO_BITMAP") );
		if( pfd.dwFlags & PFD_SUPPORT_GDI )
			appStrcat( Flags, TEXT(" PFD_SUPPORT_GDI") );
		if( pfd.dwFlags & PFD_SUPPORT_OPENGL )
			appStrcat( Flags, TEXT(" PFD_SUPPORT_OPENGL") );
		if( pfd.dwFlags & PFD_GENERIC_ACCELERATED )
			appStrcat( Flags, TEXT(" PFD_GENERIC_ACCELERATED") );
		if( pfd.dwFlags & PFD_GENERIC_FORMAT )
			appStrcat( Flags, TEXT(" PFD_GENERIC_FORMAT") );
		if( pfd.dwFlags & PFD_NEED_PALETTE )
			appStrcat( Flags, TEXT(" PFD_NEED_PALETTE") );
		if( pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE )
			appStrcat( Flags, TEXT(" PFD_NEED_SYSTEM_PALETTE") );
		if( pfd.dwFlags & PFD_DOUBLEBUFFER )
			appStrcat( Flags, TEXT(" PFD_DOUBLEBUFFER") );
		if( pfd.dwFlags & PFD_STEREO )
			appStrcat( Flags, TEXT(" PFD_STEREO") );
		if( pfd.dwFlags & PFD_SWAP_LAYER_BUFFERS )
			appStrcat( Flags, TEXT("PFD_SWAP_LAYER_BUFFERS") );
		debugf( NAME_Init, TEXT("Pixel format %i:"), nPixelFormat );
		debugf( NAME_Init, TEXT("   Flags:%s"), Flags );
		debugf( NAME_Init, TEXT("   Pixel Type: %i"), pfd.iPixelType );
		debugf( NAME_Init, TEXT("   Bits: Color=%i R=%i G=%i B=%i A=%i"), pfd.cColorBits, pfd.cRedBits, pfd.cGreenBits, pfd.cBlueBits, pfd.cAlphaBits );
		debugf( NAME_Init, TEXT("   Bits: Accum=%i Depth=%i Stencil=%i"), pfd.cAccumBits, pfd.cDepthBits, pfd.cStencilBits );
		unguard;
	}
	UBOOL SetRes( INT NewX, INT NewY, INT NewColorBytes, UBOOL Fullscreen )
	{
		guard(UOpenGlRenderDevice::SetRes);
		
		// Flush textures.
		Flush();

		// If not fullscreen, and color bytes hasn't changed, do nothing.
		if( hRC && !Fullscreen && !WasFullscreen && NewColorBytes==Viewport->ColorBytes )
		{
			if( !Viewport->ResizeViewport( BLIT_HardwarePaint|BLIT_Race, NewX, NewY, NewColorBytes ) )
				return 0;
			glViewport( 0, 0, NewX, NewY );
			return 1;
		}

		// Exit res.
		if( hRC )
			UnsetRes();

#if !STDGL
		Fullscreen = 1; /* Minidrivers are fullscreen only!! */
#endif

		// Change display settings.
		if( Fullscreen && STDGL )
		{
			INT FindX=NewX, FindY=NewY, BestError = MAXINT;
			for( INT i=0; i<Modes.Num(); i++ )
			{
				if( Modes(i).Z==NewColorBytes*8 )
				{
					INT Error
					=	(Modes(i).X-FindX)*(Modes(i).X-FindX)
					+	(Modes(i).Y-FindY)*(Modes(i).Y-FindY);
					if( Error < BestError )
					{
						NewX      
						= Modes(i).X;
						NewY      = Modes(i).Y;
						BestError = Error;
					}
				}
			}
#if UNICODE
			if( !GUnicodeOS )
			{
				DEVMODEA dm;
				ZeroMemory( &dm, sizeof(dm) );
				dm.dmSize       = sizeof(dm);
				dm.dmPelsWidth  = NewX;
				dm.dmPelsHeight = NewY;
				dm.dmBitsPerPel = NewColorBytes;
				dm.dmFields     = DM_PELSWIDTH | DM_PELSHEIGHT;
				//DM_BITSPERPEL
				if( ChangeDisplaySettingsA( &dm, CDS_FULLSCREEN )!=DISP_CHANGE_SUCCESSFUL )
				{
					debugf( TEXT("ChangeDisplaySettingsA failed: %ix%i"), NewX, NewY );
					return 0;
				}
			}
			else
#endif
			{
				DEVMODE dm;
				ZeroMemory( &dm, sizeof(dm) );
				dm.dmSize       = sizeof(dm);
				dm.dmPelsWidth  = NewX;
				dm.dmPelsHeight = NewY;
				dm.dmBitsPerPel = NewColorBytes;
				dm.dmFields     = DM_PELSWIDTH | DM_PELSHEIGHT;
				//DM_BITSPERPEL
				if( ChangeDisplaySettings( &dm, CDS_FULLSCREEN )!=DISP_CHANGE_SUCCESSFUL )
				{
					debugf( TEXT("ChangeDisplaySettings failed: %ix%i"), NewX, NewY );
					return 0;
				}
			}
		}

		// Change window size.
		UBOOL Result = Viewport->ResizeViewport( Fullscreen ? (BLIT_Fullscreen|BLIT_Race) : (BLIT_HardwarePaint|BLIT_Race), NewX, NewY, NewColorBytes );
		if( !Result )
		{
			if( Fullscreen )
				TCHAR_CALL_OS(ChangeDisplaySettings(NULL,0),ChangeDisplaySettingsA(NULL,0));
			return 0;
		}

		// Set res.
		INT DesiredColorBits   = NewColorBytes<=2 ? 16 : 24;
		INT DesiredStencilBits = NewColorBytes<=2 ? 0  : 8;
		INT DesiredDepthBits   = NewColorBytes<=2 ? 16 : 32;
		PIXELFORMATDESCRIPTOR pfd =
		{
			sizeof(PIXELFORMATDESCRIPTOR),
			1,
			PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
			PFD_TYPE_RGBA,
			DesiredColorBits,
			0,0,0,0,0,0,
			0,0,
			0,0,0,0,0,
			DesiredDepthBits,
			DesiredStencilBits,
			0,
			PFD_MAIN_PLANE,
			0,
			0,0,0
		};
		INT nPixelFormat = ChoosePixelFormat( hDC, &pfd );
		Parse( appCmdLine(), TEXT("PIXELFORMAT="), nPixelFormat );
		debugf( NAME_Init, TEXT("Using pixel format %i"), nPixelFormat );
		check(nPixelFormat);
		verify(SetPixelFormat( hDC, nPixelFormat, &pfd ));
		hRC = wglCreateContext( hDC );
		check(hRC);
		MakeCurrent();
		if( ShareLists && AllContexts.Num() )
			verify(wglShareLists(AllContexts(0),hRC)==1);
		AllContexts.AddItem(hRC);

		// Get info and extensions.
		debugf( NAME_Init, TEXT("glGetString(GL_VENDOR): %s"),     appFromAnsi((ANSICHAR*)glGetString(GL_VENDOR)) );
		debugf( NAME_Init, TEXT("glGetString(GL_RENDERER): %s"),   appFromAnsi((ANSICHAR*)glGetString(GL_RENDERER)) );
		debugf( NAME_Init, TEXT("glGetString(GL_VERSION): %s"),    appFromAnsi((ANSICHAR*)glGetString(GL_VERSION)) );
		debugf( NAME_Init, TEXT("glGetString(GL_EXTENSIONS): %s"), appFromAnsi((ANSICHAR*)glGetString(GL_EXTENSIONS)) );
		PrintFormat( hDC, nPixelFormat );
		FindProcs( 1 );

		// Set modelview.
		glMatrixMode( GL_MODELVIEW );
		glLoadIdentity();
		FLOAT Matrix[16] =
		{
			+1, +0, +0, +0,
			+0, -1, +0, +0,
			+0, +0, -1, +0,
			+0, +0, +0, +1,
		};
		glMultMatrixf( Matrix );

		// Find section.
		FString Section = US + appFromAnsi((ANSICHAR*)glGetString(GL_VENDOR)) + TEXT("/") + appFromAnsi((ANSICHAR*)glGetString(GL_RENDERER));
		if( !GConfig->GetSectionPrivate( *Section, 0, 1, GPackage ) )
			Section = TEXT("Default");
		debugf( NAME_Init, TEXT("Using OpenGL settings [%s]"), *Section );

		// Get hardware defaults.
		GConfig->GetInt( *Section, TEXT("MinLogTextureSize"), MinLogTextureSize, GPackage );
		GConfig->GetInt( *Section, TEXT("MaxLogTextureSize"), MaxLogTextureSize, GPackage );
		GConfig->GetInt( *Section, TEXT("MaxLogUOverV"     ), MaxLogUOverV,      GPackage );
		GConfig->GetInt( *Section, TEXT("MaxLogVOverU"     ), MaxLogVOverU,      GPackage );
		GConfig->GetInt( *Section, TEXT("UseZTrick"        ), UseZTrick,         GPackage );
		GConfig->GetInt( *Section, TEXT("UseMultiTexture"  ), UseMultiTexture,   GPackage );
		GConfig->GetInt( *Section, TEXT("UsePalette"       ), UsePalette,        GPackage );
		GConfig->GetInt( *Section, TEXT("ShareLists"       ), ShareLists,        GPackage );
		GConfig->GetInt( *Section, TEXT("AlwaysMipmap"     ), AlwaysMipmap,      GPackage );
		GConfig->GetInt( *Section, TEXT("DoPrecache"       ), DoPrecache,        GPackage );
		SupportsLazyTextures = DoPrecache;

		// Verify hardware defaults.
		check(MinLogTextureSize>=0);
		check(MaxLogTextureSize>=0);
		check(MinLogTextureSize<MaxLogTextureSize);
		check(MinLogTextureSize<=MaxLogTextureSize);

		// Validate flags.
		if( !SUPPORTS_GL_ARB_multitexture )
			UseMultiTexture = 0;
		if( !SUPPORTS_GL_EXT_paletted_texture )
			UsePalette = 0;

		// Misc.
		Multipass1X = UseMultiTexture; //!! and 2X blending isn't supported
		ScaleByte   = Multipass1X ? ScaleByteBrighten : ScaleByteNormal;

		// Bind little white RGBA texture to ID 0.
		FColor Data[8*8];
		for( INT i=0; i<ARRAY_COUNT(Data); i++ )
			Data[i] = FColor(255,255,255,255);
		SetNoTexture( 0 );
		for( INT Level=0; 8>>Level; Level++ )
			glTexImage2D( GL_TEXTURE_2D, Level, 4, 8>>Level, 8>>Level, 0, GL_RGBA, GL_UNSIGNED_BYTE, Data );

		// Set permanent state.
		glEnable( GL_DEPTH_TEST );
		glShadeModel( GL_SMOOTH );
		glEnable( GL_TEXTURE_2D );
		glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
		glAlphaFunc( GL_GREATER, 0.5 );
		glDisable( GL_ALPHA_TEST );
		glDepthMask( 1 );
		glBlendFunc( GL_ONE, GL_ZERO );
		glEnable( GL_BLEND );
		CurrentPolyFlags = PF_Occlude;

		// Remember fullscreenness.
		WasFullscreen = Fullscreen;
		return 1;

		unguard;
	}
	void Exit()
	{
		guard(UOpenGLRenderDevice::Exit);
		check(NumDevices>0);

		// Shut down RC.
		Flush();
		if( hRC )
			UnsetRes();

		// Shut down this GL context. May fail if window was already destroyed.
		if( hDC )
			ReleaseDC(hWnd,hDC);

		// Shut down global GL.
		if( --NumDevices==0 )
		{
#if DYNAMIC_BIND && 0 /* Broken on some drivers */
			// Free modules.
			if( hModuleGlMain )
				verify(FreeLibrary( hModuleGlMain ));
			if( hModuleGlGdi )
				verify(FreeLibrary( hModuleGlGdi ));
#endif
			SharedBindMap.~TMap<QWORD,FCachedTexture>();
			AllContexts.~TArray<HGLRC>();
		}
		unguard;
	}
	void ShutdownAfterError()
	{
		guard(UOpenGLRenderDevice::ShutdownAfterError);
		debugf( NAME_Exit, TEXT("UOpenGLRenderDevice::ShutdownAfterError") );
		ChangeDisplaySettings( NULL, 0 );
		unguard;
	}
	void Flush()
	{
		guard(UOpenGLRenderDevice::Flush);
		TArray<GLuint> Binds;
		for( TMap<QWORD,FCachedTexture>::TIterator It(*BindMap); It; ++It )
			Binds.AddItem( It->Value.Id );
		BindMap->Empty();
		glDeleteTextures( Binds.Num(), (GLuint*)&Binds(0) );
		if( DoPrecache && !GIsEditor )
			PrecacheOnFlip = 1;
		unguard;
	}
	static QSORT_RETURN CDECL CompareRes( const FPlane* A, const FPlane* B )
	{
		return (A->X-B->X)!=0.0 ? (A->X-B->X) : (A->Y-B->Y);
	}
	UBOOL Exec( const TCHAR* Cmd, FOutputDevice& Ar )
	{
		guard(UOpenGLRenderDevice::Exec);
		if( ParseCommand(&Cmd,TEXT("GetRes")) )
		{
			TArray<FPlane> Relevant;
			INT i;
			for( i=0; i<Modes.Num(); i++ )
				if( Modes(i).Z==Viewport->ColorBytes*8 )
					if
					(	(Modes(i).X!=320 || Modes(i).Y!=200)
					&&	(Modes(i).X!=640 || Modes(i).Y!=400) )
					Relevant.AddUniqueItem(FPlane(Modes(i).X,Modes(i).Y,0,0));
			appQsort( &Relevant(0), Relevant.Num(), sizeof(FPlane), (QSORT_COMPARE)CompareRes );
			FString Str;
			for( i=0; i<Relevant.Num(); i++ )
				Str += FString::Printf( TEXT("%ix%i "), (INT)Relevant(i).X, (INT)Relevant(i).Y );
			Ar.Log( *Str.LeftChop(1) );
			return 1;
		}
		return 0;
		unguard;
	}
	void Lock( FPlane InFlashScale, FPlane InFlashFog, FPlane ScreenClear, DWORD RenderLockFlags, BYTE* InHitData, INT* InHitSize )
	{
		guard(UOpenGLRenderDevice::Lock);
		check(LockCount==0);
		BindCycles = ImageCycles = ComplexCycles = GouraudCycles = TileCycles = 0;
		++LockCount;

		// Make this context current.
		MakeCurrent();

		// Clear the Z buffer if needed.
		if( !UseZTrick || GIsEditor )
		{
			glClearColor( ScreenClear.X, ScreenClear.Y, ScreenClear.Z, ScreenClear.W );
			glClearDepth( 1.0 );
			glDepthRange( 0.0, 1.0 );
			ZTrickFunc = GL_LEQUAL;
			SetBlend( PF_Occlude );
			glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
		}
		else if( ZTrickToggle )
		{
			ZTrickToggle = 0;
			glClearDepth( 0.5 );
			glDepthRange( 0.0, 0.5 );
			ZTrickFunc = GL_LEQUAL;
		}
		else
		{
			ZTrickToggle = 1;
			glClearDepth( 0.5 );
			glDepthRange( 1.0, 0.5 );
			ZTrickFunc = GL_GEQUAL;
		}
		glDepthFunc( ZTrickFunc );

		// Remember stuff.
		FlashScale = InFlashScale;
		FlashFog   = InFlashFog;
		HitData    = InHitData;
		HitSize    = InHitSize;
		if( HitData )
		{
			*HitSize = 0;
			if( !GLHitData.Num() )
				GLHitData.Add( 16384 );
			glSelectBuffer( GLHitData.Num(), (GLuint*)&GLHitData(0) );
			glRenderMode( GL_SELECT );
			glInitNames();
		}

⌨️ 快捷键说明

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