📄 opengl.cpp
字号:
}
}
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 + -