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

📄 opengl.cpp

📁 虚幻的再开发程序包源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		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 + -