mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 03:24:56 +08:00
Compare commits
27 Commits
mac-bsd-id
...
continuous
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e2b51f5a3 | ||
|
|
2086dc6128 | ||
|
|
5c4dd797ce | ||
|
|
e7636d580f | ||
|
|
64c1413278 | ||
|
|
7eb1220b19 | ||
|
|
a260b4c143 | ||
|
|
cb5146bb48 | ||
|
|
0365e645df | ||
|
|
d1143b4b5c | ||
|
|
aa4bdf0732 | ||
|
|
700a5333af | ||
|
|
ad25458c5a | ||
|
|
8f6ff1b64f | ||
|
|
3abb39f172 | ||
|
|
6a02b77163 | ||
|
|
a3c26affa3 | ||
|
|
95df96e668 | ||
|
|
bdce95a31b | ||
|
|
eec9609354 | ||
|
|
a58f2ac13b | ||
|
|
e704247f9d | ||
|
|
07a096d04e | ||
|
|
f5077a13b9 | ||
|
|
d414eeb246 | ||
|
|
5daf686a82 | ||
|
|
635b382c1d |
2
3rdparty/gl4es/wscript
vendored
2
3rdparty/gl4es/wscript
vendored
@@ -16,6 +16,8 @@ def build(bld):
|
||||
cflags = []
|
||||
if bld.env.COMPILER_CC != 'msvc':
|
||||
cflags += ['-w', '-fvisibility=hidden', '-std=gnu99']
|
||||
else:
|
||||
cflags += ['-wd4098']
|
||||
bld.stlib(source = gl4es_srcdir.ant_glob(['gl/*.c', 'gl/*/*.c', 'glx/hardext.c']),
|
||||
target = 'gl4es',
|
||||
includes = ['gl4es/src', 'gl4es/src/gl', 'gl4es/src/glx', 'gl4es/include'],
|
||||
|
||||
@@ -706,6 +706,9 @@ static void R_CollectRendererNames( void )
|
||||
#if XASH_REF_GLES3COMPAT_ENABLED
|
||||
"gles3compat",
|
||||
#endif
|
||||
#if XASH_REF_DX2_ENABLED
|
||||
"dx2",
|
||||
#endif
|
||||
#if XASH_REF_SOFT_ENABLED
|
||||
"soft",
|
||||
#endif
|
||||
@@ -729,6 +732,9 @@ static void R_CollectRendererNames( void )
|
||||
#if XASH_REF_GLES3COMPAT_ENABLED
|
||||
"GLES3 (gl2_shim)",
|
||||
#endif
|
||||
#if XASH_REF_DX2_ENABLED
|
||||
"DirectX 2",
|
||||
#endif
|
||||
#if XASH_REF_SOFT_ENABLED
|
||||
"Software",
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,7 @@ typedef struct
|
||||
{
|
||||
void *context; // handle to GL rendering context
|
||||
ref_safegl_context_t safe;
|
||||
qboolean software;
|
||||
ref_graphic_apis_t type;
|
||||
} glwstate_t;
|
||||
|
||||
extern glwstate_t glw_state;
|
||||
|
||||
@@ -285,7 +285,7 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
|
||||
if( window_mode != WINDOW_MODE_WINDOWED )
|
||||
SetBits( flags, SDL_FULLSCREEN|SDL_HWSURFACE );
|
||||
|
||||
if( !glw_state.software )
|
||||
if( glw_state.type == REF_GL )
|
||||
SetBits( flags, SDL_OPENGL );
|
||||
|
||||
if( !VID_CreateWindowWithSafeGL( wndname, 0, 0, width, height, flags ))
|
||||
@@ -381,10 +381,10 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
|
||||
|
||||
refState.desktopBitsPixel = 16;
|
||||
|
||||
glw_state.type = type;
|
||||
switch( type )
|
||||
{
|
||||
case REF_SOFTWARE:
|
||||
glw_state.software = true;
|
||||
break;
|
||||
case REF_GL:
|
||||
if( !glw_state.safe && Sys_GetParmFromCmdLine( "-safegl", safe ) )
|
||||
@@ -399,6 +399,8 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case REF_D3D:
|
||||
break;
|
||||
default:
|
||||
Host_Error( "Can't initialize unknown context type %d!\n", type );
|
||||
break;
|
||||
@@ -417,6 +419,7 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
|
||||
ref.dllFuncs.GL_InitExtensions();
|
||||
break;
|
||||
case REF_SOFTWARE:
|
||||
case REF_D3D:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -359,7 +359,7 @@ void GL_UpdateSwapInterval( void )
|
||||
{
|
||||
ClearBits( gl_vsync.flags, FCVAR_CHANGED );
|
||||
|
||||
if( SDL_GL_SetSwapInterval( gl_vsync.value ) < 0 )
|
||||
if( glw_state.context && SDL_GL_SetSwapInterval( gl_vsync.value ) < 0 )
|
||||
Con_Reportf( S_ERROR "SDL_GL_SetSwapInterval: %s\n", SDL_GetError( ));
|
||||
}
|
||||
}
|
||||
@@ -386,7 +386,7 @@ static void VID_GetWindowSizeInPixels( SDL_Window *window, SDL_Renderer *rendere
|
||||
#if SDL_VERSION_ATLEAST( 2, 26, 0 )
|
||||
SDL_GetWindowSizeInPixels( window, w, h );
|
||||
#else
|
||||
if( glw_state.software )
|
||||
if( glw_state.type != REF_GL )
|
||||
SDL_GetRendererOutputSize( renderer, w, h );
|
||||
else
|
||||
SDL_GL_GetDrawableSize( window, w, h );
|
||||
@@ -669,7 +669,7 @@ static rserr_t VID_CreateWindow( const int input_width, const int input_height,
|
||||
SetBits( flags, SDL_WINDOW_ALLOW_HIGHDPI );
|
||||
#endif // !XASH_WIN32
|
||||
|
||||
if( !glw_state.software )
|
||||
if( glw_state.type == REF_GL )
|
||||
SetBits( flags, SDL_WINDOW_OPENGL );
|
||||
|
||||
if( vid_maximized.value )
|
||||
@@ -681,7 +681,7 @@ static rserr_t VID_CreateWindow( const int input_width, const int input_height,
|
||||
|
||||
if( !host.hWnd )
|
||||
{
|
||||
err = glw_state.software ? rserr_unknown : rserr_invalid_context;
|
||||
err = (glw_state.type == REF_GL) ? rserr_invalid_context : rserr_unknown;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -698,7 +698,7 @@ static rserr_t VID_CreateWindow( const int input_width, const int input_height,
|
||||
SDL_ShowWindow( host.hWnd );
|
||||
SDL_RaiseWindow( host.hWnd );
|
||||
|
||||
if( glw_state.software )
|
||||
if( glw_state.type == REF_SOFTWARE )
|
||||
{
|
||||
char cmd[64];
|
||||
|
||||
@@ -720,7 +720,7 @@ static rserr_t VID_CreateWindow( const int input_width, const int input_height,
|
||||
Con_Printf( "SDL_Renderer %s initialized\n", info.name );
|
||||
}
|
||||
}
|
||||
else
|
||||
else if( glw_state.type == REF_GL )
|
||||
{
|
||||
glw_state.context = SDL_GL_CreateContext( host.hWnd );
|
||||
|
||||
@@ -917,10 +917,10 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
|
||||
SDL_SetHint( SDL_HINT_VIDEO_X11_XRANDR, "1" );
|
||||
SDL_SetHint( SDL_HINT_VIDEO_X11_XVIDMODE, "1" );
|
||||
|
||||
glw_state.type = type;
|
||||
switch( type )
|
||||
{
|
||||
case REF_SOFTWARE:
|
||||
glw_state.software = true;
|
||||
break;
|
||||
case REF_GL:
|
||||
if( !glw_state.safe && Sys_GetParmFromCmdLine( "-safegl", safe ) )
|
||||
@@ -935,6 +935,8 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case REF_D3D:
|
||||
break;
|
||||
default:
|
||||
Host_Error( "Can't initialize unknown context type %d!\n", type );
|
||||
break;
|
||||
@@ -950,6 +952,7 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
|
||||
ref.dllFuncs.GL_InitExtensions();
|
||||
break;
|
||||
case REF_SOFTWARE:
|
||||
case REF_D3D:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ static qboolean VID_CreateWindow( const int input_width, const int input_height,
|
||||
SDL_Rect rect = { SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, input_width, input_height };
|
||||
Uint32 flags = SDL_WINDOW_RESIZABLE;
|
||||
|
||||
if( !glw_state.software )
|
||||
if( glw_state.type == REF_GL )
|
||||
SetBits( flags, SDL_WINDOW_OPENGL );
|
||||
|
||||
// probe true fullscreen first, if it fails, try borderless next
|
||||
@@ -168,12 +168,12 @@ static qboolean VID_CreateWindow( const int input_width, const int input_height,
|
||||
|
||||
VID_SetWindowIcon( host.hWnd );
|
||||
|
||||
if( glw_state.software )
|
||||
if( glw_state.type == REF_SOFTWARE )
|
||||
{
|
||||
// no support yet
|
||||
return false;
|
||||
}
|
||||
else
|
||||
else if ( glw_state.type == REF_GL )
|
||||
{
|
||||
glw_state.context = SDL_GL_CreateContext( host.hWnd );
|
||||
|
||||
@@ -337,10 +337,10 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
|
||||
if( Sys_CheckParm( "-egl" ))
|
||||
Con_Printf( S_WARN "%s: -egl option is deprecated\n", __func__ );
|
||||
|
||||
glw_state.type = type;
|
||||
switch( type )
|
||||
{
|
||||
case REF_SOFTWARE:
|
||||
glw_state.software = true;
|
||||
break;
|
||||
case REF_GL:
|
||||
{
|
||||
@@ -357,6 +357,8 @@ qboolean R_Init_Video( ref_graphic_apis_t type )
|
||||
|
||||
break;
|
||||
}
|
||||
case REF_D3D:
|
||||
break;
|
||||
default:
|
||||
Host_Error( "Can't initialize unknown context type %d!\n", type );
|
||||
break;
|
||||
|
||||
19
ref/dx2/dllmain.cpp
Normal file
19
ref/dx2/dllmain.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include "windows.h"
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
481
ref/dx2/r_context.c
Normal file
481
ref/dx2/r_context.c
Normal file
@@ -0,0 +1,481 @@
|
||||
/*
|
||||
r_context.c -- dx2 renderer context
|
||||
Copyright (C) 2023-2024 a1batross
|
||||
Copyright (C) 2025-2026 lewa_j
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#define INITGUID
|
||||
#include "r_local.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
#include "crtlib.h"
|
||||
#include "r_studioint.h"
|
||||
|
||||
//#pragma comment(lib, "ddraw.lib")
|
||||
//TODO COM_GetProcAddress
|
||||
|
||||
|
||||
static void R_SimpleStub( void )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static void R_SimpleStubInt( int unused )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static void R_SimpleStubUInt( unsigned int unused )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static const char *R_GetConfigName( void )
|
||||
{
|
||||
return "ref_dx2";
|
||||
}
|
||||
|
||||
static qboolean R_SetDisplayTransform( ref_screen_rotation_t rotate, int offset_x, int offset_y, float scale_x, float scale_y )
|
||||
{
|
||||
qboolean ret = true;
|
||||
|
||||
tr.rotation = rotate;
|
||||
|
||||
if( offset_x || offset_y )
|
||||
{
|
||||
gEngfuncs.Con_Printf("offset transform not supported\n");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
if( scale_x != 1.0f || scale_y != 1.0f )
|
||||
{
|
||||
gEngfuncs.Con_Printf("scale transform not supported\n");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GL_BackendStartFrame( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void GL_BackendEndFrame( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void GL_SetRenderMode( int mode )
|
||||
{
|
||||
dxc.renderMode = mode;
|
||||
}
|
||||
|
||||
|
||||
static void R_ProcessEntData( qboolean allocate, cl_entity_t *entities, unsigned int max_entities )
|
||||
{
|
||||
if (!allocate)
|
||||
{
|
||||
tr.draw_list->num_solid_entities = 0;
|
||||
tr.draw_list->num_trans_entities = 0;
|
||||
tr.draw_list->num_beam_entities = 0;
|
||||
|
||||
tr.max_entities = 0;
|
||||
tr.entities = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
tr.max_entities = max_entities;
|
||||
tr.entities = entities;
|
||||
}
|
||||
|
||||
if (gEngfuncs.drawFuncs->R_ProcessEntData)
|
||||
gEngfuncs.drawFuncs->R_ProcessEntData(allocate);
|
||||
}
|
||||
|
||||
static void R_SetupSky( int *skytextures )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static qboolean VID_ScreenShot( const char *filename, int shot_type )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qboolean skyshot )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static colorVec R_LightPoint( const float *p )
|
||||
{
|
||||
colorVec c = { 0 };
|
||||
return c;
|
||||
}
|
||||
|
||||
static void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static int R_CreateDecalList( struct decallist_s *pList )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static float R_StudioEstimateFrame( cl_entity_t *e, mstudioseqdesc_t *pseqdesc, double time )
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
static void R_StudioLerpMovement( cl_entity_t *e, double time, vec3_t origin, vec3_t angles )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static qboolean R_StudioFillAPI( struct engine_studio_api_s *api, struct r_studio_interface_s *pDefaultDraw )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static r_studio_interface_t *pStudioDraw;
|
||||
|
||||
static void R_StudioSetDrawInterface( struct r_studio_interface_s *pDraw )
|
||||
{
|
||||
pStudioDraw = pDraw;
|
||||
}
|
||||
|
||||
static void R_SetSkyCloudsTextures( int solidskyTexture, int alphaskyTexture )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static void CL_RunLightStyles( lightstyle_t *ls )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static qboolean Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buffer, size_t buffersize )
|
||||
{
|
||||
gEngfuncs.Con_Printf("Mod_ProcessRenderData(%p(%s), %d, %p, %zu)\n", mod, mod->name, create, buffer, buffersize);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Mod_StudioLoadTextures( model_t *mod, void *data )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static void CL_DrawParticles( double frametime, particle_t *particles, float partsize )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static void CL_DrawTracers( double frametime, particle_t *tracers )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static void CL_DrawBeams( int fTrans, BEAM *beams )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static intptr_t RefGetParm( int parm, int arg )
|
||||
{
|
||||
dx_texture_t *glt;
|
||||
|
||||
switch (parm)
|
||||
{
|
||||
case PARM_TEX_WIDTH:
|
||||
glt = R_GetTexture(arg);
|
||||
return glt->width;
|
||||
case PARM_TEX_HEIGHT:
|
||||
glt = R_GetTexture(arg);
|
||||
return glt->height;
|
||||
case PARM_TEX_SRC_WIDTH:
|
||||
glt = R_GetTexture(arg);
|
||||
return glt->srcWidth;
|
||||
case PARM_TEX_SRC_HEIGHT:
|
||||
glt = R_GetTexture(arg);
|
||||
return glt->srcHeight;
|
||||
case PARM_TEX_GLFORMAT:
|
||||
glt = R_GetTexture(arg);
|
||||
return 0;
|
||||
case PARM_TEX_ENCODE:
|
||||
glt = R_GetTexture(arg);
|
||||
return 0;
|
||||
case PARM_TEX_MIPCOUNT:
|
||||
glt = R_GetTexture(arg);
|
||||
return glt->numMips;
|
||||
case PARM_TEX_DEPTH:
|
||||
glt = R_GetTexture(arg);
|
||||
return 1;
|
||||
#if 0
|
||||
case PARM_TEX_SKYBOX:
|
||||
Assert(arg >= 0 && arg < 6);
|
||||
return tr.skyboxTextures[arg];
|
||||
#endif
|
||||
case PARM_TEX_SKYTEXNUM:
|
||||
return tr.skytexturenum;
|
||||
#if 0
|
||||
case PARM_TEX_LIGHTMAP:
|
||||
arg = bound(0, arg, MAX_LIGHTMAPS - 1);
|
||||
return tr.lightmapTextures[arg];
|
||||
#endif
|
||||
case PARM_TEX_TARGET:
|
||||
glt = R_GetTexture(arg);
|
||||
return 0;
|
||||
case PARM_TEX_TEXNUM:
|
||||
glt = R_GetTexture(arg);
|
||||
return arg;
|
||||
case PARM_TEX_FLAGS:
|
||||
glt = R_GetTexture(arg);
|
||||
return glt->flags;
|
||||
#if 0
|
||||
case PARM_TEX_MEMORY:
|
||||
return GL_TexMemory();
|
||||
case PARM_ACTIVE_TMU:
|
||||
return glState.activeTMU;
|
||||
#endif
|
||||
case PARM_LIGHTSTYLEVALUE:
|
||||
arg = bound(0, arg, MAX_LIGHTSTYLES - 1);
|
||||
return g_lightstylevalue[arg];
|
||||
#if 0
|
||||
case PARM_MAX_IMAGE_UNITS:
|
||||
return GL_MaxTextureUnits();
|
||||
case PARM_REBUILD_GAMMA:
|
||||
return glConfig.softwareGammaUpdate;
|
||||
case PARM_GL_CONTEXT_TYPE:
|
||||
return glConfig.context;
|
||||
case PARM_GLES_WRAPPER:
|
||||
return glConfig.wrapper;
|
||||
#endif
|
||||
case PARM_STENCIL_ACTIVE:
|
||||
return 0;//No stencil in dx2
|
||||
case PARM_TEX_FILTERING:
|
||||
return 0;
|
||||
#if 0
|
||||
if (arg < 0)
|
||||
return gl_texture_nearest.value == 0.0f;
|
||||
|
||||
return GL_TextureFilteringEnabled(R_GetTexture(arg));
|
||||
#endif
|
||||
case PARM_GET_STUDIO_HDR:
|
||||
//return (intptr_t)R_StudioGetHeader();
|
||||
return 0;
|
||||
default:
|
||||
return (*gEngfuncs.EngineGetParm)(parm, arg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void GL_Bind( int tmu, unsigned int texnum )
|
||||
{
|
||||
const dx_texture_t *texture;
|
||||
|
||||
// missed or invalid texture?
|
||||
if( texnum <= 0 || texnum >= MAX_TEXTURES )
|
||||
{
|
||||
if( texnum != 0 )
|
||||
gEngfuncs.Con_DPrintf( S_ERROR "%s: invalid texturenum %d\n", __func__, texnum );
|
||||
texnum = tr.defaultTexture;
|
||||
}
|
||||
|
||||
texture = R_GetTexture( texnum );
|
||||
|
||||
//if( dxc.currentTexture == texture->d3dHandle )
|
||||
// return;
|
||||
|
||||
dxc.currentTexture = texture->d3dHandle;
|
||||
}
|
||||
|
||||
static qboolean R_SpeedsMessage( char *out, size_t size )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static void R_NewMap( void )
|
||||
{
|
||||
tr.worldmodel = gp_cl->models[1];
|
||||
|
||||
// clear out efrags in case the level hasn't been reloaded
|
||||
for( int i = 0; i < tr.worldmodel->numleafs; i++ )
|
||||
tr.worldmodel->leafs[i+1].efrags = NULL;
|
||||
|
||||
tr.skytexturenum = -1;
|
||||
|
||||
// clearing texture chains
|
||||
for( int i = 0; i < tr.worldmodel->numtextures; i++ )
|
||||
{
|
||||
if( !tr.worldmodel->textures[i] )
|
||||
continue;
|
||||
|
||||
texture_t *tx = tr.worldmodel->textures[i];
|
||||
|
||||
if( !Q_strncmp( tx->name, "sky", 3 ) && tx->width == ( tx->height * 2 ))
|
||||
tr.skytexturenum = i;
|
||||
|
||||
tx->texturechain = NULL;
|
||||
}
|
||||
|
||||
GL_BuildLightmaps();
|
||||
|
||||
if( gEngfuncs.drawFuncs->R_NewMap != NULL )
|
||||
gEngfuncs.drawFuncs->R_NewMap();
|
||||
}
|
||||
|
||||
static void Color4f( float r, float g, float b, float a )
|
||||
{
|
||||
Vector4Set(dxc.currentColor, r, g, b, a);
|
||||
}
|
||||
|
||||
static void Color4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a )
|
||||
{
|
||||
Vector4Set(dxc.currentColor, r/255.f, g/255.f, b/255.f, a/255.f);
|
||||
}
|
||||
|
||||
static void Vertex3fv( const float *worldPnt )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static void Vertex3f( float x, float y, float z )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static void CullFace( TRICULLSTYLE mode )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static void VGUI_SetupDrawing( qboolean rect )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static void R_FillRenderAPI( render_api_t *api )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static void R_FillTriAPI( triangleapi_t *api )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
const ref_interface_t gReffuncs =
|
||||
{
|
||||
.R_Init = R_Init,
|
||||
.R_Shutdown = R_Shutdown,
|
||||
.R_GetConfigName = R_GetConfigName,
|
||||
.R_SetDisplayTransform = R_SetDisplayTransform,
|
||||
|
||||
.GL_SetupAttributes = GL_SetupAttributes,
|
||||
.GL_InitExtensions = GL_InitExtensions,
|
||||
.GL_ClearExtensions = GL_ClearExtensions,
|
||||
|
||||
.R_GammaChanged = R_GammaChanged,
|
||||
.R_BeginFrame = R_BeginFrame,
|
||||
.R_RenderScene = R_RenderScene,
|
||||
.R_EndFrame = R_EndFrame,
|
||||
.R_PushScene = R_SimpleStub,
|
||||
.R_PopScene = R_SimpleStub,
|
||||
.GL_BackendStartFrame = GL_BackendStartFrame,
|
||||
.GL_BackendEndFrame = GL_BackendEndFrame,
|
||||
|
||||
.R_ClearScreen = R_SimpleStub,
|
||||
.R_AllowFog = R_AllowFog,
|
||||
.GL_SetRenderMode = GL_SetRenderMode,
|
||||
|
||||
.R_AddEntity = R_AddEntity,
|
||||
.R_ProcessEntData = R_ProcessEntData,
|
||||
|
||||
.R_ShowTextures = R_ShowTextures,
|
||||
|
||||
.R_GetTextureOriginalBuffer = R_GetTextureOriginalBuffer,
|
||||
.GL_LoadTextureFromBuffer = GL_LoadTextureFromBuffer,
|
||||
.GL_ProcessTexture = GL_ProcessTexture,
|
||||
.R_SetupSky = R_SetupSky,
|
||||
|
||||
.R_Set2DMode = R_Set2DMode,
|
||||
.R_DrawStretchPic = R_DrawStretchPic,
|
||||
.FillRGBA = FillRGBA,
|
||||
.WorldToScreen = WorldToScreen,
|
||||
|
||||
.VID_ScreenShot = VID_ScreenShot,
|
||||
.VID_CubemapShot = VID_CubemapShot,
|
||||
|
||||
.R_LightPoint = R_LightPoint,
|
||||
|
||||
.R_DecalShoot = R_DecalShoot,
|
||||
.R_DecalRemoveAll = R_SimpleStubInt,
|
||||
.R_CreateDecalList = R_CreateDecalList,
|
||||
.R_ClearAllDecals = R_SimpleStub,
|
||||
|
||||
.R_StudioEstimateFrame = R_StudioEstimateFrame,
|
||||
.R_StudioLerpMovement = R_StudioLerpMovement,
|
||||
.R_StudioFillAPI = R_StudioFillAPI,
|
||||
.R_StudioSetDrawInterface = R_StudioSetDrawInterface,
|
||||
|
||||
.R_SetSkyCloudsTextures = R_SetSkyCloudsTextures,
|
||||
.GL_SubdivideSurface = GL_SubdivideSurface,
|
||||
.CL_RunLightStyles = CL_RunLightStyles,
|
||||
|
||||
.Mod_ProcessRenderData = Mod_ProcessRenderData,
|
||||
.Mod_StudioLoadTextures = Mod_StudioLoadTextures,
|
||||
|
||||
.CL_DrawParticles = CL_DrawParticles,
|
||||
.CL_DrawTracers = CL_DrawTracers,
|
||||
.CL_DrawBeams = CL_DrawBeams,
|
||||
|
||||
.RefGetParm = RefGetParm,
|
||||
|
||||
.R_GetDetailScaleForTexture = R_GetDetailScaleForTexture,
|
||||
.R_SetDetailScaleForTexture = R_SetDetailScaleForTexture,
|
||||
|
||||
.GL_CreateTexture = GL_CreateTexture,
|
||||
.GL_FindTexture = GL_FindTexture,
|
||||
.GL_TextureName = GL_TextureName,
|
||||
.GL_TextureData = GL_TextureData,
|
||||
.GL_LoadTexture = GL_LoadTexture,
|
||||
.GL_FreeTexture = GL_FreeTexture,
|
||||
.R_OverrideTextureSourceSize = R_OverrideTextureSourceSize,
|
||||
.GL_UpdateTexture = GL_UpdateTexture,
|
||||
|
||||
.GL_Bind = GL_Bind,
|
||||
|
||||
.GL_RenderFrame = R_RenderFrame,
|
||||
.GL_OrthoBounds = GL_OrthoBounds,
|
||||
.R_SpeedsMessage = R_SpeedsMessage,
|
||||
.Mod_GetCurrentVis = Mod_GetCurrentVis,
|
||||
.R_NewMap = R_NewMap,
|
||||
.R_ClearScene = R_ClearScene,
|
||||
|
||||
.TriRenderMode = R_SimpleStubInt,
|
||||
.Begin = R_SimpleStubInt,
|
||||
.End = R_SimpleStub,
|
||||
.Color4f = Color4f,
|
||||
.Color4ub = Color4ub,
|
||||
.Vertex3fv = Vertex3fv,
|
||||
.Vertex3f = Vertex3f,
|
||||
.CullFace = CullFace,
|
||||
|
||||
.R_FillRenderAPI = R_FillRenderAPI,
|
||||
.R_FillTriAPI = R_FillTriAPI,
|
||||
|
||||
.VGUI_SetupDrawing = VGUI_SetupDrawing,
|
||||
};
|
||||
|
||||
559
ref/dx2/r_d3d.c
Normal file
559
ref/dx2/r_d3d.c
Normal file
@@ -0,0 +1,559 @@
|
||||
/*
|
||||
r_d3d.c -- dx2 renderer d3d related code
|
||||
Copyright (C) 2025-2026 lewa_j
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "r_local.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
|
||||
CVAR_DEFINE_AUTO( r_novis, "0", 0, "ignore vis information (perfomance test)" );
|
||||
CVAR_DEFINE_AUTO( r_nocull, "0", 0, "ignore frustrum culling (perfomance test)" );
|
||||
CVAR_DEFINE_AUTO( r_lockpvs, "0", FCVAR_CHEAT, "lockpvs area at current point (pvs test)" );
|
||||
CVAR_DEFINE_AUTO( r_lockfrustum, "0", FCVAR_CHEAT, "lock frustrum area at current point (cull test)" );
|
||||
|
||||
dx_globals_t tr;
|
||||
dx_context_t dxc;
|
||||
|
||||
const char *dxResultToStr( HRESULT r )
|
||||
{
|
||||
if( r == DD_OK )
|
||||
return "DD_OK";
|
||||
if( r == DDERR_INVALIDPARAMS )
|
||||
return "DDERR_INVALIDPARAMS";
|
||||
if( r == DDERR_INVALIDOBJECT )
|
||||
return "DDERR_INVALIDOBJECT";
|
||||
if( r == DDERR_UNSUPPORTED )
|
||||
return "DDERR_UNSUPPORTED";
|
||||
if( r == DDERR_NOCOOPERATIVELEVELSET )
|
||||
return "DDERR_NOCOOPERATIVELEVELSET";
|
||||
if( r == DDERR_INVALIDCAPS )
|
||||
return "DDERR_INVALIDCAPS";
|
||||
if( r == DDERR_INCOMPATIBLEPRIMARY )
|
||||
return "DDERR_INCOMPATIBLEPRIMARY";
|
||||
if( r == DDERR_NOEXCLUSIVEMODE )
|
||||
return "DDERR_NOEXCLUSIVEMODE";
|
||||
if( r == DDERR_NOFLIPHW )
|
||||
return "DDERR_NOFLIPHW";
|
||||
if( r == DDERR_OUTOFVIDEOMEMORY )
|
||||
return "DDERR_OUTOFVIDEOMEMORY";
|
||||
if( r == DDERR_PRIMARYSURFACEALREADYEXISTS )
|
||||
return "DDERR_PRIMARYSURFACEALREADYEXISTS";
|
||||
if( r == DDERR_UNSUPPORTEDMODE )
|
||||
return "DDERR_UNSUPPORTEDMODE";
|
||||
if( r == DDERR_NOTFOUND )
|
||||
return "DDERR_NOTFOUND";
|
||||
if( r == DDERR_INVALIDRECT )
|
||||
return "DDERR_INVALIDRECT";
|
||||
|
||||
if( r == D3DERR_VIEWPORTDATANOTSET )
|
||||
return "D3DERR_VIEWPORTDATANOTSET";
|
||||
if( r == D3DERR_VIEWPORTHASNODEVICE )
|
||||
return "D3DERR_VIEWPORTHASNODEVICE";
|
||||
if( r == D3DERR_SURFACENOTINVIDMEM )
|
||||
return "D3DERR_SURFACENOTINVIDMEM";
|
||||
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static qboolean DD_CreatePrimarySurface( void )
|
||||
{
|
||||
DDSURFACEDESC ddsd = { 0 };
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_CAPS;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
||||
|
||||
DXCheck(IDirectDraw_CreateSurface(dxc.pdd, &ddsd, &dxc.pddsPrimary, NULL));
|
||||
printf("IDirectDraw::CreateSurface(PRIMARY) %p\n", dxc.pddsPrimary);
|
||||
if (!dxc.pddsPrimary)
|
||||
return false;
|
||||
|
||||
DXCheck(IDirectDraw_CreateClipper(dxc.pdd, 0, &dxc.pddClipper, NULL));
|
||||
gEngfuncs.Con_Printf("IDirectDraw::CreateClipper %p\n", dxc.pddClipper);
|
||||
if (!dxc.pddClipper)
|
||||
return false;
|
||||
|
||||
DXCheck(IDirectDrawClipper_SetHWnd(dxc.pddClipper, 0, dxc.window));
|
||||
DXCheck(IDirectDrawSurface_SetClipper(dxc.pddsPrimary, dxc.pddClipper));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static qboolean DD_CreateBackSurface( void )
|
||||
{
|
||||
DDCAPS ddcaps =
|
||||
{
|
||||
.dwSize = sizeof(ddcaps)
|
||||
};
|
||||
DDCAPS helcaps =
|
||||
{
|
||||
.dwSize = sizeof(helcaps)
|
||||
};
|
||||
DXCheck(IDirectDraw_GetCaps(dxc.pdd, &ddcaps, &helcaps));
|
||||
gEngfuncs.Con_Printf("IDirectDraw::GetCaps\n");
|
||||
gEngfuncs.Con_Printf("ZBUFFER: %s\n", (ddcaps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) ? "- ^2enabled" : "- ^1failed");
|
||||
if (ddcaps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
|
||||
gEngfuncs.Con_Printf("ZBufferBitDepths: 0x%X\n", ddcaps.dwZBufferBitDepths);
|
||||
if (helcaps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
|
||||
gEngfuncs.Con_Printf("HEL ZBufferBitDepths: 0x%X\n", helcaps.dwZBufferBitDepths);
|
||||
|
||||
DDSURFACEDESC ddsd = { 0 };
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY;
|
||||
ddsd.dwWidth = dxc.windowWidth;
|
||||
ddsd.dwHeight = dxc.windowHeight;
|
||||
|
||||
DXCheck(IDirectDraw_CreateSurface(dxc.pdd, &ddsd, &dxc.pddsBack, NULL));
|
||||
gEngfuncs.Con_Printf("IDirectDraw::CreateSurface(BACK) %p\n", dxc.pddsBack);
|
||||
if (!dxc.pddsBack)
|
||||
return false;
|
||||
|
||||
DXCheck(IDirectDraw_CreateClipper(dxc.pdd, 0, &dxc.pddBackClipper, NULL));
|
||||
gEngfuncs.Con_Printf("IDirectDraw::CreateClipper(BACK) %p\n", dxc.pddBackClipper);
|
||||
if (!dxc.pddBackClipper)
|
||||
return false;
|
||||
|
||||
struct region_t
|
||||
{
|
||||
RGNDATAHEADER rdh;
|
||||
RECT rect;
|
||||
} region;
|
||||
region.rdh.dwSize = sizeof(region.rdh);
|
||||
region.rdh.iType = RDH_RECTANGLES;
|
||||
region.rdh.nCount = 1;
|
||||
region.rdh.nRgnSize = sizeof(RECT);
|
||||
region.rdh.rcBound.left = 0;
|
||||
region.rdh.rcBound.top = 0;
|
||||
region.rdh.rcBound.right = dxc.windowWidth;
|
||||
region.rdh.rcBound.bottom = dxc.windowHeight;
|
||||
memcpy(®ion.rect, ®ion.rdh.rcBound, sizeof(region.rdh.rcBound));
|
||||
|
||||
DXCheck(IDirectDrawClipper_SetClipList(dxc.pddBackClipper, (RGNDATA *)®ion, 0));
|
||||
DXCheck(IDirectDrawSurface_SetClipper(dxc.pddsBack, dxc.pddBackClipper));
|
||||
|
||||
int bitDepths = ddcaps.dwZBufferBitDepths;
|
||||
if (!bitDepths)
|
||||
bitDepths = helcaps.dwZBufferBitDepths;
|
||||
if( (ddcaps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && bitDepths )
|
||||
{
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_ZBUFFERBITDEPTH;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
|
||||
ddsd.dwWidth = dxc.windowWidth;
|
||||
ddsd.dwHeight = dxc.windowHeight;
|
||||
ddsd.dwZBufferBitDepth = 16;
|
||||
if(bitDepths & DDBD_16 )
|
||||
ddsd.dwZBufferBitDepth = 16;
|
||||
else if(bitDepths & DDBD_24 )
|
||||
ddsd.dwZBufferBitDepth = 24;
|
||||
else if(bitDepths & DDBD_32 )
|
||||
ddsd.dwZBufferBitDepth = 32;
|
||||
DXCheck(IDirectDraw_CreateSurface(dxc.pdd, &ddsd, &dxc.pddsZBuffer, NULL));
|
||||
gEngfuncs.Con_Printf("IDirectDraw::CreateSurface(ZBUFFER %dbit) %p\n", ddsd.dwZBufferBitDepth, dxc.pddsZBuffer);
|
||||
if( !dxc.pddsZBuffer )
|
||||
return false;
|
||||
DXCheck(IDirectDrawSurface_AddAttachedSurface(dxc.pddsBack, dxc.pddsZBuffer));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static qboolean D3D_Init( void )
|
||||
{
|
||||
DXCheck(IDirectDraw_QueryInterface(dxc.pdd, &IID_IDirect3D, (void**)&dxc.pd3d));
|
||||
gEngfuncs.Con_Printf("IDirectDraw::QueryInterface(IID_IDirect3D) %p\n", dxc.pd3d);
|
||||
|
||||
if( !dxc.pd3d )
|
||||
return false;
|
||||
|
||||
DXCheck(IDirect3D_CreateViewport(dxc.pd3d, &dxc.viewport, NULL));
|
||||
gEngfuncs.Con_Printf("IDirect3D::CreateViewport %p\n", dxc.viewport);
|
||||
|
||||
if( !dxc.viewport )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static qboolean D3D_InitDevice( void )
|
||||
{
|
||||
if( !dxc.pd3d )
|
||||
return false;
|
||||
|
||||
D3DFINDDEVICESEARCH search = { 0 };
|
||||
memset(&search, 0, sizeof(search));
|
||||
search.dwSize = sizeof(search);
|
||||
search.dwFlags = D3DFDS_COLORMODEL;
|
||||
search.dcmColorModel = D3DCOLOR_RGB;
|
||||
#if 0
|
||||
search.dwFlags |= D3DFDS_HARDWARE;
|
||||
search.bHardware = FALSE;
|
||||
#endif
|
||||
D3DFINDDEVICERESULT result = { 0 };
|
||||
memset(&result, 0, sizeof(result));
|
||||
result.dwSize = sizeof(result);
|
||||
|
||||
DXCheck(IDirect3D_FindDevice(dxc.pd3d, &search, &result));
|
||||
DXCheck(IDirectDrawSurface_QueryInterface(dxc.pddsBack, &result.guid, (void**)&dxc.pd3dd));
|
||||
gEngfuncs.Con_Printf("IDirectDrawSurface::QueryInterface(IDirect3DDevice) %p\n", dxc.pd3dd);
|
||||
gEngfuncs.Con_Printf("DeviceZBufferBitDepth: 0x%X\n", result.ddHwDesc.dwDeviceZBufferBitDepth);
|
||||
gEngfuncs.Con_Printf("SW DeviceZBufferBitDepth: 0x%X\n", result.ddSwDesc.dwDeviceZBufferBitDepth);
|
||||
|
||||
if( !dxc.pd3dd )
|
||||
return false;
|
||||
|
||||
D3DDEVICEDESC d3ddesc =
|
||||
{
|
||||
.dwSize = sizeof(d3ddesc)
|
||||
};
|
||||
D3DDEVICEDESC held3ddesc =
|
||||
{
|
||||
.dwSize = sizeof(held3ddesc)
|
||||
};
|
||||
DXCheck(IDirect3DDevice_GetCaps(dxc.pd3dd, &d3ddesc, &held3ddesc));
|
||||
gEngfuncs.Con_Printf("IDirect3DDevice::GetCaps\n");
|
||||
gEngfuncs.Con_Printf("DeviceZBufferBitDepth: 0x%X\n", result.ddHwDesc.dwDeviceZBufferBitDepth);
|
||||
gEngfuncs.Con_Printf("HEL DeviceZBufferBitDepth: 0x%X\n", result.ddSwDesc.dwDeviceZBufferBitDepth);
|
||||
|
||||
D3DEXECUTEBUFFERDESC ebd = { 0 };
|
||||
memset(&ebd, 0, sizeof(ebd));
|
||||
ebd.dwSize = sizeof(ebd);
|
||||
ebd.dwFlags = D3DDEB_BUFSIZE;
|
||||
ebd.dwBufferSize = 1024 * 64;
|
||||
DXCheck(IDirect3DDevice_CreateExecuteBuffer(dxc.pd3dd, &ebd, &dxc.pd3deb, NULL));
|
||||
gEngfuncs.Con_Printf("IDirect3DDevice::CreateExecuteBuffer %p\n", dxc.pd3deb);
|
||||
|
||||
if (!dxc.pd3deb)
|
||||
return false;
|
||||
|
||||
if (!dxc.viewport)
|
||||
return false;
|
||||
|
||||
DXCheck(IDirect3DDevice_AddViewport(dxc.pd3dd, dxc.viewport));
|
||||
|
||||
DDSURFACEDESC desc = { 0 };
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.dwSize = sizeof(desc);
|
||||
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
|
||||
DXCheck(IDirectDrawSurface_GetSurfaceDesc(dxc.pddsBack, &desc));
|
||||
|
||||
D3DVIEWPORT viewport = { 0 };
|
||||
viewport.dwSize = sizeof(viewport);
|
||||
viewport.dwX = 0;
|
||||
viewport.dwY = 0;
|
||||
viewport.dwWidth = desc.dwWidth;
|
||||
viewport.dwHeight = desc.dwHeight;
|
||||
viewport.dvScaleX = 0.5 * viewport.dwWidth;
|
||||
viewport.dvScaleY = 0.5f * viewport.dwHeight;
|
||||
viewport.dvMaxX = 1;
|
||||
viewport.dvMaxY = 1;
|
||||
viewport.dvMinZ = 0;
|
||||
viewport.dvMaxZ = 1;
|
||||
DXCheck(IDirect3DViewport_SetViewport(dxc.viewport, &viewport));
|
||||
|
||||
DXCheck(IDirect3DDevice_CreateMatrix(dxc.pd3dd, &dxc.mtxWorld));
|
||||
DXCheck(IDirect3DDevice_CreateMatrix(dxc.pd3dd, &dxc.mtxProjection));
|
||||
|
||||
//set transform state
|
||||
{
|
||||
d3dEBContext_t ebc = { 0 };
|
||||
if (!D3D_StartExecuteBuffer(&ebc))
|
||||
return false;
|
||||
void *cur = ebc.data;
|
||||
|
||||
D3D_PutInstruction(&cur, D3DOP_STATETRANSFORM, sizeof(D3DSTATE), 2);
|
||||
D3D_PutTransformState(&cur, D3DTRANSFORMSTATE_WORLD, dxc.mtxWorld);
|
||||
D3D_PutTransformState(&cur, D3DTRANSFORMSTATE_PROJECTION, dxc.mtxProjection);
|
||||
|
||||
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 2);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZENABLE, FALSE);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZWRITEENABLE, FALSE);
|
||||
|
||||
D3D_PutInstruction(&cur, D3DOP_EXIT, 0, 0);
|
||||
|
||||
ebc.vertCount = 0;
|
||||
ebc.insOffset = 0;
|
||||
ebc.insLength = ((char *)cur - (char *)ebc.data);
|
||||
|
||||
if (!D3D_EndExecuteBuffer(&ebc))
|
||||
return false;
|
||||
|
||||
DXCheck(IDirect3DDevice_BeginScene(dxc.pd3dd));
|
||||
DXCheck(IDirect3DDevice_Execute(dxc.pd3dd, ebc.pd3deb, dxc.viewport, D3DEXECUTE_CLIPPED));
|
||||
DXCheck(IDirect3DDevice_EndScene(dxc.pd3dd));
|
||||
|
||||
D3D_ReleaseExecuteBuffer(&ebc);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
qboolean R_Init( void )
|
||||
{
|
||||
memset(&dxc, 0, sizeof(dxc));
|
||||
|
||||
gEngfuncs.Cvar_RegisterVariable( &r_novis );
|
||||
gEngfuncs.Cvar_RegisterVariable( &r_nocull );
|
||||
gEngfuncs.Cvar_RegisterVariable( &r_lockpvs );
|
||||
gEngfuncs.Cvar_RegisterVariable( &r_lockfrustum );
|
||||
|
||||
// init draw stack
|
||||
tr.draw_list = &tr.draw_stack[0];
|
||||
tr.draw_stack_pos = 0;
|
||||
|
||||
r_temppool = Mem_AllocPool("Render Zone");
|
||||
|
||||
// create the window
|
||||
if (!gEngfuncs.R_Init_Video(REF_D3D))
|
||||
{
|
||||
Mem_FreePool(&r_temppool);
|
||||
return false;
|
||||
}
|
||||
|
||||
void *handle = NULL;
|
||||
ref_window_type_t wt = gEngfuncs.R_GetWindowHandle( &handle, REF_WINDOW_TYPE_WIN32 );
|
||||
gEngfuncs.Con_Printf( "R_Init: WindowHandle %p type %d\n", handle, wt );
|
||||
if (wt != REF_WINDOW_TYPE_WIN32 || !handle)
|
||||
{
|
||||
Mem_FreePool(&r_temppool);
|
||||
return false;
|
||||
}
|
||||
dxc.window = (HWND)handle;
|
||||
|
||||
RECT dstRect = { 0 };
|
||||
GetClientRect(dxc.window, &dstRect);
|
||||
dxc.windowWidth = dstRect.right - dstRect.left;
|
||||
dxc.windowHeight = dstRect.bottom - dstRect.top;
|
||||
|
||||
DXCheck(DirectDrawCreate(NULL, &dxc.pdd, NULL));
|
||||
gEngfuncs.Con_Reportf("DirectDrawCreate %p\n", dxc.pdd);
|
||||
if (!dxc.pdd)
|
||||
{
|
||||
Mem_FreePool(&r_temppool);
|
||||
return false;
|
||||
}
|
||||
|
||||
DXCheck(IDirectDraw_SetCooperativeLevel(dxc.pdd, dxc.window, DDSCL_NORMAL));
|
||||
|
||||
if (!DD_CreatePrimarySurface())
|
||||
{
|
||||
Mem_FreePool(&r_temppool);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DD_CreateBackSurface())
|
||||
{
|
||||
Mem_FreePool(&r_temppool);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!D3D_Init())
|
||||
{
|
||||
Mem_FreePool(&r_temppool);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!D3D_InitDevice())
|
||||
{
|
||||
Mem_FreePool(&r_temppool);
|
||||
return false;
|
||||
}
|
||||
|
||||
// see R_ProcessEntData for tr.entities initialization
|
||||
tr.world = (struct world_static_s *)ENGINE_GET_PARM( PARM_GET_WORLD_PTR );
|
||||
tr.viewent = (cl_entity_t *)ENGINE_GET_PARM( PARM_GET_VIEWENT_PTR );
|
||||
|
||||
dxc.renderMode = kRenderNormal;
|
||||
Vector4Set(dxc.currentColor, 1, 1, 1, 1);
|
||||
|
||||
R_InitImages();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void R_Shutdown( void )
|
||||
{
|
||||
gEngfuncs.Con_Printf("ref: R_Shutdown()\n");
|
||||
|
||||
Mem_FreePool(&r_temppool);
|
||||
|
||||
gEngfuncs.R_Free_Video();
|
||||
}
|
||||
|
||||
void D3D_Resize( int width, int height )
|
||||
{
|
||||
dxc.windowWidth = width;
|
||||
dxc.windowHeight = height;
|
||||
|
||||
if( dxc.pd3deb )
|
||||
IDirect3DExecuteBuffer_Release(dxc.pd3deb);
|
||||
dxc.pd3deb = NULL;
|
||||
if( dxc.pd3dd )
|
||||
IDirect3DDevice_Release(dxc.pd3dd);
|
||||
dxc.pd3dd = NULL;
|
||||
if( dxc.pddsBack )
|
||||
IDirectDrawSurface_Release(dxc.pddsBack);
|
||||
dxc.pddsBack = NULL;
|
||||
if( dxc.pddsZBuffer )
|
||||
IDirectDrawSurface_Release(dxc.pddsZBuffer);
|
||||
dxc.pddsZBuffer = NULL;
|
||||
if( dxc.pddBackClipper )
|
||||
IDirectDrawClipper_Release(dxc.pddBackClipper);
|
||||
dxc.pddBackClipper = NULL;
|
||||
if( DD_CreateBackSurface() )
|
||||
{
|
||||
if( D3D_InitDevice() )
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GL_SetupAttributes( int safegl )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void GL_InitExtensions( void )
|
||||
{
|
||||
tr.framecount = tr.visframecount = 1;
|
||||
}
|
||||
|
||||
void GL_ClearExtensions( void )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
#define DX2_CREATE_EB 0
|
||||
|
||||
qboolean D3D_StartExecuteBuffer( d3dEBContext_t *ctx )
|
||||
{
|
||||
#if DX2_CREATE_EB
|
||||
ctx->pd3deb = NULL;
|
||||
D3DEXECUTEBUFFERDESC ebd = { 0 };
|
||||
memset(&ebd, 0, sizeof(ebd));
|
||||
ebd.dwSize = sizeof(ebd);
|
||||
ebd.dwFlags = D3DDEB_BUFSIZE;
|
||||
ebd.dwBufferSize = 512;
|
||||
DXCheck(IDirect3DDevice_CreateExecuteBuffer(dxc.pd3dd, &ebd, &ctx->pd3deb, NULL));
|
||||
#else
|
||||
ctx->pd3deb = dxc.pd3deb;
|
||||
#endif
|
||||
|
||||
if (!ctx->pd3deb)
|
||||
return false;
|
||||
|
||||
D3DEXECUTEBUFFERDESC ebDesc = { 0 };
|
||||
memset(&ebDesc, 0, sizeof(ebDesc));
|
||||
ebDesc.dwSize = sizeof(ebDesc);
|
||||
ebDesc.dwFlags = D3DDEB_LPDATA;
|
||||
HRESULT r = D3D_OK;
|
||||
DXCheckRet(r, IDirect3DExecuteBuffer_Lock(ctx->pd3deb, &ebDesc));
|
||||
if (r != D3D_OK)
|
||||
return false;
|
||||
|
||||
//gEngfuncs.Con_Printf("IDirect3DExecuteBuffer_Lock size %lu data %p\n", ebDesc.dwBufferSize, ebDesc.lpData);
|
||||
|
||||
ctx->bufferSize = ebDesc.dwBufferSize;
|
||||
ctx->data = ebDesc.lpData;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
qboolean D3D_EndExecuteBuffer( d3dEBContext_t *ctx )
|
||||
{
|
||||
HRESULT r = D3D_OK;
|
||||
DXCheckRet(r, IDirect3DExecuteBuffer_Unlock(ctx->pd3deb));
|
||||
if( r != D3D_OK )
|
||||
return false;
|
||||
|
||||
D3DEXECUTEDATA exData = { 0 };
|
||||
memset(&exData, 0, sizeof(exData));
|
||||
exData.dwSize = sizeof(exData);
|
||||
exData.dwVertexCount = ctx->vertCount;
|
||||
exData.dwVertexOffset = 0;
|
||||
exData.dwInstructionOffset = ctx->insOffset;
|
||||
exData.dwInstructionLength = ctx->insLength;
|
||||
DXCheckRet(r, IDirect3DExecuteBuffer_SetExecuteData(ctx->pd3deb, &exData));
|
||||
|
||||
return r == D3D_OK;
|
||||
}
|
||||
|
||||
void D3D_ReleaseExecuteBuffer( d3dEBContext_t *ctx )
|
||||
{
|
||||
#if DX2_CREATE_EB
|
||||
if( ctx->pd3deb && ctx->pd3deb != dxc.pd3deb )
|
||||
IDirect3DExecuteBuffer_Release( ctx->pd3deb );
|
||||
#endif
|
||||
}
|
||||
|
||||
void D3D_SetVertTL( D3DTLVERTEX* v, float x, float y, float z, float w, float tu, float tv )
|
||||
{
|
||||
v->sx = x;
|
||||
v->sy = y;
|
||||
v->sz = z;
|
||||
v->rhw = w;
|
||||
//v->color = RGBA_MAKE(250, 10, 10, 255);
|
||||
v->tu = tu;
|
||||
v->tv = tv;
|
||||
}
|
||||
|
||||
void D3D_SetTri( D3DTRIANGLE *t, int v1, int v2, int v3 )
|
||||
{
|
||||
t->v1 = v1;
|
||||
t->v2 = v2;
|
||||
t->v3 = v3;
|
||||
t->wFlags = D3DTRIFLAG_EDGEENABLETRIANGLE;
|
||||
}
|
||||
|
||||
void D3D_PutInstruction( void **dst, BYTE opcode, BYTE size, WORD count )
|
||||
{
|
||||
D3DINSTRUCTION* inst = (D3DINSTRUCTION*)*dst;
|
||||
inst->bOpcode = opcode;
|
||||
inst->bSize = size;
|
||||
inst->wCount = count;
|
||||
*dst = (void*)(((D3DINSTRUCTION*)*dst) + 1);
|
||||
}
|
||||
|
||||
void D3D_PutProcessVertices( void** dst, DWORD flags, WORD start, WORD count )
|
||||
{
|
||||
D3D_PutInstruction(dst, D3DOP_PROCESSVERTICES, sizeof(D3DPROCESSVERTICES), 1);
|
||||
|
||||
D3DPROCESSVERTICES* pv = (D3DPROCESSVERTICES*)*dst;
|
||||
pv->dwFlags = flags;
|
||||
pv->wStart = start;
|
||||
pv->wDest = start;
|
||||
pv->dwCount = count;
|
||||
pv->dwReserved = 0;
|
||||
*dst = (void*)(((D3DPROCESSVERTICES*)*dst) + 1);
|
||||
}
|
||||
|
||||
void D3D_PutRenderState( void** dst, D3DRENDERSTATETYPE type, DWORD arg )
|
||||
{
|
||||
D3DSTATE* s = (D3DSTATE*)*dst;
|
||||
|
||||
s->drstRenderStateType = type;
|
||||
s->dwArg[0] = arg;
|
||||
*dst = (void*)(((D3DSTATE*)*dst) + 1);
|
||||
}
|
||||
|
||||
void D3D_PutTransformState( void** dst, D3DTRANSFORMSTATETYPE type, DWORD arg )
|
||||
{
|
||||
D3DSTATE* s = (D3DSTATE*)*dst;
|
||||
|
||||
s->dtstTransformStateType = type;
|
||||
s->dwArg[0] = arg;
|
||||
*dst = (void*)(((D3DSTATE*)*dst) + 1);
|
||||
}
|
||||
204
ref/dx2/r_draw.c
Normal file
204
ref/dx2/r_draw.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
r_draw.c -- dx2 2D drawing
|
||||
Copyright (C) 2025-2026 lewa_j
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "r_local.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
|
||||
void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum )
|
||||
{
|
||||
if (texnum <= 0 || texnum >= MAX_TEXTURES)
|
||||
return;
|
||||
|
||||
dx_texture_t *tex = R_GetTexture(texnum);
|
||||
if (!tex->dds)
|
||||
return;
|
||||
|
||||
#if 0
|
||||
RECT dstRect = { x, y, x + w, y + h };
|
||||
RECT srcRect = { s1 * tex->width, t1 * tex->height, s2 * tex->width, t2 * tex->height};
|
||||
|
||||
if (dxc.renderMode == kRenderNormal)
|
||||
{
|
||||
DXCheck(IDirectDrawSurface_Blt(dxc.pddsBack, &dstRect, tex->dds, &srcRect, DDBLT_WAIT, NULL));
|
||||
}
|
||||
else
|
||||
{
|
||||
DDCOLORKEY ddck;
|
||||
ddck.dwColorSpaceLowValue = 0;
|
||||
ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue;
|
||||
DXCheck(IDirectDrawSurface_SetColorKey(tex->dds, DDCKEY_SRCBLT, &ddck));
|
||||
|
||||
DXCheck(IDirectDrawSurface_Blt(dxc.pddsBack, &dstRect, tex->dds, &srcRect, DDBLT_WAIT | DDBLT_KEYSRC, NULL));
|
||||
}
|
||||
#else
|
||||
|
||||
if (!dxc.pd3dd)
|
||||
return;
|
||||
|
||||
d3dEBContext_t ebc = { 0 };
|
||||
{
|
||||
if( !D3D_StartExecuteBuffer( &ebc ))
|
||||
return;
|
||||
|
||||
void *cur = ebc.data;
|
||||
|
||||
const int vertCount = 4;
|
||||
D3DTLVERTEX* verts = (D3DTLVERTEX*)cur;
|
||||
|
||||
// fix for half coordinate pixel centers in d3d compared to gl
|
||||
x -= 0.5;
|
||||
y -= 0.5;
|
||||
|
||||
#define VecToD3DCOLOR(v) D3DRGBA(v[0], v[1], v[2], v[3])
|
||||
|
||||
verts[0].color = VecToD3DCOLOR(dxc.currentColor);
|
||||
D3D_SetVertTL(verts, x, y, 0.5, 1, s1, t1);
|
||||
verts[1].color = verts[0].color;
|
||||
D3D_SetVertTL(verts + 1, x + w, y, 0.5, 1, s2, t1);
|
||||
verts[2].color = verts[0].color;
|
||||
D3D_SetVertTL(verts + 2, x + w, y + h, 0.5, 1, s2, t2);
|
||||
verts[3].color = verts[0].color;
|
||||
D3D_SetVertTL(verts + 3, x, y + h, 0.5, 1, s1, t2);
|
||||
|
||||
cur = (void*)(((D3DTLVERTEX*)cur) + vertCount);
|
||||
|
||||
void* insStart = cur;
|
||||
|
||||
D3D_PutProcessVertices(&cur, D3DPROCESSVERTICES_COPY | D3DPROCESSVERTICES_UPDATEEXTENTS, 0, vertCount);
|
||||
|
||||
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 3);
|
||||
// TODO disable when == tr.whiteTexture
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_TEXTUREHANDLE, tex->d3dHandle);
|
||||
//D3D_PutRenderState(&cur, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_DECAL);
|
||||
|
||||
if (dxc.renderMode == kRenderTransAlpha)
|
||||
{
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_BLENDENABLE, FALSE);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
|
||||
}
|
||||
else if (dxc.renderMode == kRenderGlow ||
|
||||
dxc.renderMode == kRenderTransAdd)
|
||||
{
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_BLENDENABLE, TRUE);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
|
||||
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 2);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE);
|
||||
}
|
||||
else if (dxc.renderMode == kRenderTransColor || dxc.renderMode == kRenderTransTexture)
|
||||
{
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_BLENDENABLE, TRUE);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
|
||||
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 2);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
}
|
||||
else// if (dxc.renderMode == kRenderNormal)
|
||||
{
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_BLENDENABLE, FALSE);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
|
||||
}
|
||||
|
||||
// align
|
||||
if (((ULONG)cur) & 7) {
|
||||
D3D_PutInstruction(&cur, D3DOP_TRIANGLE, sizeof(D3DTRIANGLE), 0);
|
||||
}
|
||||
|
||||
D3D_PutInstruction(&cur, D3DOP_TRIANGLE, sizeof(D3DTRIANGLE), 2);
|
||||
|
||||
D3DTRIANGLE* tris = (D3DTRIANGLE*)cur;
|
||||
D3D_SetTri(tris, 0, 1, 2);
|
||||
D3D_SetTri(tris + 1, 0, 2, 3);
|
||||
cur = (void*)(((D3DTRIANGLE*)cur) + 2);
|
||||
|
||||
D3D_PutInstruction(&cur, D3DOP_EXIT, 0, 0);
|
||||
|
||||
ebc.vertCount = 4;
|
||||
ebc.insOffset = ((char*)insStart - (char*)ebc.data);
|
||||
ebc.insLength = ((char*)cur - (char*)insStart);
|
||||
|
||||
if( !D3D_EndExecuteBuffer( &ebc ))
|
||||
return;
|
||||
}
|
||||
|
||||
DXCheck(IDirect3DDevice_BeginScene(dxc.pd3dd));
|
||||
DXCheck(IDirect3DDevice_Execute(dxc.pd3dd, ebc.pd3deb, dxc.viewport, D3DEXECUTE_CLIPPED));
|
||||
DXCheck(IDirect3DDevice_EndScene(dxc.pd3dd));
|
||||
|
||||
D3D_ReleaseExecuteBuffer( &ebc );
|
||||
#endif
|
||||
}
|
||||
|
||||
void FillRGBA( int rendermode, float x, float y, float w, float h, byte r, byte g, byte b, byte a )
|
||||
{
|
||||
#if 0
|
||||
RECT dstRect = { x, y, x + w, y + h };
|
||||
DDBLTFX bltFx = { 0 };
|
||||
bltFx.dwSize = sizeof(bltFx);
|
||||
bltFx.dwFillColor = RGBA_MAKE(r, g, b, a);
|
||||
DXCheck(IDirectDrawSurface_Blt(dxc.pddsBack, &dstRect, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &bltFx));
|
||||
#else
|
||||
// TODO Restore after?
|
||||
GL_SetRenderMode( (rendermode == kRenderTransAdd) ? rendermode : kRenderTransColor);
|
||||
Vector4Set( dxc.currentColor, r / 255.f, g / 255.f, b / 255.f, a / 255.f );
|
||||
R_DrawStretchPic( x, y, w, h, 0, 0, 0, 0, tr.whiteTexture );
|
||||
#endif
|
||||
}
|
||||
|
||||
void R_Set2DMode( qboolean enable )
|
||||
{
|
||||
if( enable && dxc.in2DMode )
|
||||
return;
|
||||
dxc.in2DMode = enable;
|
||||
|
||||
d3dEBContext_t ebc = { 0 };
|
||||
if( !D3D_StartExecuteBuffer( &ebc ))
|
||||
return;
|
||||
void *cur = ebc.data;
|
||||
|
||||
if( enable )
|
||||
{
|
||||
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 4);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZENABLE, FALSE);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZWRITEENABLE, FALSE);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
|
||||
Vector4Set( dxc.currentColor, 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
|
||||
RI.currententity = NULL;
|
||||
RI.currentmodel = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 3);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZENABLE, TRUE);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ZWRITEENABLE, TRUE);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_CULLMODE, D3DCULL_CCW);
|
||||
}
|
||||
|
||||
ebc.vertCount = 0;
|
||||
ebc.insOffset = 0;
|
||||
ebc.insLength = ((char *)cur - (char *)ebc.data);
|
||||
|
||||
if (!D3D_EndExecuteBuffer(&ebc))
|
||||
return;
|
||||
|
||||
DXCheck(IDirect3DDevice_BeginScene(dxc.pd3dd));
|
||||
DXCheck(IDirect3DDevice_Execute(dxc.pd3dd, ebc.pd3deb, dxc.viewport, D3DEXECUTE_CLIPPED));
|
||||
DXCheck(IDirect3DDevice_EndScene(dxc.pd3dd));
|
||||
|
||||
D3D_ReleaseExecuteBuffer(&ebc);
|
||||
|
||||
}
|
||||
185
ref/dx2/r_frustum.c
Normal file
185
ref/dx2/r_frustum.c
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
r_frustum.c - frustum test implementation
|
||||
Copyright (C) 2016 Uncle Mike
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "r_local.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
|
||||
static void GL_FrustumSetPlane( gl_frustum_t *out, int side, const vec3_t vecNormal, float flDist )
|
||||
{
|
||||
Assert( side >= 0 && side < FRUSTUM_PLANES );
|
||||
|
||||
out->planes[side].type = PlaneTypeForNormal( vecNormal );
|
||||
out->planes[side].signbits = SignbitsForPlane( vecNormal );
|
||||
VectorCopy( vecNormal, out->planes[side].normal );
|
||||
out->planes[side].dist = flDist;
|
||||
|
||||
SetBits( out->clipFlags, BIT( side ));
|
||||
}
|
||||
|
||||
void GL_FrustumInitProj( gl_frustum_t *out, float flZNear, float flZFar, float flFovX, float flFovY )
|
||||
{
|
||||
float xs, xc;
|
||||
vec3_t farpoint, nearpoint;
|
||||
vec3_t normal, iforward;
|
||||
|
||||
// horizontal fov used for left and right planes
|
||||
SinCos( DEG2RAD( flFovX ) * 0.5f, &xs, &xc );
|
||||
|
||||
// setup left plane
|
||||
VectorMAM( xs, RI.cull_vforward, -xc, RI.cull_vright, normal );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_LEFT, normal, DotProduct( RI.cullorigin, normal ));
|
||||
|
||||
// setup right plane
|
||||
VectorMAM( xs, RI.cull_vforward, xc, RI.cull_vright, normal );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_RIGHT, normal, DotProduct( RI.cullorigin, normal ));
|
||||
|
||||
// vertical fov used for top and bottom planes
|
||||
SinCos( DEG2RAD( flFovY ) * 0.5f, &xs, &xc );
|
||||
VectorNegate( RI.cull_vforward, iforward );
|
||||
|
||||
// setup bottom plane
|
||||
VectorMAM( xs, RI.cull_vforward, -xc, RI.cull_vup, normal );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_BOTTOM, normal, DotProduct( RI.cullorigin, normal ));
|
||||
|
||||
// setup top plane
|
||||
VectorMAM( xs, RI.cull_vforward, xc, RI.cull_vup, normal );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_TOP, normal, DotProduct( RI.cullorigin, normal ));
|
||||
|
||||
// setup far plane
|
||||
VectorMA( RI.cullorigin, flZFar, RI.cull_vforward, farpoint );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_FAR, iforward, DotProduct( iforward, farpoint ));
|
||||
|
||||
// no need to setup backplane for general view.
|
||||
if( flZNear == 0.0f ) return;
|
||||
|
||||
// setup near plane
|
||||
VectorMA( RI.cullorigin, flZNear, RI.cull_vforward, nearpoint );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_NEAR, RI.cull_vforward, DotProduct( RI.cull_vforward, nearpoint ));
|
||||
}
|
||||
|
||||
void GL_FrustumInitOrtho( gl_frustum_t *out, float xLeft, float xRight, float yTop, float yBottom, float flZNear, float flZFar )
|
||||
{
|
||||
vec3_t iforward, iright, iup;
|
||||
|
||||
// setup the near and far planes
|
||||
float orgOffset = DotProduct( RI.cullorigin, RI.cull_vforward );
|
||||
VectorNegate( RI.cull_vforward, iforward );
|
||||
|
||||
// because quake ortho is inverted and far and near should be swaped
|
||||
GL_FrustumSetPlane( out, FRUSTUM_FAR, iforward, -flZNear - orgOffset );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_NEAR, RI.cull_vforward, flZFar + orgOffset );
|
||||
|
||||
// setup left and right planes
|
||||
orgOffset = DotProduct( RI.cullorigin, RI.cull_vright );
|
||||
VectorNegate( RI.cull_vright, iright );
|
||||
|
||||
GL_FrustumSetPlane( out, FRUSTUM_LEFT, RI.cull_vright, xLeft + orgOffset );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_RIGHT, iright, -xRight - orgOffset );
|
||||
|
||||
// setup top and buttom planes
|
||||
orgOffset = DotProduct( RI.cullorigin, RI.cull_vup );
|
||||
VectorNegate( RI.cull_vup, iup );
|
||||
|
||||
GL_FrustumSetPlane( out, FRUSTUM_TOP, RI.cull_vup, yTop + orgOffset );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_BOTTOM, iup, -yBottom - orgOffset );
|
||||
}
|
||||
|
||||
// cull methods
|
||||
qboolean GL_FrustumCullBox( const gl_frustum_t *out, const vec3_t mins, const vec3_t maxs, int userClipFlags )
|
||||
{
|
||||
int iClipFlags;
|
||||
int i, bit;
|
||||
|
||||
if( r_nocull.value )
|
||||
return false;
|
||||
|
||||
if( userClipFlags != 0 )
|
||||
iClipFlags = userClipFlags;
|
||||
else iClipFlags = out->clipFlags;
|
||||
|
||||
for( i = FRUSTUM_PLANES, bit = 1; i > 0; i--, bit <<= 1 )
|
||||
{
|
||||
const mplane_t *p = &out->planes[FRUSTUM_PLANES - i];
|
||||
|
||||
if( !FBitSet( iClipFlags, bit ))
|
||||
continue;
|
||||
|
||||
switch( p->signbits )
|
||||
{
|
||||
case 0:
|
||||
if( p->normal[0] * maxs[0] + p->normal[1] * maxs[1] + p->normal[2] * maxs[2] < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 1:
|
||||
if( p->normal[0] * mins[0] + p->normal[1] * maxs[1] + p->normal[2] * maxs[2] < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 2:
|
||||
if( p->normal[0] * maxs[0] + p->normal[1] * mins[1] + p->normal[2] * maxs[2] < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 3:
|
||||
if( p->normal[0] * mins[0] + p->normal[1] * mins[1] + p->normal[2] * maxs[2] < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 4:
|
||||
if( p->normal[0] * maxs[0] + p->normal[1] * maxs[1] + p->normal[2] * mins[2] < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 5:
|
||||
if( p->normal[0] * mins[0] + p->normal[1] * maxs[1] + p->normal[2] * mins[2] < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 6:
|
||||
if( p->normal[0] * maxs[0] + p->normal[1] * mins[1] + p->normal[2] * mins[2] < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 7:
|
||||
if( p->normal[0] * mins[0] + p->normal[1] * mins[1] + p->normal[2] * mins[2] < p->dist )
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean GL_FrustumCullSphere( const gl_frustum_t *out, const vec3_t center, float radius, int userClipFlags )
|
||||
{
|
||||
int iClipFlags;
|
||||
int i, bit;
|
||||
|
||||
if( r_nocull.value )
|
||||
return false;
|
||||
|
||||
if( userClipFlags != 0 )
|
||||
iClipFlags = userClipFlags;
|
||||
else iClipFlags = out->clipFlags;
|
||||
|
||||
for( i = FRUSTUM_PLANES, bit = 1; i > 0; i--, bit <<= 1 )
|
||||
{
|
||||
const mplane_t *p = &out->planes[FRUSTUM_PLANES - i];
|
||||
|
||||
if( !FBitSet( iClipFlags, bit ))
|
||||
continue;
|
||||
|
||||
if( DotProduct( center, p->normal ) - p->dist <= -radius )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
41
ref/dx2/r_frustum.h
Normal file
41
ref/dx2/r_frustum.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
r_frustum.h - frustum test implementation
|
||||
Copyright (C) 2016 Uncle Mike
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef GL_FRUSTUM_H
|
||||
#define GL_FRUSTUM_H
|
||||
|
||||
// don't change this order
|
||||
#define FRUSTUM_LEFT 0
|
||||
#define FRUSTUM_RIGHT 1
|
||||
#define FRUSTUM_BOTTOM 2
|
||||
#define FRUSTUM_TOP 3
|
||||
#define FRUSTUM_FAR 4
|
||||
#define FRUSTUM_NEAR 5
|
||||
#define FRUSTUM_PLANES 6
|
||||
|
||||
typedef struct gl_frustum_s
|
||||
{
|
||||
mplane_t planes[FRUSTUM_PLANES];
|
||||
unsigned int clipFlags;
|
||||
} gl_frustum_t;
|
||||
|
||||
void GL_FrustumInitProj( gl_frustum_t *out, float flZNear, float flZFar, float flFovX, float flFovY );
|
||||
void GL_FrustumInitOrtho( gl_frustum_t *out, float xLeft, float xRight, float yTop, float yBottom, float flZNear, float flZFar );
|
||||
|
||||
// cull methods
|
||||
qboolean GL_FrustumCullBox( const gl_frustum_t *out, const vec3_t mins, const vec3_t maxs, int userClipFlags );
|
||||
qboolean GL_FrustumCullSphere( const gl_frustum_t *out, const vec3_t centre, float radius, int userClipFlags );
|
||||
|
||||
#endif//GL_FRUSTUM_H
|
||||
622
ref/dx2/r_image.c
Normal file
622
ref/dx2/r_image.c
Normal file
@@ -0,0 +1,622 @@
|
||||
/*
|
||||
r_context.c -- dx2 renderer texture uploading and processing
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
Copyright (C) 2025 lewa_j
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "r_local.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
#include "crtlib.h"
|
||||
#include "crclib.h"
|
||||
|
||||
static dx_texture_t dx_textures[MAX_TEXTURES];
|
||||
static dx_texture_t *dx_texturesHashTable[TEXTURES_HASH_SIZE];
|
||||
static uint dx_numTextures;
|
||||
|
||||
void R_InitImages( void )
|
||||
{
|
||||
memset(dx_textures, 0, sizeof(dx_textures));
|
||||
memset(dx_texturesHashTable, 0, sizeof(dx_texturesHashTable));
|
||||
dx_numTextures = 0;
|
||||
|
||||
// create unused 0-entry
|
||||
Q_strncpy(dx_textures->name, "*unused*", sizeof(dx_textures->name));
|
||||
dx_textures->hashValue = COM_HashKey(dx_textures->name, TEXTURES_HASH_SIZE);
|
||||
dx_textures->nextHash = dx_texturesHashTable[dx_textures->hashValue];
|
||||
dx_texturesHashTable[dx_textures->hashValue] = dx_textures;
|
||||
dx_numTextures = 1;
|
||||
}
|
||||
|
||||
dx_texture_t *R_GetTexture( unsigned int texnum )
|
||||
{
|
||||
Assert(texnum < MAX_TEXTURES);
|
||||
return &dx_textures[texnum];
|
||||
}
|
||||
|
||||
void R_ShowTextures( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const byte *R_GetTextureOriginalBuffer( unsigned int idx )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static qboolean GL_CheckTexName( const char *name )
|
||||
{
|
||||
int len;
|
||||
|
||||
if( COM_StringEmptyOrNULL( name ))
|
||||
return false;
|
||||
|
||||
len = Q_strlen( name );
|
||||
|
||||
// because multi-layered textures can exceed name string
|
||||
if( len >= sizeof( dx_textures->name ))
|
||||
{
|
||||
gEngfuncs.Con_Printf( S_ERROR "LoadTexture: too long name %s (%d)\n", name, len );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static dx_texture_t *GL_TextureForName( const char *name )
|
||||
{
|
||||
dx_texture_t *tex;
|
||||
uint hash;
|
||||
|
||||
// find the texture in array
|
||||
hash = COM_HashKey(name, TEXTURES_HASH_SIZE);
|
||||
|
||||
for (tex = dx_texturesHashTable[hash]; tex != NULL; tex = tex->nextHash)
|
||||
{
|
||||
if (!Q_stricmp(tex->name, name))
|
||||
return tex;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static dx_texture_t *GL_AllocTexture( const char *name, texFlags_t flags )
|
||||
{
|
||||
dx_texture_t *tex = NULL;
|
||||
|
||||
// find a free texture_t slot
|
||||
uint i;
|
||||
|
||||
//skip 0
|
||||
for (i = 1; i < MAX_TEXTURES; i++)
|
||||
{
|
||||
if (dx_textures[i].used)
|
||||
continue;
|
||||
|
||||
tex = &dx_textures[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (tex == NULL)
|
||||
{
|
||||
gEngfuncs.Host_Error("%s: MAX_TEXTURES limit exceeds\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// copy initial params
|
||||
Q_strncpy(tex->name, name, sizeof(tex->name));
|
||||
tex->used = 1;
|
||||
tex->flags = flags;
|
||||
|
||||
// increase counter
|
||||
dx_numTextures = Q_max((tex - dx_textures) + 1, dx_numTextures);
|
||||
|
||||
// add to hash table
|
||||
tex->hashValue = COM_HashKey(name, TEXTURES_HASH_SIZE);
|
||||
tex->nextHash = dx_texturesHashTable[tex->hashValue];
|
||||
dx_texturesHashTable[tex->hashValue] = tex;
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
static void GL_ProcessImage( dx_texture_t *tex, rgbdata_t *pic )
|
||||
{
|
||||
uint img_flags = 0;
|
||||
|
||||
// force upload texture as RGB or RGBA (detail textures requires this)
|
||||
if (tex->flags & TF_FORCE_COLOR) pic->flags |= IMAGE_HAS_COLOR;
|
||||
if (pic->flags & IMAGE_HAS_ALPHA) tex->flags |= TF_HAS_ALPHA;
|
||||
|
||||
if (ImageCompressed(pic->type))
|
||||
{
|
||||
if (!pic->numMips)
|
||||
tex->flags |= TF_NOMIPMAP; // disable mipmapping by user request
|
||||
|
||||
// clear all the unsupported flags
|
||||
tex->flags &= ~TF_KEEP_SOURCE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// copy flag about luma pixels
|
||||
if (pic->flags & IMAGE_HAS_LUMA)
|
||||
tex->flags |= TF_HAS_LUMA;
|
||||
|
||||
if (pic->flags & IMAGE_QUAKEPAL)
|
||||
tex->flags |= TF_QUAKEPAL;
|
||||
|
||||
// create luma texture from quake texture
|
||||
if (tex->flags & TF_MAKELUMA)
|
||||
{
|
||||
img_flags |= IMAGE_MAKE_LUMA;
|
||||
tex->flags &= ~TF_MAKELUMA;
|
||||
}
|
||||
|
||||
if (!FBitSet(tex->flags, TF_IMG_UPLOADED) && FBitSet(tex->flags, TF_KEEP_SOURCE))
|
||||
tex->original = gEngfuncs.FS_CopyImage(pic); // because current pic will be expanded to rgba
|
||||
|
||||
// we need to expand image into RGBA buffer
|
||||
if (pic->type == PF_INDEXED_24 || pic->type == PF_INDEXED_32)
|
||||
img_flags |= IMAGE_FORCE_RGBA;
|
||||
|
||||
// processing image before uploading (force to rgba, make luma etc)
|
||||
if (pic->buffer) gEngfuncs.Image_Process(&pic, 0, 0, img_flags, 0);
|
||||
|
||||
if (FBitSet(tex->flags, TF_LUMINANCE))
|
||||
ClearBits(pic->flags, IMAGE_HAS_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
static int GL_CalcMipmapCount( dx_texture_t *tex, qboolean haveBuffer )
|
||||
{
|
||||
int width, height;
|
||||
int mipcount;
|
||||
|
||||
Assert(tex != NULL);
|
||||
|
||||
//TEMP
|
||||
return 1;
|
||||
|
||||
if (!haveBuffer)
|
||||
return 1;
|
||||
|
||||
// generate mip-levels by user request
|
||||
if (FBitSet(tex->flags, TF_NOMIPMAP))
|
||||
return 1;
|
||||
|
||||
// mip-maps can't exceeds 16
|
||||
for (mipcount = 0; mipcount < 16; mipcount++)
|
||||
{
|
||||
width = Q_max(1, (tex->width >> mipcount));
|
||||
height = Q_max(1, (tex->height >> mipcount));
|
||||
if (width == 1 && height == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
return mipcount + 1;
|
||||
}
|
||||
|
||||
static void GL_TextureImageRAW( dx_texture_t *tex, int width, int height, int type, const char *data )
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
DDSURFACEDESC ddsd = {};
|
||||
ZeroMemory(&ddsd, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_LPSURFACE;
|
||||
DXCheck(IDirectDrawSurface_Lock(tex->dds, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL));
|
||||
|
||||
int pitch = ddsd.lPitch;
|
||||
if (!pitch)
|
||||
pitch = ddsd.dwWidth * 4;
|
||||
char *dst = (char *)ddsd.lpSurface;
|
||||
|
||||
for (int j = 0; j < (int)ddsd.dwHeight; j++)
|
||||
{
|
||||
//RGBA to BGRA
|
||||
if (type == PF_RGBA_32)
|
||||
{
|
||||
for (int i = 0; i < ddsd.dwWidth; i++)
|
||||
{
|
||||
dst[i * 4 + 0] = data[i * 4 + 2];
|
||||
dst[i * 4 + 1] = data[i * 4 + 1];
|
||||
dst[i * 4 + 2] = data[i * 4 + 0];
|
||||
dst[i * 4 + 3] = data[i * 4 + 3];
|
||||
}
|
||||
}
|
||||
else if (type == PF_BGRA_32)
|
||||
{
|
||||
memcpy(dst, data, ddsd.dwWidth * 4);
|
||||
}
|
||||
|
||||
dst += pitch;
|
||||
data += ddsd.dwWidth * 4;
|
||||
}
|
||||
|
||||
DXCheck(IDirectDrawSurface_Unlock(tex->dds, ddsd.lpSurface));
|
||||
}
|
||||
|
||||
static qboolean GL_UploadTexture( dx_texture_t *tex, rgbdata_t *pic )
|
||||
{
|
||||
byte *buf, *data;
|
||||
size_t size;
|
||||
uint width, height;
|
||||
uint j;
|
||||
qboolean normalMap;
|
||||
const byte *bufend;
|
||||
|
||||
// dedicated server
|
||||
if (!dxc.window)
|
||||
return true;
|
||||
|
||||
Assert(pic != NULL);
|
||||
Assert(tex != NULL);
|
||||
|
||||
qboolean supported = true;
|
||||
|
||||
if (FBitSet(pic->flags, IMAGE_CUBEMAP))
|
||||
supported = false;
|
||||
else if (FBitSet(pic->flags, IMAGE_MULTILAYER) && pic->depth >= 1)
|
||||
supported = false;
|
||||
else if (pic->width > 1 && pic->height > 1 && pic->depth > 1)
|
||||
supported = false;
|
||||
else if (FBitSet(tex->flags, TF_RECTANGLE))
|
||||
supported = false;
|
||||
else if (FBitSet(tex->flags, TF_MULTISAMPLE))
|
||||
supported = false;
|
||||
|
||||
// make sure what target is correct
|
||||
if (!supported)
|
||||
{
|
||||
gEngfuncs.Con_DPrintf(S_ERROR "%s: %s is not supported\n", __func__, tex->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
//if (pic->type == PF_BC6H_SIGNED || pic->type == PF_BC6H_UNSIGNED || pic->type == PF_BC7_UNORM || pic->type == PF_BC7_SRGB)
|
||||
if (ImageCompressed(pic->type))
|
||||
{
|
||||
gEngfuncs.Con_DPrintf(S_ERROR "%s: compressed textures are not supported\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
// store original sizes
|
||||
tex->srcWidth = pic->width;
|
||||
tex->srcHeight = pic->height;
|
||||
|
||||
// set the texture dimensions
|
||||
{
|
||||
int step = 0;// (int)gl_round_down.value;
|
||||
int scaled_width, scaled_height;
|
||||
|
||||
for (scaled_width = 1; scaled_width < pic->width; scaled_width <<= 1);
|
||||
|
||||
if (step > 0 && pic->width < scaled_width && (step == 1 || (scaled_width - pic->width) > (scaled_width >> step)))
|
||||
scaled_width >>= 1;
|
||||
|
||||
for (scaled_height = 1; scaled_height < pic->height; scaled_height <<= 1);
|
||||
|
||||
if (step > 0 && pic->height < scaled_height && (step == 1 || (scaled_height - pic->height) > (scaled_height >> step)))
|
||||
scaled_height >>= 1;
|
||||
|
||||
tex->width = Q_max(1, scaled_width);
|
||||
tex->height = Q_max(1, scaled_height);
|
||||
}
|
||||
|
||||
DDSURFACEDESC ddsd = {};
|
||||
ZeroMemory(&ddsd, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
||||
//if (pic->numMips > 1)
|
||||
// ddsd.ddsCaps.dwCaps |= DDSCAPS_MIPMAP | DDSCAPS_COMPLEX;
|
||||
ddsd.dwWidth = tex->width;
|
||||
ddsd.dwHeight = tex->height;
|
||||
|
||||
#if 1
|
||||
//BGRA8
|
||||
ddsd.dwFlags |= DDSD_PIXELFORMAT;
|
||||
ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
|
||||
ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
|
||||
if(FBitSet(pic->flags, IMAGE_HAS_ALPHA))
|
||||
ddsd.ddpfPixelFormat.dwFlags |= DDPF_ALPHAPIXELS;
|
||||
ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
|
||||
ddsd.ddpfPixelFormat.dwBBitMask = 0xFF;
|
||||
ddsd.ddpfPixelFormat.dwGBitMask = 0xFF00;
|
||||
ddsd.ddpfPixelFormat.dwRBitMask = 0xFF0000;
|
||||
ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xFF000000;
|
||||
#endif
|
||||
|
||||
DXCheck(IDirectDraw_CreateSurface(dxc.pdd, &ddsd, &tex->dds, NULL));
|
||||
DXCheck(IDirectDrawSurface_QueryInterface(tex->dds, &IID_IDirect3DTexture, (void**)&tex->d3dTex));
|
||||
DXCheck(IDirect3DTexture_GetHandle(tex->d3dTex, dxc.pd3dd, &tex->d3dHandle));
|
||||
|
||||
tex->fogParams[0] = pic->fogParams[0];
|
||||
tex->fogParams[1] = pic->fogParams[1];
|
||||
tex->fogParams[2] = pic->fogParams[2];
|
||||
tex->fogParams[3] = pic->fogParams[3];
|
||||
|
||||
buf = pic->buffer;
|
||||
bufend = pic->buffer + pic->size; // total image size include all the layers, cube sides, mipmaps
|
||||
normalMap = FBitSet(tex->flags, TF_NORMALMAP) ? true : false;
|
||||
|
||||
if (Q_max(1, pic->numMips) > 1) // not-compressed DDS
|
||||
{
|
||||
//TEMP
|
||||
j = 0;
|
||||
//for (j = 0; j < Q_max(1, pic->numMips); j++)
|
||||
{
|
||||
// track the buffer bounds
|
||||
if (buf != NULL && buf >= bufend)
|
||||
gEngfuncs.Host_Error("%s: %s image buffer overflow\n", __func__, tex->name);
|
||||
|
||||
width = Q_max(1, (tex->width >> j));
|
||||
height = Q_max(1, (tex->height >> j));
|
||||
size = gEngfuncs.Image_CalcImageSize(pic->type, width, height, 1);
|
||||
GL_TextureImageRAW(tex, width, height, pic->type, buf);
|
||||
buf += size; // move pointer
|
||||
tex->numMips++;
|
||||
}
|
||||
}
|
||||
else // RGBA32
|
||||
{
|
||||
// track the buffer bounds
|
||||
if (buf != NULL && buf >= bufend)
|
||||
gEngfuncs.Host_Error("%s: %s image buffer overflow\n", __func__, tex->name);
|
||||
|
||||
int mipCount = GL_CalcMipmapCount(tex, (buf != NULL));
|
||||
|
||||
// NOTE: only single uncompressed textures can be resamples, no mips, no layers, no sides
|
||||
if (((pic->width != tex->width) || (pic->height != tex->height)))
|
||||
data = GL_ResampleTexture(buf, pic->width, pic->height, tex->width, tex->height, normalMap);
|
||||
else data = buf;
|
||||
|
||||
//if (!ImageCompressed(pic->type) && !FBitSet(tex->flags, TF_NOMIPMAP) && FBitSet(pic->flags, IMAGE_ONEBIT_ALPHA))
|
||||
// data = GL_ApplyFilter(data, tex->width, tex->height);
|
||||
|
||||
// mips will be auto-generated if desired
|
||||
for (j = 0; j < mipCount; j++)
|
||||
{
|
||||
width = Q_max(1, (tex->width >> j));
|
||||
height = Q_max(1, (tex->height >> j));
|
||||
size = gEngfuncs.Image_CalcImageSize(pic->type, width, height, 1);
|
||||
GL_TextureImageRAW(tex, width, height, pic->type, data);
|
||||
//if (mipCount > 1)
|
||||
// GL_BuildMipMap(data, width, height, tex->depth, tex->flags);
|
||||
tex->numMips++;
|
||||
}
|
||||
}
|
||||
|
||||
SetBits(tex->flags, TF_IMG_UPLOADED); // done
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update )
|
||||
{
|
||||
dx_texture_t *tex;
|
||||
|
||||
if (!GL_CheckTexName(name))
|
||||
return 0;
|
||||
|
||||
// see if already loaded
|
||||
if ((tex = GL_TextureForName(name)) && !update)
|
||||
return (tex - dx_textures);
|
||||
|
||||
// couldn't loading image
|
||||
if (!pic) return 0;
|
||||
|
||||
if (update)
|
||||
{
|
||||
if (tex == NULL)
|
||||
gEngfuncs.Host_Error("%s: couldn't find texture %s for update\n", __func__, name);
|
||||
SetBits(tex->flags, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
// allocate the new one
|
||||
tex = GL_AllocTexture(name, flags);
|
||||
}
|
||||
|
||||
GL_ProcessImage(tex, pic);
|
||||
|
||||
if (!GL_UploadTexture(tex, pic))
|
||||
{
|
||||
memset(tex, 0, sizeof(dx_texture_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (tex - dx_textures);
|
||||
}
|
||||
|
||||
int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags )
|
||||
{
|
||||
qboolean update = FBitSet( flags, TF_UPDATE ) ? true : false;
|
||||
int datasize = 1;
|
||||
rgbdata_t r_empty;
|
||||
|
||||
if( FBitSet( flags, TF_ARB_16BIT ))
|
||||
datasize = 2;
|
||||
else if( FBitSet( flags, TF_ARB_FLOAT ))
|
||||
datasize = 4;
|
||||
|
||||
ClearBits( flags, TF_UPDATE );
|
||||
memset( &r_empty, 0, sizeof( r_empty ));
|
||||
r_empty.width = width;
|
||||
r_empty.height = height;
|
||||
r_empty.type = PF_RGBA_32;
|
||||
r_empty.size = r_empty.width * r_empty.height * datasize * 4;
|
||||
r_empty.buffer = (byte *)buffer;
|
||||
|
||||
// clear invalid combinations
|
||||
ClearBits( flags, TF_TEXTURE_3D );
|
||||
|
||||
// if image not luminance and not alphacontrast it will have color
|
||||
if( !FBitSet( flags, TF_LUMINANCE ) && !FBitSet( flags, TF_ALPHACONTRAST ))
|
||||
SetBits( r_empty.flags, IMAGE_HAS_COLOR );
|
||||
|
||||
if( FBitSet( flags, TF_HAS_ALPHA ))
|
||||
SetBits( r_empty.flags, IMAGE_HAS_ALPHA );
|
||||
|
||||
if( FBitSet( flags, TF_CUBEMAP ))
|
||||
{
|
||||
// no cubemaps in dx2
|
||||
return 0;
|
||||
}
|
||||
|
||||
int texnum = GL_LoadTextureFromBuffer( name, &r_empty, flags, update );
|
||||
|
||||
if( !Q_strcmp( name, REF_DEFAULT_TEXTURE ))
|
||||
tr.defaultTexture = texnum;
|
||||
else if( !Q_strcmp( name, REF_PARTICLE_TEXTURE ))
|
||||
tr.particleTexture = texnum;
|
||||
else if( !Q_strcmp( name, REF_WHITE_TEXTURE ))
|
||||
tr.whiteTexture = texnum;
|
||||
else if( !Q_strcmp( name, REF_GRAY_TEXTURE ))
|
||||
tr.grayTexture = texnum;
|
||||
else if( !Q_strcmp( name, REF_BLACK_TEXTURE ))
|
||||
tr.blackTexture = texnum;
|
||||
|
||||
return texnum;
|
||||
}
|
||||
|
||||
void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScale )
|
||||
{
|
||||
*xScale = *yScale = 1.0f;
|
||||
}
|
||||
|
||||
void R_SetDetailScaleForTexture( int texture, float xScale, float yScale )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
int GL_FindTexture( const char *name )
|
||||
{
|
||||
gEngfuncs.Con_Printf("GL_FindTexture(%s)\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *GL_TextureName( unsigned int texnum )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const byte *GL_TextureData( unsigned int texnum )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags )
|
||||
{
|
||||
dx_texture_t *tex;
|
||||
rgbdata_t *pic;
|
||||
uint picFlags = 0;
|
||||
|
||||
if (!GL_CheckTexName(name))
|
||||
return 0;
|
||||
|
||||
// see if already loaded
|
||||
if ((tex = GL_TextureForName(name)))
|
||||
return (tex - dx_textures);
|
||||
|
||||
gEngfuncs.Con_Printf("GL_LoadTexture(%s, %p, %zu, %X)\n", name, buf, size, flags);
|
||||
|
||||
if (FBitSet(flags, TF_NOFLIP_TGA))
|
||||
SetBits(picFlags, IL_DONTFLIP_TGA);
|
||||
|
||||
if (FBitSet(flags, TF_KEEP_SOURCE) && !FBitSet(flags, TF_EXPAND_SOURCE))
|
||||
SetBits(picFlags, IL_KEEP_8BIT);
|
||||
|
||||
// set some image flags
|
||||
gEngfuncs.Image_SetForceFlags(picFlags);
|
||||
|
||||
pic = gEngfuncs.FS_LoadImage(name, buf, size);
|
||||
if (!pic) return 0; // couldn't loading image
|
||||
|
||||
// allocate the new one
|
||||
tex = GL_AllocTexture(name, flags);
|
||||
GL_ProcessImage(tex, pic);
|
||||
|
||||
if (!GL_UploadTexture(tex, pic))
|
||||
{
|
||||
memset(tex, 0, sizeof(dx_texture_t));
|
||||
gEngfuncs.FS_FreeImage(pic); // release source texture
|
||||
return 0;
|
||||
}
|
||||
|
||||
//GL_ApplyTextureParams(tex); // update texture filter, wrap etc
|
||||
gEngfuncs.FS_FreeImage(pic); // release source texture
|
||||
|
||||
// NOTE: always return texnum as index in array or engine will stop work !!!
|
||||
return tex - dx_textures;
|
||||
}
|
||||
|
||||
void GL_FreeTexture( unsigned int texnum )
|
||||
{
|
||||
if (texnum <= 0 || texnum >= MAX_TEXTURES)
|
||||
return;
|
||||
|
||||
gEngfuncs.Con_Printf("GL_FreeTexture(%d) %s\n", texnum, dx_textures[texnum].name);
|
||||
|
||||
dx_texture_t* tex = R_GetTexture(texnum);
|
||||
if (!tex->dds)
|
||||
return;
|
||||
|
||||
// debug
|
||||
if (!tex->name[0])
|
||||
{
|
||||
gEngfuncs.Con_Printf(S_ERROR "%s: trying to free unnamed texture with handle %X\n", __func__, tex->d3dHandle);
|
||||
return;
|
||||
}
|
||||
|
||||
// remove from hash table
|
||||
dx_texture_t **prev = &dx_texturesHashTable[tex->hashValue];
|
||||
|
||||
while (1)
|
||||
{
|
||||
dx_texture_t *cur = *prev;
|
||||
if (!cur) break;
|
||||
|
||||
if (cur == tex)
|
||||
{
|
||||
*prev = cur->nextHash;
|
||||
break;
|
||||
}
|
||||
prev = &cur->nextHash;
|
||||
}
|
||||
|
||||
// TODO invalidate texture state
|
||||
|
||||
// release source
|
||||
if (tex->original)
|
||||
gEngfuncs.FS_FreeImage(tex->original);
|
||||
|
||||
if (tex->d3dTex)
|
||||
IDirect3DTexture_Release(tex->d3dTex);
|
||||
if (tex->dds)
|
||||
IDirectDrawSurface_Release(tex->dds);
|
||||
memset(tex, 0, sizeof(*tex));
|
||||
}
|
||||
|
||||
void R_OverrideTextureSourceSize( unsigned int textnum, unsigned int srcWidth, unsigned int srcHeight )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void GL_UpdateTexture( int texnum, int cols, int rows, int width, int height, const byte *buffer, pixformat_t fmt )
|
||||
{
|
||||
;
|
||||
}
|
||||
319
ref/dx2/r_local.h
Normal file
319
ref/dx2/r_local.h
Normal file
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
r_local.h - renderer local declarations
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
Copyright (C) 2025-2026 lewa_j
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ref_common.h"
|
||||
#include "ref_api.h"
|
||||
#include "r_frustum.h"
|
||||
#include "ref_params.h"
|
||||
#include "mod_local.h"
|
||||
#include "com_strings.h"
|
||||
#include "pmove.h"
|
||||
|
||||
#define DIRECTDRAW_VERSION 0x0200
|
||||
#define DIRECT3D_VERSION 0x0500//D3DCOLORMODEL bug
|
||||
#include <ddraw.h>
|
||||
#include <d3d.h>
|
||||
|
||||
#define MAX_TEXTURES 8192
|
||||
#define TEXTURES_HASH_SIZE (MAX_TEXTURES >> 2)
|
||||
|
||||
#define MAX_DRAW_STACK 2 // normal view and menu view
|
||||
|
||||
#define CULL_VISIBLE 0 // not culled
|
||||
#define CULL_BACKSIDE 1 // backside of transparent wall
|
||||
#define CULL_FRUSTUM 2 // culled by frustum
|
||||
#define CULL_VISFRAME 3 // culled by PVS
|
||||
#define CULL_OTHER 4 // culled by other reason
|
||||
|
||||
typedef struct dx_texture_s
|
||||
{
|
||||
char name[256]; // game path, including extension (can be store image programs)
|
||||
word srcWidth; // keep unscaled sizes
|
||||
word srcHeight;
|
||||
word width; // upload width\height
|
||||
word height;
|
||||
|
||||
byte numMips; // mipmap count
|
||||
|
||||
int used;
|
||||
texFlags_t flags;
|
||||
rgba_t fogParams; // some water textures
|
||||
// contain info about underwater fog
|
||||
rgbdata_t *original; // keep original image
|
||||
#if 0
|
||||
word depth; // texture depth or count of layers for 2D_ARRAY
|
||||
|
||||
GLuint target; // glTarget
|
||||
GLuint texnum; // gl texture binding
|
||||
GLint format; // uploaded format
|
||||
|
||||
// debug info
|
||||
size_t size; // upload size for debug targets
|
||||
|
||||
// detail textures stuff
|
||||
float xscale;
|
||||
float yscale;
|
||||
|
||||
#endif
|
||||
IDirectDrawSurface *dds;
|
||||
IDirect3DTexture *d3dTex;
|
||||
D3DTEXTUREHANDLE d3dHandle;
|
||||
uint hashValue;
|
||||
struct dx_texture_s *nextHash;
|
||||
} dx_texture_t;
|
||||
|
||||
typedef struct d3dEBContext_s
|
||||
{
|
||||
IDirect3DExecuteBuffer *pd3deb;
|
||||
DWORD bufferSize;
|
||||
void *data;
|
||||
DWORD vertCount;
|
||||
DWORD insOffset;
|
||||
DWORD insLength;
|
||||
} d3dEBContext_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ref_viewpass_t rvp;
|
||||
|
||||
cl_entity_t *currententity;
|
||||
model_t *currentmodel;
|
||||
cl_entity_t *currentbeam; // same as above but for beams
|
||||
|
||||
gl_frustum_t frustum;
|
||||
|
||||
mleaf_t *viewleaf;
|
||||
mleaf_t *oldviewleaf;
|
||||
vec3_t vforward;
|
||||
vec3_t vright;
|
||||
vec3_t vup;
|
||||
|
||||
vec3_t cullorigin;
|
||||
vec3_t cull_vforward;
|
||||
vec3_t cull_vright;
|
||||
vec3_t cull_vup;
|
||||
|
||||
float farClip;
|
||||
|
||||
qboolean fogCustom;
|
||||
qboolean fogEnabled;
|
||||
qboolean fogSkybox;
|
||||
vec4_t fogColor;
|
||||
float fogDensity;
|
||||
float fogStart;
|
||||
float fogEnd;
|
||||
int cached_contents; // in water
|
||||
int cached_waterlevel; // was in water
|
||||
|
||||
float skyMins[2][SKYBOX_MAX_SIDES];
|
||||
float skyMaxs[2][SKYBOX_MAX_SIDES];
|
||||
|
||||
matrix4x4 objectMatrix; // currententity matrix
|
||||
matrix4x4 worldviewMatrix; // modelview for world
|
||||
matrix4x4 modelviewMatrix; // worldviewMatrix * objectMatrix
|
||||
|
||||
matrix4x4 projectionMatrix;
|
||||
matrix4x4 worldviewProjectionMatrix; // worldviewMatrix * projectionMatrix
|
||||
byte visbytes[( MAX_MAP_LEAFS + 7 ) / 8];// actual PVS for current frame
|
||||
|
||||
float viewplanedist;
|
||||
mplane_t clipPlane;
|
||||
} ref_instance_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cl_entity_t *solid_entities[MAX_VISIBLE_PACKET]; // opaque moving or alpha brushes
|
||||
cl_entity_t *trans_entities[MAX_VISIBLE_PACKET]; // translucent brushes
|
||||
cl_entity_t *beam_entities[MAX_VISIBLE_PACKET];
|
||||
uint num_solid_entities;
|
||||
uint num_trans_entities;
|
||||
uint num_beam_entities;
|
||||
} draw_list_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int defaultTexture; // use for bad textures
|
||||
int particleTexture;
|
||||
int whiteTexture;
|
||||
int grayTexture;
|
||||
int blackTexture;
|
||||
|
||||
int skytexturenum; // index into model_t::textures
|
||||
|
||||
// entity lists
|
||||
draw_list_t draw_stack[MAX_DRAW_STACK];
|
||||
int draw_stack_pos;
|
||||
draw_list_t *draw_list;
|
||||
|
||||
// matrix states
|
||||
qboolean modelviewIdentity;
|
||||
|
||||
int visframecount; // PVS frame
|
||||
int dlightframecount; // dynamic light frame
|
||||
int realframecount; // not including viewpasses
|
||||
int framecount;
|
||||
|
||||
qboolean fCustomRendering;
|
||||
qboolean fResetVis;
|
||||
|
||||
double frametime; // special frametime for multipass rendering (will set to 0 on a nextview)
|
||||
float blend; // global blend value
|
||||
|
||||
// cull info
|
||||
vec3_t modelorg; // relative to viewpoint
|
||||
|
||||
// get from engine
|
||||
model_t *worldmodel;
|
||||
world_static_t *world;
|
||||
cl_entity_t *entities;
|
||||
cl_entity_t *viewent;
|
||||
|
||||
uint max_entities;
|
||||
|
||||
ref_screen_rotation_t rotation;
|
||||
} dx_globals_t;
|
||||
|
||||
struct dx_context_s
|
||||
{
|
||||
HWND window;
|
||||
int windowWidth;
|
||||
int windowHeight;
|
||||
IDirectDraw *pdd;
|
||||
IDirectDrawSurface *pddsPrimary;
|
||||
IDirectDrawSurface *pddsBack;
|
||||
IDirectDrawSurface *pddsZBuffer;
|
||||
IDirectDrawClipper *pddClipper;
|
||||
IDirectDrawClipper *pddBackClipper;
|
||||
IDirect3D *pd3d;
|
||||
IDirect3DDevice *pd3dd;
|
||||
IDirect3DExecuteBuffer *pd3deb;
|
||||
IDirect3DViewport *viewport;
|
||||
D3DMATRIXHANDLE mtxWorld;
|
||||
D3DMATRIXHANDLE mtxProjection;
|
||||
|
||||
qboolean in2DMode;
|
||||
int renderMode;
|
||||
vec4_t currentColor;
|
||||
D3DTEXTUREHANDLE currentTexture;
|
||||
D3DTEXTUREHANDLE lastBoundTexture;
|
||||
};
|
||||
typedef struct dx_context_s dx_context_t;
|
||||
|
||||
extern ref_instance_t RI;
|
||||
extern dx_globals_t tr;
|
||||
extern dx_context_t dxc;
|
||||
|
||||
|
||||
static inline cl_entity_t *CL_GetEntityByIndex( int index )
|
||||
{
|
||||
if( unlikely( index < 0 || index >= tr.max_entities || !tr.entities ))
|
||||
return NULL;
|
||||
|
||||
return &tr.entities[index];
|
||||
}
|
||||
|
||||
static inline model_t *CL_ModelHandle( int index )
|
||||
{
|
||||
if( unlikely( index < 0 || index >= gp_cl->nummodels ))
|
||||
return NULL;
|
||||
|
||||
return gp_cl->models[index];
|
||||
}
|
||||
|
||||
const char *dxResultToStr( HRESULT r );
|
||||
|
||||
#define DXCheckRet(DST, CALL) \
|
||||
(DST) = (CALL);\
|
||||
if ((DST) != DD_OK)\
|
||||
gEngfuncs.Con_Printf( S_ERROR "%s():%s:%d: DirectX error %X(%d 0x%X %d) %s at \"" #CALL "\"\n", __FUNCTION__, __FILE__, __LINE__, (DST), ( (DST) >> 31 ) & 1, ( (DST) >> 16 ) & 0x7FFF, (DST) & 0xFFFF, dxResultToStr( r ));
|
||||
|
||||
#define DXCheck(CALL) \
|
||||
{\
|
||||
HRESULT r = DD_OK;\
|
||||
DXCheckRet(r, CALL)\
|
||||
}
|
||||
|
||||
void GL_SetRenderMode( int mode );
|
||||
void GL_Bind( int tmu, unsigned int texnum );
|
||||
|
||||
// r_d3d.c
|
||||
qboolean R_Init( void );
|
||||
void R_Shutdown( void );
|
||||
void GL_SetupAttributes( int safegl );
|
||||
void GL_InitExtensions( void );
|
||||
void GL_ClearExtensions( void );
|
||||
void D3D_Resize( int width, int height );
|
||||
qboolean D3D_StartExecuteBuffer( d3dEBContext_t *ctx );
|
||||
qboolean D3D_EndExecuteBuffer( d3dEBContext_t *ctx );
|
||||
void D3D_ReleaseExecuteBuffer( d3dEBContext_t *ctx );
|
||||
void D3D_SetVertTL( D3DTLVERTEX *v, float x, float y, float z, float w, float tu, float tv );
|
||||
void D3D_SetTri( D3DTRIANGLE *t, int v1, int v2, int v3 );
|
||||
void D3D_PutInstruction( void **dst, BYTE opcode, BYTE size, WORD count );
|
||||
void D3D_PutProcessVertices( void **dst, DWORD flags, WORD start, WORD count );
|
||||
void D3D_PutRenderState( void **dst, D3DRENDERSTATETYPE type, DWORD arg );
|
||||
void D3D_PutTransformState( void **dst, D3DTRANSFORMSTATETYPE type, DWORD arg );
|
||||
|
||||
// r_main.c
|
||||
void R_GammaChanged( qboolean do_reset_gamma );
|
||||
void R_BeginFrame( qboolean clearScene );
|
||||
void R_RenderScene( void );
|
||||
void R_EndFrame( void );
|
||||
void R_AllowFog( qboolean allowed );
|
||||
void R_RenderFrame( const struct ref_viewpass_s *rvp );
|
||||
qboolean R_AddEntity( struct cl_entity_s *clent, int type );
|
||||
void R_ClearScene( void );
|
||||
int WorldToScreen( const vec3_t world, vec3_t screen );
|
||||
void R_LoadIdentity( void );
|
||||
void R_SetupD3D( qboolean set_state );
|
||||
|
||||
// r_draw.c
|
||||
void R_Set2DMode( qboolean enable );
|
||||
void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum );
|
||||
void FillRGBA( int rendermode, float x, float y, float w, float h, byte r, byte g, byte b, byte a );
|
||||
|
||||
// r_image.c
|
||||
void R_InitImages( void );
|
||||
dx_texture_t *R_GetTexture( unsigned int texnum );
|
||||
void R_ShowTextures( void );
|
||||
const byte *R_GetTextureOriginalBuffer( unsigned int idx );
|
||||
int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update );
|
||||
void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor );
|
||||
void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScale );
|
||||
void R_SetDetailScaleForTexture( int texture, float xScale, float yScale );
|
||||
int GL_FindTexture( const char *name );
|
||||
const char *GL_TextureName( unsigned int texnum );
|
||||
const byte *GL_TextureData( unsigned int texnum );
|
||||
int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags );
|
||||
int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags );
|
||||
void GL_FreeTexture( unsigned int texnum );
|
||||
void R_OverrideTextureSourceSize( unsigned int textnum, unsigned int srcWidth, unsigned int srcHeight );
|
||||
void GL_UpdateTexture( int texnum, int cols, int rows, int width, int height, const byte *buffer, pixformat_t fmt );
|
||||
|
||||
// r_surf.c
|
||||
void GL_SubdivideSurface( model_t *mod, msurface_t *fa );
|
||||
void GL_OrthoBounds( const float *mins, const float *maxs );
|
||||
byte *Mod_GetCurrentVis( void );
|
||||
void R_DrawWorld( void );
|
||||
void R_MarkLeaves( void );
|
||||
void GL_BuildLightmaps( void );
|
||||
|
||||
extern convar_t r_novis;
|
||||
extern convar_t r_nocull;
|
||||
extern convar_t r_lockpvs;
|
||||
extern convar_t r_lockfrustum;
|
||||
|
||||
380
ref/dx2/r_main.c
Normal file
380
ref/dx2/r_main.c
Normal file
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
r_main.c -- dx2 renderer main loop
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
Copyright (C) 2025-2026 lewa_j
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "r_local.h"
|
||||
#include "ref_params.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
|
||||
ref_instance_t RI;
|
||||
|
||||
static void R_Clear( int bitMask )
|
||||
{
|
||||
int bits = D3DCLEAR_ZBUFFER;
|
||||
//bits &= bitMask;
|
||||
|
||||
D3DRECT rect = {
|
||||
.x1 = 0,
|
||||
.y1 = 0,
|
||||
.x2 = dxc.windowWidth,
|
||||
.y2 = dxc.windowHeight,
|
||||
};
|
||||
DXCheck(IDirect3DViewport_Clear(dxc.viewport, 1, &rect, bits));
|
||||
}
|
||||
|
||||
static float R_GetFarClip( void )
|
||||
{
|
||||
if( tr.worldmodel && FBitSet( RI.rvp.flags, RF_DRAW_WORLD ) )
|
||||
return gp_movevars->zmax * 1.73f;
|
||||
|
||||
return 2048.0f;
|
||||
}
|
||||
|
||||
void R_SetupFrustum( void )
|
||||
{
|
||||
// build the transformation matrix for the given view angles
|
||||
AngleVectors( RI.rvp.viewangles, RI.vforward, RI.vright, RI.vup );
|
||||
|
||||
if( !r_lockfrustum.value )
|
||||
{
|
||||
VectorCopy( RI.rvp.vieworigin, RI.cullorigin );
|
||||
VectorCopy( RI.vforward, RI.cull_vforward );
|
||||
VectorCopy( RI.vright, RI.cull_vright );
|
||||
VectorCopy( RI.vup, RI.cull_vup );
|
||||
}
|
||||
|
||||
if( FBitSet( RI.rvp.flags, RF_DRAW_OVERVIEW ))
|
||||
{
|
||||
const ref_overview_t *ov = gEngfuncs.GetOverviewParms();
|
||||
GL_FrustumInitOrtho( &RI.frustum, ov->xLeft, ov->xRight, ov->yTop, ov->yBottom, ov->zNear, ov->zFar );
|
||||
}
|
||||
else
|
||||
{
|
||||
GL_FrustumInitProj( &RI.frustum, 0.0f, R_GetFarClip(), RI.rvp.fov_x, RI.rvp.fov_y ); // NOTE: we ignore nearplane here (mirrors only)
|
||||
}
|
||||
}
|
||||
|
||||
static void R_SetupProjectionMatrix( matrix4x4 m )
|
||||
{
|
||||
float xMin, xMax, yMin, yMax, zNear, zFar;
|
||||
|
||||
if( FBitSet( RI.rvp.flags, RF_DRAW_OVERVIEW ))
|
||||
{
|
||||
const ref_overview_t *ov = gEngfuncs.GetOverviewParms();
|
||||
Matrix4x4_CreateOrtho( m, ov->xLeft, ov->xRight, ov->yTop, ov->yBottom, ov->zNear, ov->zFar );
|
||||
return;
|
||||
}
|
||||
|
||||
RI.farClip = R_GetFarClip();
|
||||
|
||||
zNear = 4.0f;
|
||||
zFar = Q_max( 256.0f, RI.farClip );
|
||||
|
||||
yMax = zNear * tan( RI.rvp.fov_y * M_PI_F / 360.0f );
|
||||
yMin = -yMax;
|
||||
|
||||
xMax = zNear * tan( RI.rvp.fov_x * M_PI_F / 360.0f );
|
||||
xMin = -xMax;
|
||||
|
||||
if( tr.rotation & 1 )
|
||||
{
|
||||
Matrix4x4_CreateProjection( m, yMax, yMin, xMax, xMin, zNear, zFar );
|
||||
}
|
||||
else
|
||||
{
|
||||
Matrix4x4_CreateProjection( m, xMax, xMin, yMax, yMin, zNear, zFar );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_SetupModelviewMatrix
|
||||
=============
|
||||
*/
|
||||
static void R_SetupModelviewMatrix( matrix4x4 m )
|
||||
{
|
||||
Matrix4x4_CreateModelview( m );
|
||||
if( tr.rotation & 1 )
|
||||
{
|
||||
Matrix4x4_ConcatRotate( m, anglemod( -RI.rvp.viewangles[2] + 90 ), 1, 0, 0 );
|
||||
Matrix4x4_ConcatRotate( m, -RI.rvp.viewangles[0], 0, 1, 0 );
|
||||
Matrix4x4_ConcatRotate( m, -RI.rvp.viewangles[1], 0, 0, 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
Matrix4x4_ConcatRotate( m, -RI.rvp.viewangles[2], 1, 0, 0 );
|
||||
Matrix4x4_ConcatRotate( m, -RI.rvp.viewangles[0], 0, 1, 0 );
|
||||
Matrix4x4_ConcatRotate( m, -RI.rvp.viewangles[1], 0, 0, 1 );
|
||||
}
|
||||
Matrix4x4_ConcatTranslate( m, -RI.rvp.vieworigin[0], -RI.rvp.vieworigin[1], -RI.rvp.vieworigin[2] );
|
||||
}
|
||||
|
||||
void R_LoadIdentity( void )
|
||||
{
|
||||
if( tr.modelviewIdentity ) return;
|
||||
|
||||
Matrix4x4_LoadIdentity( RI.objectMatrix );
|
||||
Matrix4x4_Copy( RI.modelviewMatrix, RI.worldviewMatrix );
|
||||
|
||||
//TODO GL_LoadMatrix( MODELVIEW, RI.modelviewMatrix );
|
||||
tr.modelviewIdentity = true;
|
||||
}
|
||||
|
||||
void R_GammaChanged( qboolean do_reset_gamma )
|
||||
{
|
||||
if( do_reset_gamma )
|
||||
{
|
||||
// paranoia cubemap rendering
|
||||
if( gEngfuncs.drawFuncs->GL_BuildLightmaps )
|
||||
gEngfuncs.drawFuncs->GL_BuildLightmaps( );
|
||||
}
|
||||
else
|
||||
{
|
||||
//GL_RebuildLightmaps();
|
||||
}
|
||||
}
|
||||
|
||||
void R_BeginFrame( qboolean clearScene )
|
||||
{
|
||||
if(( gl_clear->value || ENGINE_GET_PARM( PARM_DEV_OVERVIEW )) &&
|
||||
clearScene && ENGINE_GET_PARM( PARM_CONNSTATE ) != ca_cinematic )
|
||||
{
|
||||
D3DRECT rect = {
|
||||
.x1 = 0,
|
||||
.y1 = 0,
|
||||
.x2 = dxc.windowWidth,
|
||||
.y2 = dxc.windowHeight,
|
||||
};
|
||||
DXCheck(IDirect3DViewport_Clear(dxc.viewport, 1, &rect, D3DCLEAR_TARGET));
|
||||
}
|
||||
|
||||
R_Set2DMode( true );
|
||||
|
||||
gEngfuncs.CL_ExtraUpdate();
|
||||
}
|
||||
|
||||
static void R_DrawEntitiesOnList( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void R_RenderScene( void )
|
||||
{
|
||||
if( !tr.worldmodel && FBitSet( RI.rvp.flags, RF_DRAW_WORLD ) )
|
||||
gEngfuncs.Host_Error("%s: NULL worldmodel\n", __func__);
|
||||
|
||||
// frametime is valid only for normal pass
|
||||
if( !FBitSet( RI.rvp.flags, RF_DRAW_CUBEMAP ))
|
||||
tr.frametime = gp_cl->time - gp_cl->oldtime;
|
||||
else tr.frametime = 0.0;
|
||||
|
||||
// begin a new frame
|
||||
tr.framecount++;
|
||||
|
||||
tr.dlightframecount = R_PushDlights( tr.worldmodel, tr.framecount );
|
||||
|
||||
R_SetupFrustum();
|
||||
#if 0
|
||||
R_SetupFrame();
|
||||
#endif
|
||||
R_SetupD3D(true);
|
||||
R_Clear(~0);
|
||||
R_MarkLeaves();
|
||||
#if 0
|
||||
R_DrawFog();
|
||||
if( FBitSet( RI.rvp.flags, RF_DRAW_WORLD ))
|
||||
R_AnimateRipples();
|
||||
|
||||
R_CheckGLFog();
|
||||
#endif
|
||||
R_DrawWorld();
|
||||
|
||||
// R_CheckFog();
|
||||
|
||||
gEngfuncs.CL_ExtraUpdate(); // don't let sound get messed up if going slow
|
||||
|
||||
R_DrawEntitiesOnList();
|
||||
|
||||
// R_DrawWaterSurfaces();
|
||||
|
||||
}
|
||||
|
||||
void R_EndFrame( void )
|
||||
{
|
||||
|
||||
if (!dxc.window)
|
||||
return;
|
||||
|
||||
R_Set2DMode( false );
|
||||
|
||||
//swap
|
||||
if (dxc.pddsBack)
|
||||
{
|
||||
RECT dstRect = { 0 };
|
||||
POINT point = { 0,0 };
|
||||
ClientToScreen(dxc.window, &point);
|
||||
GetClientRect(dxc.window, &dstRect);
|
||||
OffsetRect(&dstRect, point.x, point.y);
|
||||
|
||||
RECT srcRect = { 0,0,dxc.windowWidth,dxc.windowHeight };
|
||||
DXCheck(IDirectDrawSurface_Blt(dxc.pddsPrimary, &dstRect, dxc.pddsBack, &srcRect, DDBLT_WAIT, NULL));
|
||||
}
|
||||
|
||||
//resize
|
||||
RECT rect = { 0 };
|
||||
GetClientRect(dxc.window, &rect);
|
||||
int w = rect.right - rect.left;
|
||||
int h = rect.bottom - rect.top;
|
||||
|
||||
if (w != dxc.windowWidth || h != dxc.windowHeight)
|
||||
{
|
||||
D3D_Resize(w, h);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void R_AllowFog( qboolean allowed )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void R_SetupRefParams( const ref_viewpass_t *rvp )
|
||||
{
|
||||
RI.rvp = *rvp;
|
||||
|
||||
RI.farClip = 0;
|
||||
}
|
||||
|
||||
|
||||
void R_RenderFrame( const ref_viewpass_t *rvp )
|
||||
{
|
||||
if( r_norefresh->value )
|
||||
return;
|
||||
|
||||
// setup the initial render params
|
||||
R_SetupRefParams( rvp );
|
||||
|
||||
// completely override rendering
|
||||
if( gEngfuncs.drawFuncs->GL_RenderFrame != NULL )
|
||||
{
|
||||
tr.fCustomRendering = true;
|
||||
|
||||
if( gEngfuncs.drawFuncs->GL_RenderFrame( rvp ))
|
||||
{
|
||||
R_GatherPlayerLight( tr.viewent );
|
||||
tr.realframecount++;
|
||||
tr.fResetVis = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
tr.fCustomRendering = false;
|
||||
#if 0
|
||||
if( !FBitSet( RI.rvp.flags, RF_ONLY_CLIENTDRAW ))
|
||||
R_RunViewmodelEvents();
|
||||
#endif
|
||||
|
||||
tr.realframecount++; // right called after viewmodel events
|
||||
R_RenderScene();
|
||||
}
|
||||
|
||||
|
||||
qboolean R_AddEntity( struct cl_entity_s *clent, int type )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void R_ClearScene( void )
|
||||
{
|
||||
tr.draw_list->num_solid_entities = 0;
|
||||
tr.draw_list->num_trans_entities = 0;
|
||||
tr.draw_list->num_beam_entities = 0;
|
||||
|
||||
// clear the scene befor start new frame
|
||||
if (gEngfuncs.drawFuncs->R_ClearScene != NULL)
|
||||
gEngfuncs.drawFuncs->R_ClearScene();
|
||||
}
|
||||
|
||||
|
||||
int WorldToScreen( const vec3_t world, vec3_t screen )
|
||||
{
|
||||
VectorClear( screen );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void R_SetupD3D( qboolean set_state )
|
||||
{
|
||||
R_SetupModelviewMatrix( RI.worldviewMatrix );
|
||||
R_SetupProjectionMatrix( RI.projectionMatrix );
|
||||
|
||||
Matrix4x4_Concat( RI.worldviewProjectionMatrix, RI.projectionMatrix, RI.worldviewMatrix );
|
||||
|
||||
if( !set_state ) return;
|
||||
|
||||
D3DVIEWPORT viewport = { 0 };
|
||||
viewport.dwSize = sizeof(viewport);
|
||||
|
||||
if( !FBitSet( RI.rvp.flags, RF_DRAW_CUBEMAP ))
|
||||
{
|
||||
int x, x2, y, y2;
|
||||
|
||||
// set up viewport (main, playersetup)
|
||||
x = floor( RI.rvp.viewport[0] * gpGlobals->width / gpGlobals->width );
|
||||
x2 = ceil( (RI.rvp.viewport[0] + RI.rvp.viewport[2]) * gpGlobals->width / gpGlobals->width );
|
||||
y = floor( gpGlobals->height - RI.rvp.viewport[1] * gpGlobals->height / gpGlobals->height );
|
||||
y2 = ceil( gpGlobals->height - (RI.rvp.viewport[1] + RI.rvp.viewport[3]) * gpGlobals->height / gpGlobals->height );
|
||||
|
||||
if( tr.rotation & 1 )
|
||||
{
|
||||
viewport.dwX = y2;
|
||||
viewport.dwY = x;
|
||||
viewport.dwWidth = y - y2;
|
||||
viewport.dwHeight = x2 - x;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewport.dwX = x;
|
||||
viewport.dwY = y2;
|
||||
viewport.dwWidth = x2 - x;
|
||||
viewport.dwHeight = y - y2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// envpass, mirrorpass
|
||||
viewport.dwX = RI.rvp.viewport[0];
|
||||
viewport.dwY = RI.rvp.viewport[1];
|
||||
viewport.dwWidth = RI.rvp.viewport[2];
|
||||
viewport.dwHeight = RI.rvp.viewport[3];
|
||||
}
|
||||
|
||||
viewport.dvScaleX = 0.5f * viewport.dwWidth;
|
||||
viewport.dvScaleY = 0.5f * viewport.dwHeight;
|
||||
viewport.dvMaxX = 1;//calc for partial views
|
||||
viewport.dvMaxY = 1;
|
||||
viewport.dvMinZ = 0;
|
||||
viewport.dvMaxZ = 1;
|
||||
DXCheck(IDirect3DViewport_SetViewport(dxc.viewport, &viewport));
|
||||
|
||||
{
|
||||
float dest[16];
|
||||
Matrix4x4_ToArrayFloatGL(RI.projectionMatrix, dest);
|
||||
DXCheck(IDirect3DDevice_SetMatrix(dxc.pd3dd, dxc.mtxProjection, (D3DMATRIX *)&dest));
|
||||
Matrix4x4_ToArrayFloatGL(RI.worldviewMatrix, dest);
|
||||
DXCheck(IDirect3DDevice_SetMatrix(dxc.pd3dd, dxc.mtxWorld, (D3DMATRIX *)&dest));
|
||||
}
|
||||
}
|
||||
625
ref/dx2/r_surf.c
Normal file
625
ref/dx2/r_surf.c
Normal file
@@ -0,0 +1,625 @@
|
||||
/*
|
||||
r_surf.c - surface-related refresh code
|
||||
Copyright (C) 2025-2026 lewa_j
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "r_local.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
|
||||
|
||||
void GL_OrthoBounds( const float *mins, const float *maxs )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
byte *Mod_GetCurrentVis( void )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void R_LightmapCoord( const vec3_t v, const msurface_t *surf, const float sample_size, vec2_t coords )
|
||||
{
|
||||
const mextrasurf_t *info = surf->info;
|
||||
float s, t;
|
||||
|
||||
#define BLOCK_SIZE 256
|
||||
|
||||
s = DotProduct( v, info->lmvecs[0] ) + info->lmvecs[0][3] - info->lightmapmins[0];
|
||||
s += surf->light_s * sample_size;
|
||||
s += sample_size * 0.5f;
|
||||
s /= BLOCK_SIZE * sample_size;
|
||||
|
||||
t = DotProduct( v, info->lmvecs[1] ) + info->lmvecs[1][3] - info->lightmapmins[1];
|
||||
t += surf->light_t * sample_size;
|
||||
t += sample_size * 0.5f;
|
||||
t /= BLOCK_SIZE * sample_size;
|
||||
|
||||
#undef BLOCK_SIZE
|
||||
|
||||
Vector2Set( coords, s, t );
|
||||
}
|
||||
|
||||
static void R_TextureCoord( const vec3_t v, const msurface_t *surf, vec2_t coords )
|
||||
{
|
||||
const mtexinfo_t *info = surf->texinfo;
|
||||
float s, t;
|
||||
|
||||
s = DotProduct( v, info->vecs[0] );
|
||||
t = DotProduct( v, info->vecs[1] );
|
||||
|
||||
if( !FBitSet( surf->flags, SURF_DRAWTURB ))
|
||||
{
|
||||
s = ( s + info->vecs[0][3] ) / info->texture->width;
|
||||
t = ( t + info->vecs[1][3] ) / info->texture->height;
|
||||
}
|
||||
|
||||
Vector2Set( coords, s, t );
|
||||
}
|
||||
|
||||
static void R_GetEdgePosition( const model_t *mod, const msurface_t *fa, int i, vec3_t vec )
|
||||
{
|
||||
const int lindex = mod->surfedges[fa->firstedge + i];
|
||||
|
||||
if( FBitSet( mod->flags, MODEL_QBSP2 ))
|
||||
{
|
||||
const medge32_t *pedges = mod->edges32;
|
||||
|
||||
if( lindex > 0 )
|
||||
VectorCopy( mod->vertexes[pedges[lindex].v[0]].position, vec );
|
||||
else
|
||||
VectorCopy( mod->vertexes[pedges[-lindex].v[1]].position, vec );
|
||||
}
|
||||
else
|
||||
{
|
||||
const medge16_t *pedges = mod->edges16;
|
||||
|
||||
if( lindex > 0 )
|
||||
VectorCopy( mod->vertexes[pedges[lindex].v[0]].position, vec );
|
||||
else
|
||||
VectorCopy( mod->vertexes[pedges[-lindex].v[1]].position, vec );
|
||||
}
|
||||
}
|
||||
|
||||
void GL_SubdivideSurface( model_t *mod, msurface_t *fa )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
GL_BuildPolygonFromSurface
|
||||
================
|
||||
*/
|
||||
static int GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa )
|
||||
{
|
||||
int i, lnumverts, nColinElim = 0;
|
||||
float sample_size;
|
||||
texture_t *tex;
|
||||
dx_texture_t *dxt;
|
||||
glpoly2_t *poly;
|
||||
|
||||
if( !mod || !fa->texinfo || !fa->texinfo->texture )
|
||||
return nColinElim; // bad polygon ?
|
||||
|
||||
if( FBitSet( fa->flags, SURF_CONVEYOR ) && fa->texinfo->texture->gl_texturenum != 0 )
|
||||
{
|
||||
dxt = R_GetTexture( fa->texinfo->texture->gl_texturenum );
|
||||
tex = fa->texinfo->texture;
|
||||
Assert( dxt != NULL && tex != NULL );
|
||||
|
||||
// update conveyor widths for keep properly speed of scrolling
|
||||
dxt->srcWidth = tex->width;
|
||||
dxt->srcHeight = tex->height;
|
||||
}
|
||||
|
||||
sample_size = gEngfuncs.Mod_SampleSizeForFace( fa );
|
||||
|
||||
// reconstruct the polygon
|
||||
lnumverts = fa->numedges;
|
||||
|
||||
// detach if already created, reconstruct again
|
||||
poly = fa->polys;
|
||||
fa->polys = NULL;
|
||||
|
||||
// quake simple models (healthkits etc) need to be reconstructed their polys because LM coords has changed after the map change
|
||||
poly = Mem_Realloc( mod->mempool, poly, sizeof( glpoly2_t ) + lnumverts * VERTEXSIZE * sizeof( float ));
|
||||
poly->next = fa->polys;
|
||||
poly->flags = fa->flags;
|
||||
fa->polys = poly;
|
||||
poly->numverts = lnumverts;
|
||||
|
||||
for( i = 0; i < lnumverts; i++ )
|
||||
{
|
||||
R_GetEdgePosition( mod, fa, i, poly->verts[i] );
|
||||
R_TextureCoord( poly->verts[i], fa, &poly->verts[i][3] );
|
||||
R_LightmapCoord( poly->verts[i], fa, sample_size, &poly->verts[i][5] );
|
||||
}
|
||||
|
||||
// TODO or not TODO gl_keeptjunctions?
|
||||
|
||||
poly->numverts = lnumverts;
|
||||
return nColinElim;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_TextureAnimation
|
||||
|
||||
Returns the proper texture for a given time and surface
|
||||
===============
|
||||
*/
|
||||
static texture_t *R_TextureAnimation( msurface_t *s )
|
||||
{
|
||||
texture_t *base = s->texinfo->texture;
|
||||
// TODO
|
||||
return base;
|
||||
}
|
||||
|
||||
static void DrawGLPoly( glpoly2_t *p, float xScale, float yScale )
|
||||
{
|
||||
float *v;
|
||||
float sOffset, sy;
|
||||
float tOffset, cy;
|
||||
cl_entity_t *e = RI.currententity;
|
||||
int i, hasScale = false;
|
||||
|
||||
if( !p ) return;
|
||||
|
||||
{
|
||||
sOffset = tOffset = 0.0f;
|
||||
}
|
||||
|
||||
if( xScale != 0.0f && yScale != 0.0f )
|
||||
hasScale = true;
|
||||
|
||||
d3dEBContext_t ebc = { 0 };
|
||||
if( !D3D_StartExecuteBuffer( &ebc ))
|
||||
return;
|
||||
|
||||
void *cur = ebc.data;
|
||||
|
||||
D3DLVERTEX* verts = (D3DLVERTEX*)cur;
|
||||
|
||||
for( i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE )
|
||||
{
|
||||
D3DLVERTEX *dv = verts + i;
|
||||
if( hasScale )
|
||||
{
|
||||
dv->tu = ( v[3] + sOffset ) * xScale;
|
||||
dv->tv = ( v[4] + tOffset ) * yScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
dv->tu = v[3] + sOffset;
|
||||
dv->tv = v[4] + tOffset;
|
||||
}
|
||||
|
||||
dv->x = v[0];
|
||||
dv->y = v[1];
|
||||
dv->z = v[2];
|
||||
dv->color = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
cur = (void*)(((D3DTLVERTEX*)cur) + p->numverts);
|
||||
|
||||
void* insStart = cur;
|
||||
|
||||
D3D_PutProcessVertices(&cur, D3DPROCESSVERTICES_TRANSFORM | D3DPROCESSVERTICES_UPDATEEXTENTS, 0, p->numverts);
|
||||
|
||||
D3D_PutInstruction(&cur, D3DOP_STATERENDER, sizeof(D3DSTATE), 4);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_TEXTUREHANDLE, dxc.currentTexture);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_DECAL);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_BLENDENABLE, FALSE);
|
||||
D3D_PutRenderState(&cur, D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
|
||||
|
||||
// align
|
||||
if (((ULONG)cur) & 7) {
|
||||
D3D_PutInstruction(&cur, D3DOP_TRIANGLE, sizeof(D3DTRIANGLE), 0);
|
||||
}
|
||||
D3D_PutInstruction(&cur, D3DOP_TRIANGLE, sizeof(D3DTRIANGLE), p->numverts - 2);
|
||||
|
||||
for (i = 0; i < p->numverts; i++)
|
||||
{
|
||||
D3D_SetTri(cur, 0, i + 1, i + 2);
|
||||
cur = (void*)(((D3DTRIANGLE*)cur) + 1);
|
||||
}
|
||||
|
||||
D3D_PutInstruction(&cur, D3DOP_EXIT, 0, 0);
|
||||
|
||||
ebc.vertCount = p->numverts;
|
||||
ebc.insOffset = ((char*)insStart - (char*)ebc.data);
|
||||
ebc.insLength = ((char*)cur - (char*)insStart);
|
||||
|
||||
if( !D3D_EndExecuteBuffer( &ebc ))
|
||||
return;
|
||||
|
||||
DXCheck(IDirect3DDevice_BeginScene(dxc.pd3dd));
|
||||
DXCheck(IDirect3DDevice_Execute(dxc.pd3dd, ebc.pd3deb, dxc.viewport, D3DEXECUTE_CLIPPED));
|
||||
DXCheck(IDirect3DDevice_EndScene(dxc.pd3dd));
|
||||
|
||||
D3D_ReleaseExecuteBuffer( &ebc );
|
||||
//
|
||||
|
||||
//if( FBitSet( p->flags, SURF_DRAWTILED ))
|
||||
// GL_SetupFogColorForSurfaces();
|
||||
}
|
||||
|
||||
static void R_RenderBrushPoly( msurface_t *fa, int cull_type )
|
||||
{
|
||||
texture_t *t;
|
||||
|
||||
//r_stats.c_world_polys++;
|
||||
|
||||
if( fa->flags & SURF_DRAWSKY )
|
||||
return; // already handled
|
||||
|
||||
t = R_TextureAnimation( fa );
|
||||
|
||||
GL_Bind( XASH_TEXTURE0, t->gl_texturenum );
|
||||
|
||||
DrawGLPoly( fa->polys, 0.0f, 0.0f );
|
||||
}
|
||||
|
||||
static void R_DrawTextureChains( void )
|
||||
{
|
||||
int i;
|
||||
msurface_t *s;
|
||||
texture_t *t;
|
||||
|
||||
// make sure what color is reset
|
||||
Vector4Set( dxc.currentColor, 1, 1, 1, 1 );
|
||||
R_LoadIdentity(); // set identity matrix
|
||||
|
||||
//GL_SetupFogColorForSurfaces();
|
||||
|
||||
// restore worldmodel
|
||||
RI.currententity = CL_GetEntityByIndex( 0 );
|
||||
RI.currentmodel = RI.currententity->model;
|
||||
|
||||
for( i = 0; i < tr.worldmodel->numtextures; i++ )
|
||||
{
|
||||
t = tr.worldmodel->textures[i];
|
||||
if( !t ) continue;
|
||||
|
||||
s = t->texturechain;
|
||||
|
||||
if( !s || ( i == tr.skytexturenum ))
|
||||
continue;
|
||||
|
||||
for( ; s != NULL; s = s->texturechain )
|
||||
R_RenderBrushPoly( s, CULL_VISIBLE );
|
||||
t->texturechain = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_CullSurface
|
||||
|
||||
cull invisible surfaces
|
||||
=================
|
||||
*/
|
||||
static int R_CullSurface( msurface_t *surf, gl_frustum_t *frustum, uint clipflags )
|
||||
{
|
||||
cl_entity_t *e = RI.currententity;
|
||||
|
||||
if( !surf || !surf->texinfo || !surf->texinfo->texture )
|
||||
return CULL_OTHER;
|
||||
|
||||
//TODO
|
||||
return CULL_VISIBLE;
|
||||
}
|
||||
|
||||
static void R_RecursiveWorldNode( mnode_t *node, uint clipflags )
|
||||
{
|
||||
int i, clipped;
|
||||
msurface_t *surf, **mark;
|
||||
mleaf_t *pleaf;
|
||||
int c, side;
|
||||
float dot;
|
||||
mnode_t *children[2];
|
||||
int numsurfaces, firstsurface;
|
||||
|
||||
loc0:
|
||||
if( node->contents == CONTENTS_SOLID )
|
||||
return; // hit a solid leaf
|
||||
|
||||
if( node->visframe != tr.visframecount )
|
||||
return;
|
||||
|
||||
if( clipflags && !r_nocull.value )
|
||||
{
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
const mplane_t *p = &RI.frustum.planes[i];
|
||||
|
||||
if( !FBitSet( clipflags, BIT( i )))
|
||||
continue;
|
||||
|
||||
clipped = BoxOnPlaneSide( node->minmaxs, node->minmaxs + 3, p );
|
||||
if( clipped == 2 ) return;
|
||||
if( clipped == 1 ) ClearBits( clipflags, BIT( i ));
|
||||
}
|
||||
}
|
||||
|
||||
// if a leaf node, draw stuff
|
||||
if( node->contents < 0 )
|
||||
{
|
||||
pleaf = (mleaf_t *)node;
|
||||
|
||||
mark = pleaf->firstmarksurface;
|
||||
c = pleaf->nummarksurfaces;
|
||||
|
||||
if( c )
|
||||
{
|
||||
do
|
||||
{
|
||||
(*mark)->visframe = tr.framecount;
|
||||
mark++;
|
||||
} while( --c );
|
||||
}
|
||||
|
||||
// deal with model fragments in this leaf
|
||||
if( pleaf->efrags )
|
||||
gEngfuncs.R_StoreEfrags( &pleaf->efrags, tr.realframecount );
|
||||
|
||||
// r_stats.c_world_leafs++;
|
||||
return;
|
||||
}
|
||||
|
||||
// node is just a decision point, so go down the apropriate sides
|
||||
|
||||
// find which side of the node we are on
|
||||
dot = PlaneDiff( tr.modelorg, node->plane );
|
||||
side = (dot >= 0.0f) ? 0 : 1;
|
||||
|
||||
// recurse down the children, front side first
|
||||
node_children( children, node, tr.worldmodel );
|
||||
R_RecursiveWorldNode( children[side], clipflags );
|
||||
|
||||
firstsurface = node_firstsurface( node, tr.worldmodel );
|
||||
numsurfaces = node_numsurfaces( node, tr.worldmodel );
|
||||
|
||||
// draw stuff
|
||||
for( c = numsurfaces, surf = tr.worldmodel->surfaces + firstsurface; c; c--, surf++ )
|
||||
{
|
||||
if( R_CullSurface( surf, &RI.frustum, clipflags ))
|
||||
continue;
|
||||
|
||||
if( surf->flags & SURF_DRAWSKY )
|
||||
{
|
||||
#if 0
|
||||
// make sky chain to right clip the skybox
|
||||
surf->texturechain = skychain;
|
||||
skychain = surf;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
surf->texturechain = surf->texinfo->texture->texturechain;
|
||||
surf->texinfo->texture->texturechain = surf;
|
||||
}
|
||||
}
|
||||
|
||||
// recurse down the back side
|
||||
node = children[!side];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
|
||||
void R_DrawWorld( void )
|
||||
{
|
||||
double start, end;
|
||||
|
||||
// paranoia issues: when gl_renderer is "0" we need have something valid for currententity
|
||||
// to prevent crashing until HeadShield drawing.
|
||||
RI.currententity = CL_GetEntityByIndex( 0 );
|
||||
if( !RI.currententity )
|
||||
return;
|
||||
|
||||
RI.currentmodel = RI.currententity->model;
|
||||
if( !FBitSet( RI.rvp.flags, RF_DRAW_WORLD ) || FBitSet( RI.rvp.flags, RF_ONLY_CLIENTDRAW ))
|
||||
return;
|
||||
|
||||
VectorCopy( RI.cullorigin, tr.modelorg );
|
||||
//memset( gl_lms.lightmap_surfaces, 0, sizeof( gl_lms.lightmap_surfaces ));
|
||||
//memset( fullbright_surfaces, 0, sizeof( fullbright_surfaces ));
|
||||
//memset( detail_surfaces, 0, sizeof( detail_surfaces ));
|
||||
|
||||
//gl_lms.dynamic_surfaces = NULL;
|
||||
tr.blend = 1.0f;
|
||||
|
||||
//R_ClearSkyBox ();
|
||||
|
||||
start = gEngfuncs.pfnTime();
|
||||
if( FBitSet( RI.rvp.flags, RF_DRAW_OVERVIEW ))
|
||||
{
|
||||
//R_DrawWorldTopView( tr.worldmodel->nodes, RI.frustum.clipFlags );
|
||||
}
|
||||
else R_RecursiveWorldNode( tr.worldmodel->nodes, RI.frustum.clipFlags );
|
||||
end = gEngfuncs.pfnTime();
|
||||
|
||||
//r_stats.t_world_node = end - start;
|
||||
|
||||
start = gEngfuncs.pfnTime();
|
||||
|
||||
R_DrawTextureChains();
|
||||
|
||||
end = gEngfuncs.pfnTime();
|
||||
|
||||
//r_stats.t_world_draw = end - start;
|
||||
//tr.num_draw_decals = 0;
|
||||
//skychain = NULL;
|
||||
|
||||
gEngfuncs.R_DrawWorldHull();
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_MarkLeaves
|
||||
|
||||
Mark the leaves and nodes that are in the PVS for the current leaf
|
||||
===============
|
||||
*/
|
||||
void R_MarkLeaves( void )
|
||||
{
|
||||
qboolean novis = false;
|
||||
qboolean force = false;
|
||||
mleaf_t *leaf = NULL;
|
||||
mnode_t *node;
|
||||
vec3_t test;
|
||||
int i;
|
||||
|
||||
if( !FBitSet( RI.rvp.flags, RF_DRAW_WORLD ) ) return;
|
||||
|
||||
if( FBitSet( r_novis.flags, FCVAR_CHANGED ) || tr.fResetVis )
|
||||
{
|
||||
// force recalc viewleaf
|
||||
ClearBits( r_novis.flags, FCVAR_CHANGED );
|
||||
tr.fResetVis = false;
|
||||
RI.viewleaf = NULL;
|
||||
}
|
||||
|
||||
VectorCopy( RI.rvp.vieworigin, test );
|
||||
|
||||
if( RI.viewleaf != NULL )
|
||||
{
|
||||
// merge two leafs that can be a crossed-line contents
|
||||
if( RI.viewleaf->contents == CONTENTS_EMPTY )
|
||||
VectorSet( test, RI.rvp.vieworigin[0], RI.rvp.vieworigin[1], RI.rvp.vieworigin[2] - 16.0f );
|
||||
else
|
||||
VectorSet( test, RI.rvp.vieworigin[0], RI.rvp.vieworigin[1], RI.rvp.vieworigin[2] + 16.0f );
|
||||
|
||||
leaf = gEngfuncs.Mod_PointInLeaf( test, tr.worldmodel->nodes, tr.worldmodel );
|
||||
|
||||
if(( leaf->contents != CONTENTS_SOLID ) && ( RI.viewleaf != leaf ))
|
||||
force = true;
|
||||
}
|
||||
|
||||
if( RI.viewleaf == RI.oldviewleaf && RI.viewleaf != NULL && !force )
|
||||
return;
|
||||
|
||||
// development aid to let you run around
|
||||
// and see exactly where the pvs ends
|
||||
if( r_lockpvs.value ) return;
|
||||
|
||||
RI.oldviewleaf = RI.viewleaf;
|
||||
tr.visframecount++;
|
||||
|
||||
if( r_novis.value || FBitSet( RI.rvp.flags, RF_DRAW_OVERVIEW ) || !RI.viewleaf || !tr.worldmodel->visdata )
|
||||
novis = true;
|
||||
|
||||
gEngfuncs.R_FatPVS( RI.rvp.vieworigin, r_pvs_radius->value, RI.visbytes, false, novis );
|
||||
if( force && !novis )
|
||||
gEngfuncs.R_FatPVS( test, r_pvs_radius->value, RI.visbytes, true, novis );
|
||||
|
||||
for( i = 0; i < tr.worldmodel->numleafs; i++ )
|
||||
{
|
||||
if( CHECKVISBIT( RI.visbytes, i ))
|
||||
{
|
||||
node = (mnode_t *)&tr.worldmodel->leafs[i+1];
|
||||
do
|
||||
{
|
||||
if( node->visframe == tr.visframecount )
|
||||
break;
|
||||
node->visframe = tr.visframecount;
|
||||
node = node->parent;
|
||||
} while( node );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
GL_BuildLightmaps
|
||||
|
||||
Builds the lightmap texture
|
||||
with all the surfaces from all brush models
|
||||
==================
|
||||
*/
|
||||
void GL_BuildLightmaps( void )
|
||||
{
|
||||
int i, j, nColinElim = 0;
|
||||
model_t *m;
|
||||
#if 0
|
||||
// release old lightmaps
|
||||
for( i = 0; i < MAX_LIGHTMAPS; i++ )
|
||||
{
|
||||
if( !tr.lightmapTextures[i] ) break;
|
||||
GL_FreeTexture( tr.lightmapTextures[i] );
|
||||
}
|
||||
|
||||
memset( tr.lightmapTextures, 0, sizeof( tr.lightmapTextures ));
|
||||
#endif
|
||||
memset( &RI, 0, sizeof( RI ));
|
||||
#if 0
|
||||
// update the lightmap blocksize
|
||||
if( FBitSet( gp_host->features, ENGINE_LARGE_LIGHTMAPS ) || tr.world->version == QBSP2_VERSION || r_large_lightmaps.value )
|
||||
tr.block_size = BLOCK_SIZE_MAX;
|
||||
else tr.block_size = BLOCK_SIZE_DEFAULT;
|
||||
|
||||
skychain = NULL;
|
||||
#endif
|
||||
tr.framecount = tr.visframecount = 1; // no dlight cache
|
||||
//gl_lms.current_lightmap_texture = 0;
|
||||
tr.modelviewIdentity = false;
|
||||
tr.realframecount = 1;
|
||||
#if 0
|
||||
// setup the texture for dlights
|
||||
R_InitDlightTexture();
|
||||
|
||||
// setup all the lightstyles
|
||||
CL_RunLightStyles((lightstyle_t *)ENGINE_GET_PARM( PARM_GET_LIGHTSTYLES_PTR ));
|
||||
|
||||
LM_InitBlock();
|
||||
#endif
|
||||
for( i = 0; i < gp_cl->nummodels; i++ )
|
||||
{
|
||||
if(( m = CL_ModelHandle( i + 1 )) == NULL )
|
||||
continue;
|
||||
|
||||
if( m->name[0] == '*' || m->type != mod_brush )
|
||||
continue;
|
||||
|
||||
for( j = 0; j < m->numsurfaces; j++ )
|
||||
{
|
||||
// clearing all decal chains
|
||||
m->surfaces[j].pdecals = NULL;
|
||||
m->surfaces[j].visframe = 0;
|
||||
|
||||
//GL_CreateSurfaceLightmap( m->surfaces + j, m );
|
||||
|
||||
if( m->surfaces[j].flags & SURF_DRAWTURB )
|
||||
continue;
|
||||
|
||||
nColinElim += GL_BuildPolygonFromSurface( m, m->surfaces + j );
|
||||
}
|
||||
|
||||
// clearing visframe
|
||||
for( j = 0; j < m->numleafs; j++ )
|
||||
m->leafs[j+1].visframe = 0;
|
||||
for( j = 0; j < m->numnodes; j++ )
|
||||
m->nodes[j].visframe = 0;
|
||||
}
|
||||
|
||||
//LM_UploadBlock( false );
|
||||
|
||||
if( gEngfuncs.drawFuncs->GL_BuildLightmaps )
|
||||
{
|
||||
// build lightmaps on the client-side
|
||||
gEngfuncs.drawFuncs->GL_BuildLightmaps( );
|
||||
}
|
||||
}
|
||||
18
ref/dx2/wscript
Normal file
18
ref/dx2/wscript
Normal file
@@ -0,0 +1,18 @@
|
||||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
# mittorn, 2018
|
||||
|
||||
def options(opt):
|
||||
pass
|
||||
|
||||
def configure(conf):
|
||||
pass
|
||||
|
||||
def build(bld):
|
||||
bld.shlib(
|
||||
source = ['r_context.c', 'r_image.c', 'r_d3d.c', 'r_main.c', 'r_draw.c', 'r_surf.c', 'r_frustum.c'],
|
||||
target = 'ref_dx2',
|
||||
defines = 'REF_DLL',
|
||||
use = 'ref_common engine_includes sdk_includes werror public USER32 DDRAW',
|
||||
install_path = bld.env.LIBDIR
|
||||
)
|
||||
4
wscript
4
wscript
@@ -118,6 +118,7 @@ SUBDIRS = [
|
||||
Subproject('ref/common', lambda x: x.env.CLIENT),
|
||||
Subproject('ref/gl', lambda x: x.env.CLIENT and (x.env.GL or x.env.NANOGL or x.env.GLWES or x.env.GL4ES or x.env.GLES3COMPAT)),
|
||||
Subproject('ref/soft', lambda x: x.env.CLIENT and x.env.SOFT),
|
||||
Subproject('ref/dx2', lambda x: x.env.CLIENT and x.env.DX2),
|
||||
Subproject('ref/null', lambda x: x.env.CLIENT and x.env.NULL),
|
||||
Subproject('3rdparty/bzip2', lambda x: x.env.CLIENT and not x.env.HAVE_SYSTEM_BZ2),
|
||||
Subproject('3rdparty/mbedtls'),
|
||||
@@ -151,6 +152,7 @@ REFDLLS = [
|
||||
RefDll('gl4es', False),
|
||||
RefDll('gles3compat', False, 'GLES3COMPAT'),
|
||||
RefDll('null', False),
|
||||
RefDll('dx2', False),
|
||||
]
|
||||
|
||||
def options(opt):
|
||||
@@ -495,7 +497,7 @@ def configure(conf):
|
||||
# Don't check them more than once, to save time
|
||||
# Usually, they are always available
|
||||
# but we need them in uselib
|
||||
a = [ 'user32', 'shell32', 'gdi32', 'advapi32', 'dbghelp', 'psapi', 'ws2_32', 'bcrypt' ]
|
||||
a = [ 'user32', 'shell32', 'gdi32', 'advapi32', 'dbghelp', 'psapi', 'ws2_32', 'bcrypt', 'ddraw' ]
|
||||
if conf.env.COMPILER_CC == 'msvc':
|
||||
for i in a:
|
||||
conf.start_msg('Checking for MSVC library')
|
||||
|
||||
Reference in New Issue
Block a user