📄 opengl.cpp
字号:
unguard;
}
void SetSceneNode( FSceneNode* Frame )
{
guard(UOpenGLDriver::SetSceneNode);
// Precompute stuff.
Aspect = Frame->FY/Frame->FX;
RProjZ = appTan( Viewport->Actor->FovAngle * PI/360.0 );
RFX2 = 2.0*RProjZ/Frame->FX;
RFY2 = 2.0*RProjZ*Aspect/Frame->FY;
// Set viewport and projection.
glViewport( Frame->XB, Viewport->SizeY-Frame->Y-Frame->YB, Frame->X, Frame->Y );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glFrustum( -RProjZ, +RProjZ, -Aspect*RProjZ, +Aspect*RProjZ, 1.0, 32768.0 );
// Set clip planes.
if( HitData )
{
FVector N[4];
N[0] = (FVector((Viewport->HitX-Frame->FX2)*Frame->RProj.Z,0,1)^FVector(0,-1,0)).SafeNormal();
N[1] = (FVector((Viewport->HitX+Viewport->HitXL-Frame->FX2)*Frame->RProj.Z,0,1)^FVector(0,+1,0)).SafeNormal();
N[2] = (FVector(0,(Viewport->HitY-Frame->FY2)*Frame->RProj.Z,1)^FVector(+1,0,0)).SafeNormal();
N[3] = (FVector(0,(Viewport->HitY+Viewport->HitYL-Frame->FY2)*Frame->RProj.Z,1)^FVector(-1,0,0)).SafeNormal();
for( INT i=0; i<4; i++ )
{
DOUBLE D0[4]={N[i].X,N[i].Y,N[i].Z,0};
glClipPlane( GL_CLIP_PLANE0+i, D0 );
glEnable( GL_CLIP_PLANE0+i );
}
}
unguard;
}
void Unlock( UBOOL Blit )
{
guard(UOpenGLRenderDevice::Unlock);
// Unlock and render.
check(LockCount==1);
glFlush();
if( Blit )
verify(SwapBuffers( hDC ));
--LockCount;
// Precache now if needed.
if( PrecacheOnFlip )
{
PrecacheOnFlip = 0;
for( TObjectIterator<UModel> ItM; ItM; ++ItM )
{
//oldver: Since some Unreal 1 textures were imported without masking,
// we must fix them up here.
for( INT i=0; i<ItM->Surfs.Num(); i++ )
if( ItM->Surfs(i).Texture )
ItM->Surfs(i).Texture->PolyFlags |= (ItM->Surfs(i).PolyFlags&PF_Masked);
}
for( TObjectIterator<UTexture> It; It; ++It )
{
if( !It->bParametric )
{
for( INT i=Viewport->GetOuterUClient()->TextureLODSet[It->LODSet]; i<MAX_TEXTURE_LOD; i++ )
{
FTextureInfo T;
It->Lock( T, Viewport->LastUpdateTime, i, this );
if( T.LOD==i )
SetTexture( 0, T, It->PolyFlags, 0 );
It->Unlock( T );
}
}
}
}
// Hits.
if( HitData )
{
INT Records = glRenderMode( GL_RENDER );
INT* Ptr = &GLHitData(0);
DWORD BestDepth = MAXDWORD;
for( INT i=0; i<Records; i++ )
{
INT NameCount = *Ptr++;
DWORD MinDepth = *Ptr++;
DWORD MaxDepth = *Ptr++;
if( MinDepth<=BestDepth )
{
BestDepth = MinDepth;
*HitSize = 0;
for( INT i=0; i<NameCount; )
{
INT Count = Ptr[i++];
for( INT j=0; j<Count; j+=4 )
*(INT*)(HitData+*HitSize+j) = Ptr[i++];
*HitSize += Count;
}
check(i==NameCount);
}
Ptr += NameCount;
(void)MaxDepth;
}
for( i=0; i<4; i++ )
glDisable( GL_CLIP_PLANE0+i );
}
unguard;
}
void DrawComplexSurface( FSceneNode* Frame, FSurfaceInfo& Surface, FSurfaceFacet& Facet )
{
guard(UOpenGLRenderDevice::DrawComplexSurface);
check(Surface.Texture);
clock(ComplexCycles);
FLOAT UDot = Facet.MapCoords.XAxis | Facet.MapCoords.Origin;
FLOAT VDot = Facet.MapCoords.YAxis | Facet.MapCoords.Origin;
// Modulation chain.
if( Surface.LightMap && UseMultiTexture )
{
// Draw with multitexture.
SetBlend( Surface.PolyFlags );
SetTexture( 0, *Surface.LightMap, PF_Modulated, -0.5 );
glActiveTextureARB( GL_TEXTURE1_ARB );
SetTexture( 1, *Surface.Texture, Surface.PolyFlags, 0.0 );
glEnable( GL_TEXTURE_2D );
glColor4f( TexInfo[0].ColorRenorm.X*TexInfo[1].ColorRenorm.X, TexInfo[0].ColorRenorm.Y*TexInfo[1].ColorRenorm.Y, TexInfo[0].ColorRenorm.Z*TexInfo[1].ColorRenorm.Z, 1 );
for( FSavedPoly* Poly=Facet.Polys; Poly; Poly=Poly->Next )
{
glBegin( GL_TRIANGLE_FAN );
for( INT i=0; i<Poly->NumPts; i++ )
{
FLOAT U = Facet.MapCoords.XAxis | Poly->Pts[i]->Point;
FLOAT V = Facet.MapCoords.YAxis | Poly->Pts[i]->Point;
glMultiTexCoord2fARB( GL_TEXTURE0_ARB, (U-UDot-TexInfo[0].UPan)*TexInfo[0].UMult, (V-VDot-TexInfo[0].VPan)*TexInfo[0].VMult );
glMultiTexCoord2fARB( GL_TEXTURE1_ARB, (U-UDot-TexInfo[1].UPan)*TexInfo[1].UMult, (V-VDot-TexInfo[1].VPan)*TexInfo[1].VMult );
glVertex3fv( &Poly->Pts[i]->Point.X );
}
glEnd();
}
glDisable( GL_TEXTURE_2D );
glActiveTextureARB( GL_TEXTURE0_ARB );
}
else
{
// Draw texture.
SetBlend( Surface.PolyFlags );
SetTexture( 0, *Surface.Texture, Surface.PolyFlags, 0.0 );
FPlane Modulate = TexInfo[0].ColorNorm;
glColor4fv( Surface.LightMap ? &One4.X : &Modulate.X );
for( FSavedPoly* Poly=Facet.Polys; Poly; Poly=Poly->Next )
{
glBegin( GL_TRIANGLE_FAN );
for( INT i=0; i<Poly->NumPts; i++ )
{
FLOAT U = Facet.MapCoords.XAxis | Poly->Pts[i]->Point;
FLOAT V = Facet.MapCoords.YAxis | Poly->Pts[i]->Point;
glTexCoord2f( (U-UDot-TexInfo[0].UPan)*TexInfo[0].UMult, (V-VDot-TexInfo[0].VPan)*TexInfo[0].VMult );
glVertex3fv( &Poly->Pts[i]->Point.X );
}
glEnd();
}
// Draw lightmap.
if( Surface.LightMap )
{
SetBlend( PF_Modulated );
if( Surface.PolyFlags & PF_Masked )
glDepthFunc( GL_EQUAL );
SetTexture( 0, *Surface.LightMap, 0, -0.5 );
Modulate.X *= TexInfo[0].ColorNorm.X;
Modulate.Y *= TexInfo[0].ColorNorm.Y;
Modulate.Z *= TexInfo[0].ColorNorm.Z;
glColor4fv( &Modulate.X );
for( FSavedPoly* Poly=Facet.Polys; Poly; Poly=Poly->Next )
{
glBegin( GL_TRIANGLE_FAN );
for( INT i=0; i<Poly->NumPts; i++ )
{
FLOAT U = Facet.MapCoords.XAxis | Poly->Pts[i]->Point;
FLOAT V = Facet.MapCoords.YAxis | Poly->Pts[i]->Point;
glTexCoord2f( (U-UDot-TexInfo[0].UPan)*TexInfo[0].UMult, (V-VDot-TexInfo[0].VPan)*TexInfo[0].VMult );
glVertex3fv ( &Poly->Pts[i]->Point.X );
}
glEnd();
}
if( Surface.PolyFlags & PF_Masked )
glDepthFunc( ZTrickFunc );
}
}
// Draw fog.
if( Surface.FogMap )
{
SetBlend( PF_Environment );
if( Surface.PolyFlags & PF_Masked )
glDepthFunc( GL_EQUAL );
SetTexture( 0, *Surface.FogMap, 0, -0.5 );
glColor4fv( &TexInfo[0].ColorNorm.X );
for( FSavedPoly* Poly=Facet.Polys; Poly; Poly=Poly->Next )
{
glBegin( GL_TRIANGLE_FAN );
for( INT i=0; i<Poly->NumPts; i++ )
{
FLOAT U = Facet.MapCoords.XAxis | Poly->Pts[i]->Point;
FLOAT V = Facet.MapCoords.YAxis | Poly->Pts[i]->Point;
glTexCoord2f( (U-UDot-TexInfo[0].UPan)*TexInfo[0].UMult, (V-VDot-TexInfo[0].VPan)*TexInfo[0].VMult );
glVertex3fv ( &Poly->Pts[i]->Point.X );
}
glEnd();
}
if( Surface.PolyFlags & PF_Masked )
glDepthFunc( ZTrickFunc );
}
// UnrealEd selection.
if( (Surface.PolyFlags & PF_Selected) && GIsEditor )
{
SetNoTexture( 0 );
SetBlend( PF_Environment );
glBegin( GL_TRIANGLE_FAN );
glColor4f( 0.0, 0.0, 0.5, 0.5 );
for( FSavedPoly* Poly=Facet.Polys; Poly; Poly=Poly->Next )
{
glBegin( GL_TRIANGLE_FAN );
for( INT i=0; i<Poly->NumPts; i++ )
glVertex3fv ( &Poly->Pts[i]->Point.X );
glEnd();
}
glEnd();
}
unclock(ComplexCycles);
unguard;
}
void DrawGouraudPolygon( FSceneNode* Frame, FTextureInfo& Info, FTransTexture** Pts, INT NumPts, DWORD PolyFlags, FSpanBuffer* Span )
{
guard(UOpenGLRenderDevice::GouraudPolygon);
clock(GouraudCycles);
SetBlend( PolyFlags );
SetTexture( 0, Info, PolyFlags, 0 );
glBegin( GL_TRIANGLE_FAN );
for( INT i=0; i<NumPts; i++ )
{
FTransTexture* P = Pts[i];
glColor4f( P->Light.X*TexInfo[0].ColorNorm.X, P->Light.Y*TexInfo[0].ColorNorm.Y, P->Light.Z*TexInfo[0].ColorNorm.Z, 1 );
glTexCoord2f( P->U*TexInfo[0].UMult, P->V*TexInfo[0].VMult );
glVertex3fv( &P->Point.X );
}
glEnd();
if( (PolyFlags & (PF_RenderFog|PF_Translucent|PF_Modulated))==PF_RenderFog )
{
SetNoTexture( 0 );
SetBlend( PF_Environment );
glBegin( GL_TRIANGLE_FAN );
for( INT i=0; i<NumPts; i++ )
{
FTransTexture* P = Pts[i];
glColor4f( P->Fog.X, P->Fog.Y, P->Fog.Z, P->Fog.W );
glVertex3fv( &P->Point.X );
}
glEnd();
}
unclock(GouraudCycles);
unguard;
}
void DrawTile( FSceneNode* Frame, FTextureInfo& Info, FLOAT X, FLOAT Y, FLOAT XL, FLOAT YL, FLOAT U, FLOAT V, FLOAT UL, FLOAT VL, class FSpanBuffer* Span, FLOAT Z, FPlane Color, FPlane Fog, DWORD PolyFlags )
{
guard(UOpenGLRenderDevice::DrawTile);
clock(TileCycles);
SetBlend( PolyFlags );
SetTexture( 0, Info, PolyFlags, 0 );
Color.X *= TexInfo[0].ColorNorm.X;
Color.Y *= TexInfo[0].ColorNorm.Y;
Color.Z *= TexInfo[0].ColorNorm.Z;
Color.W = 1;
glColor4fv( &Color.X );
glBegin( GL_TRIANGLE_FAN );
glTexCoord2f( (U )*TexInfo[0].UMult, (V )*TexInfo[0].VMult ); glVertex3f( RFX2*Z*(X -Frame->FX2), RFY2*Z*(Y -Frame->FY2), Z );
glTexCoord2f( (U+UL)*TexInfo[0].UMult, (V )*TexInfo[0].VMult ); glVertex3f( RFX2*Z*(X+XL-Frame->FX2), RFY2*Z*(Y -Frame->FY2), Z );
glTexCoord2f( (U+UL)*TexInfo[0].UMult, (V+VL)*TexInfo[0].VMult ); glVertex3f( RFX2*Z*(X+XL-Frame->FX2), RFY2*Z*(Y+YL-Frame->FY2), Z );
glTexCoord2f( (U )*TexInfo[0].UMult, (V+VL)*TexInfo[0].VMult ); glVertex3f( RFX2*Z*(X -Frame->FX2), RFY2*Z*(Y+YL-Frame->FY2), Z );
glEnd();
unclock(TileCycles);
unguard;
}
void Draw2DLine( FSceneNode* Frame, FPlane Color, DWORD LineFlags, FVector P1, FVector P2 )
{
guard(UOpenGLRenderDevice::Draw2DLine);
SetNoTexture( 0 );
SetBlend( PF_Environment );
glColor3fv( &Color.X );
glBegin( GL_LINES );
glVertex3f( RFX2*P1.Z*(P1.X-Frame->FX2), RFY2*P1.Z*(P1.Y-Frame->FY2), P1.Z );
glVertex3f( RFX2*P2.Z*(P2.X-Frame->FX2), RFY2*P2.Z*(P2.Y-Frame->FY2), P2.Z );
glEnd();
unguard;
}
void Draw3DLine( FSceneNode* Frame, FPlane Color, DWORD LineFlags, FVector P1, FVector P2 )
{
guard(UOpenGLRenderDevice::Draw3DLine);
P1 = P1.TransformPointBy( Frame->Coords );
P2 = P2.TransformPointBy( Frame->Coords );
if( Frame->Viewport->IsOrtho() )
{
// Zoom.
P1.X = (P1.X) / Frame->Zoom + Frame->FX2;
P1.Y = (P1.Y) / Frame->Zoom + Frame->FY2;
P2.X = (P2.X) / Frame->Zoom + Frame->FX2;
P2.Y = (P2.Y) / Frame->Zoom + Frame->FY2;
P1.Z = P2.Z = 1;
// See if points form a line parallel to our line of sight (i.e. line appears as a dot).
if( Abs(P2.X-P1.X)+Abs(P2.Y-P1.Y)>=0.2 )
Draw2DLine( Frame, Color, LineFlags, P1, P2 );
else if( Frame->Viewport->Actor->OrthoZoom < ORTHO_LOW_DETAIL )
Draw2DPoint( Frame, Color, LINE_None, P1.X-1, P1.Y-1, P1.X+1, P1.Y+1, P1.Z );
}
else
{
SetNoTexture( 0 );
SetBlend( PF_Environment );
glColor3fv( &Color.X );
glBegin( GL_LINES );
glVertex3fv( &P1.X );
glVertex3fv( &P2.X );
glEnd();
}
unguard;
}
void Draw2DPoint( FSceneNode* Frame, FPlane Color, DWORD LineFlags, FLOAT X1, FLOAT Y1, FLOAT X2, FLOAT Y2, FLOAT Z )
{
guard(UOpenGLRenderDevice::Draw2DPoint);
SetBlend( PF_Environment );
SetNoTexture( 0 );
glColor4fv( &Color.X );
glBegin( GL_TRIANGLE_FAN );
glVertex3f( RFX2*Z*(X1-Frame->FX2), RFY2*Z*(Y1-Frame->FY2), Z );
glVertex3f( RFX2*Z*(X2-Frame->FX2), RFY2*Z*(Y1-Frame->FY2), Z );
glVertex3f( RFX2*Z*(X2-Frame->FX2), RFY2*Z*(Y2-Frame->FY2), Z );
glVertex3f( RFX2*Z*(X1-Frame->FX2), RFY2*Z*(Y2-Frame->FY2), Z );
glEnd();
unguard;
}
void ClearZ( FSceneNode* Frame )
{
guard(UOpenGLRenderDevice::ClearZ);
SetBlend( PF_Occlude );
glClear( GL_DEPTH_BUFFER_BIT );
unguard;
}
void PushHit( const BYTE* Data, INT Count )
{
guard(UOpenGLRenderDevice::PushHit);
glPushName( Count );
for( INT i=0; i<Count; i+=4 )
glPushName( *(INT*)(Data+i) );
unguard;
}
void PopHit( INT Count, UBOOL bForce )
{
guard(UOpenGLRenderDevice::PopHit);
glPopName();
for( INT i=0; i<Count; i+=4 )
glPopName();
//!!implement bforce
unguard;
}
void GetStats( TCHAR* Result )
{
guard(UOpenGLRenderDevice::GetStats);
appSprintf
(
Result,
TEXT("OpenGL stats: Bind=%04.1f Image=%04.1f Complex=%04.1f Gouraud=%04.1f Tile=%04.1f"),
GSecondsPerCycle*1000 * BindCycles,
GSecondsPerCycle*1000 * ImageCycles,
GSecondsPerCycle*1000 * ComplexCycles,
GSecondsPerCycle*1000 * GouraudCycles,
GSecondsPerCycle*1000 * TileCycles
);
unguard;
}
void ReadPixels( FColor* Pixels )
{
guard(UOpenGLRenderDevice::ReadPixels);
glReadPixels( 0, 0, Viewport->SizeX, Viewport->SizeY, GL_RGBA, GL_UNSIGNED_BYTE, Pixels );
for( INT i=0; i<Viewport->SizeY/2; i++ )
{
for( INT j=0; j<Viewport->SizeX; j++ )
{
Exchange( Pixels[j+i*Viewport->SizeX].R, Pixels[j+(Viewport->SizeY-1-i)*Viewport->SizeX].B );
Exchange( Pixels[j+i*Viewport->SizeX].G, Pixels[j+(Viewport->SizeY-1-i)*Viewport->SizeX].G );
Exchange( Pixels[j+i*Viewport->SizeX].B, Pixels[j+(Viewport->SizeY-1-i)*Viewport->SizeX].R );
}
}
unguard;
}
void EndFlash()
{
if( FlashScale!=FPlane(.5,.5,.5,0) || FlashFog!=FPlane(0,0,0,0) )
{
SetBlend( PF_Environment );
SetNoTexture( 0 );
glColor4f( FlashFog.X, FlashFog.Y, FlashFog.Z, 1.0-Min(FlashScale.X*2.f,1.f) );
FLOAT RFX2 = 2.0*RProjZ /Viewport->SizeX;
FLOAT RFY2 = 2.0*RProjZ*Aspect/Viewport->SizeY;
glBegin( GL_TRIANGLE_FAN );
glVertex3f( RFX2*(-Viewport->SizeX/2.0), RFY2*(-Viewport->SizeY/2.0), 1.0 );
glVertex3f( RFX2*(+Viewport->SizeX/2.0), RFY2*(-Viewport->SizeY/2.0), 1.0 );
glVertex3f( RFX2*(+Viewport->SizeX/2.0), RFY2*(+Viewport->SizeY/2.0), 1.0 );
glVertex3f( RFX2*(-Viewport->SizeX/2.0), RFY2*(+Viewport->SizeY/2.0), 1.0 );
glEnd();
}
}
void Precache( ULevel* Level )
{
guard(UOpenGLRenderDevice::Precache);
Flush();
unguard;
}
};
IMPLEMENT_CLASS(UOpenGLRenderDevice);
// Static variables.
INT UOpenGLRenderDevice::NumDevices = 0;
INT UOpenGLRenderDevice::LockCount = 0;
HGLRC UOpenGLRenderDevice::hCurrentRC = NULL;
HMODULE UOpenGLRenderDevice::hModuleGlMain = NULL;
HMODULE UOpenGLRenderDevice::hModuleGlGdi = NULL;
TArray<HGLRC> UOpenGLRenderDevice::AllContexts;
TMap<QWORD,UOpenGLRenderDevice::FCachedTexture> UOpenGLRenderDevice::SharedBindMap;
// OpenGL function pointers.
#define GL_EXT(name) UBOOL UOpenGLRenderDevice::SUPPORTS##name=0;
#define GL_PROC(ext,ret,func,parms) ret (__stdcall *UOpenGLRenderDevice::func)parms;
#include "OpenGLFuncs.h"
#undef GL_EXT
#undef GL_PROC
/*-----------------------------------------------------------------------------
Driver issues.
General questions for all hardware:
Max texture size?
Min texture size?
Texture aspect ratio?
Which GL texture formats are supported?
Where is the end-user download page?
Riva TNT (NT4, NT050.zip):
Notes
GL_ARB_multitexture is prefered. http://www.berkelium.com/OpenGL/examples
GL_RGBA is optimized; GL_RGB is very slow.
EXT_packed_pixels: Optimized for RGBA4444 and RGBA5551, others unsupported.
Calling glTexImage2D can give hint for internal format.
Driver crashes in UnrealEd when resizing huge viewports
Riva 128:
Drivers:
Full ICD available on web
Notes
Textures: 5551 or 4444 Square power of two. Fakes 565 with 5551.
No modulation blending, must do lighting via pure alpha textures blending with blackness
No Src+Dest-Src*Dest, only Src+Dest
No 2*Src*Dest
No iterated alpha
*Test.
Rage 128:
Drivers:
From ATI's private web site, unreleased.
Notes
Render targets: RGBA8, RGBA4 and RGB4
Texture lighting
Texture formats: RGBA8, RGBA4, RGB4, ARGB4
3dfx:
Can't get GL_EXT_paletted_texture working, it draws blackness.
Intel i740:
RGBA 1555, 565, 4444
-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
The End.
-----------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -