preliminary support for qc rendertargets with d3d11. I took some shortcuts so try not to combine it with other render target stuff just yet.

flipped gl qc rendertargets to logically be top-down. the joys of weird matricies is a sight to behold.
try to fix threading dependency on recent versions of windows.
break some other related stuff.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4768 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2014-10-14 16:42:48 +00:00
parent 4461fb7759
commit dbfd69f572
20 changed files with 336 additions and 157 deletions

View File

@ -844,7 +844,7 @@ void VARGS Con_Printf (const char *fmt, ...)
vsnprintf (msg,sizeof(msg), fmt,argptr);
va_end (argptr);
if (!Sys_IsThread(NULL))
if (!Sys_IsMainThread())
{
COM_AddWork(0, Con_PrintFromThread, NULL, Z_StrDup(msg), 0, 0);
return;

View File

@ -3368,6 +3368,26 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag
switch(fmt)
{
case TF_DEPTH16:
mips->encoding = PTI_DEPTH16;
break;
case TF_DEPTH24:
mips->encoding = PTI_DEPTH24;
break;
case TF_DEPTH32:
mips->encoding = PTI_DEPTH32;
break;
case TF_RGBA16F:
case TF_RGBA32F:
if (rawdata)
{
Con_Printf("R_LoadRawTexture: bad format");
if (freedata)
BZ_Free(rawdata);
return false;
}
break;
default:
case TF_INVALID:
Con_Printf("R_LoadRawTexture: bad format");

View File

@ -1312,7 +1312,7 @@ void R2D_DrawCrosshair(void)
R2D_ImageColours(1, 1, 1, 1);
}
#define RT_IMAGEFLAGS IF_NOMIPMAP|IF_CLAMP|IF_LINEAR
#define RT_IMAGEFLAGS IF_NOMIPMAP|IF_CLAMP|IF_LINEAR|IF_RENDERTARGET
static texid_t internalrt;
//resize a texture for a render target and specify the format of it.
//pass TF_INVALID and sizes=0 to get without configuring (shaders that hardcode an $rt1 etc).

View File

@ -258,6 +258,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
//software rendering is just too glitchy, don't use it.
#if defined(SWQUAKE) && !defined(_DEBUG)
#undef SWQUAKE
#endif
//include a file to update the various configurations for game-specific configs (hopefully just names)
#ifdef BRANDING_INC
#define STRINGIFY2(s) #s

View File

@ -202,7 +202,7 @@ void Cbuf_AddText (const char *text, int level)
{
int l;
if (!Sys_IsThread(NULL))
if (!Sys_IsMainThread())
{
COM_AddWork(0, Cbuf_WorkerAddText, NULL, Z_StrDup(text), level, 0);
return;

View File

@ -4710,7 +4710,7 @@ void COM_WorkerAbort(char *message)
{
struct com_work_s work;
com_fatalerror = true;
if (Sys_IsThread(NULL))
if (Sys_IsMainThread())
return;
work.func = Sys_ErrorThread;
@ -4834,7 +4834,7 @@ static void COM_WorkerSync_Stop(void *ctx, void *data, size_t a, size_t b)
#ifndef COM_AssertMainThread
void COM_AssertMainThread(const char *msg)
{
if (com_resourcemutex && !Sys_IsThread(NULL))
if (com_resourcemutex && !Sys_IsMainThread())
{
Sys_Error("Not on main thread: %s", msg);
}

View File

@ -99,7 +99,8 @@ void Sys_SetThreadName(unsigned int dwThreadID, char *threadName);
#endif
void Sys_ThreadsInit(void);
qboolean Sys_IsThread(void *thread);
//qboolean Sys_IsThread(void *thread);
qboolean Sys_IsMainThread(void);
void *Sys_CreateThread(char *name, int (*func)(void *), void *args, int priority, int stacksize);
void Sys_WaitOnThread(void *thread);
void Sys_DetachThread(void *thread);

View File

@ -34,12 +34,14 @@ void Sys_ThreadsInit(void)
{
mainthread = pthread_self();
}
qboolean Sys_IsThread(void *thread)
static qboolean Sys_IsThread(void *thread)
{
if (!thread)
thread = &mainthread;
return pthread_equal(pthread_self(), *(pthread_t*)thread);
}
static qboolean Sys_IsMainThread(void)
{
return Sys_IsThread(&mainthread);
}
void Sys_ThreadAbort(void)
{
pthread_exit(NULL);

View File

@ -148,12 +148,16 @@ void Sys_ThreadsInit(void)
{
mainthread = GetCurrentThreadId();
}
qboolean Sys_IsMainThread(void)
{
return mainthread == GetCurrentThreadId();
}
/*
qboolean Sys_IsThread(void *thread)
{
if (!thread)
return mainthread == GetCurrentThreadId();
return GetThreadId(thread) == GetCurrentThreadId();
}
*/
/* Mutex calls */
/*

View File

@ -125,6 +125,13 @@ qboolean D3D11_LoadTextureMips(image_t *tex, struct pendingtextureinfo *mips)
tdesc.CPUAccessFlags = (mips->mip[0].data)?0:D3D11_CPU_ACCESS_WRITE;
tdesc.MiscFlags = 0;
if (tex->flags & IF_RENDERTARGET)
{
tdesc.BindFlags |= D3D11_BIND_RENDER_TARGET;
tdesc.Usage = D3D11_USAGE_DEFAULT;
tdesc.CPUAccessFlags = 0;
}
if (mips->type == PTI_CUBEMAP)
{
tdesc.ArraySize *= 6;
@ -140,6 +147,22 @@ qboolean D3D11_LoadTextureMips(image_t *tex, struct pendingtextureinfo *mips)
{
default:
return false;
case PTI_DEPTH16:
tdesc.Format = DXGI_FORMAT_D16_UNORM;
tdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
break;
case PTI_DEPTH24:
tdesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
tdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
break;
case PTI_DEPTH32:
tdesc.Format = DXGI_FORMAT_D32_FLOAT;
tdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
break;
case PTI_DEPTH24_8:
tdesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
tdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
break;
case PTI_RGB565:
tdesc.Format = DXGI_FORMAT_B5G6R5_UNORM;
break;

View File

@ -148,6 +148,61 @@ static void D3D11_PresentOrCrash(void)
typedef enum {MS_WINDOWED, MS_FULLSCREEN, MS_FULLDIB, MS_UNINIT} modestate_t;
static modestate_t modestate;
//FIXME: need to push/pop render targets like gl does, to not harm shadowmaps/refraction/etc.
void D3D11_ApplyRenderTargets(qboolean usedepth)
{
unsigned int width = 0, height = 0;
int i;
texid_t textures[1];
texid_t depth;
ID3D11RenderTargetView *rtv[sizeof(textures)/sizeof(textures[0])];
ID3D11DepthStencilView *dsv;
for (i = 0; i < sizeof(textures)/sizeof(textures[0]); i++)
{
if (!*r_refdef.rt_destcolour[i].texname)
break;
textures[i] = R2D_RT_GetTexture(r_refdef.rt_destcolour[i].texname, &width, &height);
if (textures[i]->ptr2)
{
ID3D11ShaderResourceView_Release((ID3D11ShaderResourceView*)textures[i]->ptr2);
textures[i]->ptr2 = NULL;
}
ID3D11Device_CreateRenderTargetView(pD3DDev11, textures[i]->ptr, NULL, &rtv[i]);
}
if (usedepth)
{
if (*r_refdef.rt_depth.texname)
depth = R2D_RT_GetTexture(r_refdef.rt_depth.texname, &width, &height);
else
depth = R2D_RT_Configure("depth", width, height, 5);
}
else
depth = NULL;
if (depth && depth->ptr)
{
if (depth->ptr2)
{
ID3D11DepthStencilView_Release((ID3D11DepthStencilView*)depth->ptr2);
depth->ptr2 = NULL;
}
ID3D11Device_CreateDepthStencilView(pD3DDev11, depth->ptr, NULL, &dsv);
}
else
dsv = NULL;
ID3D11DeviceContext_OMSetRenderTargets(d3ddevctx, i, rtv, dsv);
for (i = 0; i < sizeof(textures)/sizeof(textures[0]); i++)
if (rtv[i])
ID3D11RenderTargetView_Release(rtv[i]);
if (dsv)
{
ID3D11DeviceContext_ClearDepthStencilView(d3ddevctx, dsv, D3D11_CLEAR_DEPTH, 1, 0); //is it faster to clear the stencil too?
ID3D11DepthStencilView_Release(dsv);
}
}
#ifndef WINRT //winrt crap has its own non-hwnd window crap, after years of microsoft forcing everyone to use hwnds for everything. I wonder why they don't have that many winrt apps.
static void D3DVID_UpdateWindowStatus (HWND hWnd)
@ -1351,14 +1406,20 @@ static void (D3D11_R_RenderView) (void)
{
float x, x2, y, y2;
double time1 = 0, time2 = 0;
qboolean dofbo = *r_refdef.rt_destcolour[0].texname || *r_refdef.rt_depth.texname;
// texid_t colourrt[1];
if (r_speeds.ival)
time1 = Sys_DoubleTime();
if (dofbo)
D3D11_ApplyRenderTargets(true);
else
ID3D11DeviceContext_ClearDepthStencilView(d3ddevctx, fb_backdepthstencil, D3D11_CLEAR_DEPTH, 1, 0); //is it faster to clear the stencil too?
D3D11_SetupViewPort();
//unlike gl, we clear colour beforehand, because that seems more sane.
//always clear depth
ID3D11DeviceContext_ClearDepthStencilView(d3ddevctx, fb_backdepthstencil, D3D11_CLEAR_DEPTH, 1, 0); //is it faster to clear the stencil too?
x = (r_refdef.vrect.x * (int)vid.pixelwidth)/(int)vid.width;
x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * (int)vid.pixelwidth/(int)vid.width;
@ -1388,6 +1449,9 @@ static void (D3D11_R_RenderView) (void)
R2D_ImageColours(0, 0, 0, 1);
R2D_FillBlock(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height);
R2D_ImageColours(1, 1, 1, 1);
if (dofbo)
D3D11_ApplyRenderTargets(false);
return;
}
Surf_DrawWorld();
@ -1400,10 +1464,27 @@ static void (D3D11_R_RenderView) (void)
time2 = Sys_DoubleTime();
RQuantAdd(RQUANT_MSECS, (int)((time2-time1)*1000000));
}
if (dofbo)
D3D11_ApplyRenderTargets(false);
}
void D3D11BE_RenderToTextureUpdate2d(qboolean destchanged)
{
if (destchanged)
{
if (*r_refdef.rt_destcolour[0].texname)
D3D11_ApplyRenderTargets(false);
else
ID3D11DeviceContext_OMSetRenderTargets(d3ddevctx, 1, &fb_backbuffer, fb_backdepthstencil);
D3D11_Set2D();
}
else
{
// shaderstate.tex_sourcecol = R2D_RT_GetTexture(r_refdef.rt_sourcecolour.texname, &width, &height);
// shaderstate.tex_sourcedepth = R2D_RT_GetTexture(r_refdef.rt_depth.texname, &width, &height);
}
}
rendererinfo_t d3d11rendererinfo =

View File

@ -4341,15 +4341,10 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
if (!shaderstate.tex_reflection)
{
shaderstate.tex_reflection = Image_CreateTexture("***tex_reflection***", NULL, 0);
qglGenTextures(1, &shaderstate.tex_reflection->num);
GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_reflection);
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.pixelwidth/2, vid.pixelheight/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (!shaderstate.tex_reflection->num)
qglGenTextures(1, &shaderstate.tex_reflection->num);
}
oldfbo = GLBE_FBO_Update(&shaderstate.fbo_reflectrefrac, FBO_RB_DEPTH, &shaderstate.tex_reflection, 1, r_nulltex, vid.pixelwidth/2, vid.pixelheight/2);
r_refdef.vrect.x = 0;
r_refdef.vrect.y = 0;
r_refdef.vrect.width = vid.fbvwidth/2;
@ -4358,6 +4353,18 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
r_refdef.pxrect.y = 0;
r_refdef.pxrect.width = vid.fbpwidth/2;
r_refdef.pxrect.height = vid.fbpheight/2;
if (shaderstate.tex_reflection->width!=r_refdef.pxrect.width || shaderstate.tex_reflection->height!=r_refdef.pxrect.height)
{
shaderstate.tex_reflection->width = r_refdef.pxrect.width;
shaderstate.tex_reflection->height = r_refdef.pxrect.height;
GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_reflection);
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, shaderstate.tex_reflection->width, shaderstate.tex_reflection->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
oldfbo = GLBE_FBO_Update(&shaderstate.fbo_reflectrefrac, FBO_RB_DEPTH, &shaderstate.tex_reflection, 1, r_nulltex, shaderstate.tex_reflection->width, shaderstate.tex_reflection->height);
r_refdef.pxrect.maxheight = shaderstate.fbo_reflectrefrac.rb_size[1];
GL_ViewportUpdate();
GL_ForceDepthWritable();
@ -4375,13 +4382,27 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
{
vrect_t ovrect = r_refdef.vrect;
pxrect_t oprect = r_refdef.pxrect;
r_refdef.vrect.x = 0;
r_refdef.vrect.y = 0;
r_refdef.vrect.width = vid.fbvwidth/2;
r_refdef.vrect.height = vid.fbvheight/2;
r_refdef.pxrect.x = 0;
r_refdef.pxrect.y = 0;
r_refdef.pxrect.width = vid.fbpwidth/2;
r_refdef.pxrect.height = vid.fbpheight/2;
if (!shaderstate.tex_refraction)
{
shaderstate.tex_refraction = Image_CreateTexture("***tex_refraction***", NULL, 0);
if (!shaderstate.tex_refraction->num)
qglGenTextures(1, &shaderstate.tex_refraction->num);
}
if (shaderstate.tex_refraction->width != r_refdef.pxrect.width || shaderstate.tex_refraction->height != r_refdef.pxrect.height)
{
shaderstate.tex_refraction->width = r_refdef.pxrect.width;
shaderstate.tex_refraction->height = r_refdef.pxrect.height;
GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_refraction);
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.pixelwidth/2, vid.pixelheight/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, r_refdef.pxrect.width, r_refdef.pxrect.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@ -4392,29 +4413,26 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
if (!shaderstate.tex_refractiondepth)
{
shaderstate.tex_refractiondepth = Image_CreateTexture("***tex_refractiondepth***", NULL, 0);
qglGenTextures(1, &shaderstate.tex_refractiondepth->num);
if (!shaderstate.tex_refractiondepth->num)
qglGenTextures(1, &shaderstate.tex_refractiondepth->num);
}
if (shaderstate.tex_refractiondepth->width != r_refdef.pxrect.width || shaderstate.tex_refractiondepth->height != r_refdef.pxrect.height)
{
shaderstate.tex_refractiondepth->width = r_refdef.pxrect.width;
shaderstate.tex_refractiondepth->height = r_refdef.pxrect.height;
GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_refractiondepth);
qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, vid.pixelwidth/2, vid.pixelheight/2, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, r_refdef.pxrect.width, r_refdef.pxrect.height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
oldfbo = GLBE_FBO_Update(&shaderstate.fbo_reflectrefrac, FBO_TEX_DEPTH, &shaderstate.tex_refraction, 1, shaderstate.tex_refractiondepth, vid.pixelwidth/2, vid.pixelheight/2);
oldfbo = GLBE_FBO_Update(&shaderstate.fbo_reflectrefrac, FBO_TEX_DEPTH, &shaderstate.tex_refraction, 1, shaderstate.tex_refractiondepth, r_refdef.pxrect.width, r_refdef.pxrect.height);
}
else
{
oldfbo = GLBE_FBO_Update(&shaderstate.fbo_reflectrefrac, FBO_RB_DEPTH, &shaderstate.tex_refraction, 1, r_nulltex, vid.pixelwidth/2, vid.pixelheight/2);
oldfbo = GLBE_FBO_Update(&shaderstate.fbo_reflectrefrac, FBO_RB_DEPTH, &shaderstate.tex_refraction, 1, r_nulltex, r_refdef.pxrect.width, r_refdef.pxrect.height);
}
r_refdef.vrect.x = 0;
r_refdef.vrect.y = 0;
r_refdef.vrect.width = vid.fbvwidth/2;
r_refdef.vrect.height = vid.fbvheight/2;
r_refdef.pxrect.x = 0;
r_refdef.pxrect.y = 0;
r_refdef.pxrect.width = vid.fbpwidth/2;
r_refdef.pxrect.height = vid.fbpheight/2;
r_refdef.pxrect.maxheight = shaderstate.fbo_reflectrefrac.rb_size[1];
GL_ViewportUpdate();
@ -4435,19 +4453,6 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
{
vrect_t orect = r_refdef.vrect;
pxrect_t oprect = r_refdef.pxrect;
if (!shaderstate.tex_ripplemap)
{
//FIXME: can we use RGB8 instead?
shaderstate.tex_ripplemap = Image_CreateTexture("***tex_ripplemap***", NULL, 0);
qglGenTextures(1, &shaderstate.tex_ripplemap->num);
GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_ripplemap);
qglTexImage2D(GL_TEXTURE_2D, 0, /*(gl_config.glversion>3.1)?GL_RGBA8_SNORM:*/GL_RGBA16F_ARB, vid.pixelwidth/2, vid.pixelheight/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
oldfbo = GLBE_FBO_Update(&shaderstate.fbo_reflectrefrac, 0, &shaderstate.tex_ripplemap, 1, r_nulltex, vid.pixelwidth/2, vid.pixelheight/2);
r_refdef.vrect.x = 0;
r_refdef.vrect.y = 0;
r_refdef.vrect.width = vid.fbvwidth/2;
@ -4456,6 +4461,26 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
r_refdef.pxrect.y = 0;
r_refdef.pxrect.width = vid.fbpwidth/2;
r_refdef.pxrect.height = vid.fbpheight/2;
if (!shaderstate.tex_ripplemap)
{
//FIXME: can we use RGB8 instead?
shaderstate.tex_ripplemap = Image_CreateTexture("***tex_ripplemap***", NULL, 0);
if (!shaderstate.tex_ripplemap->num)
qglGenTextures(1, &shaderstate.tex_ripplemap->num);
}
if (shaderstate.tex_ripplemap->width != r_refdef.pxrect.width || shaderstate.tex_ripplemap->height != r_refdef.pxrect.height)
{
shaderstate.tex_ripplemap->width = r_refdef.pxrect.width;
shaderstate.tex_ripplemap->height = r_refdef.pxrect.height;
GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_ripplemap);
qglTexImage2D(GL_TEXTURE_2D, 0, /*(gl_config.glversion>3.1)?GL_RGBA8_SNORM:*/GL_RGBA16F_ARB, r_refdef.pxrect.width, r_refdef.pxrect.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
oldfbo = GLBE_FBO_Update(&shaderstate.fbo_reflectrefrac, 0, &shaderstate.tex_ripplemap, 1, r_nulltex, r_refdef.pxrect.width, r_refdef.pxrect.height);
r_refdef.pxrect.maxheight = shaderstate.fbo_reflectrefrac.rb_size[1];
GL_ViewportUpdate();

View File

@ -144,6 +144,8 @@ void GL_Set2D (qboolean flipped)
R2D_RT_GetTexture(r_refdef.rt_destcolour[0].texname, &vid.fbpwidth, &vid.fbpheight);
vid.fbvwidth = vid.fbpwidth;
vid.fbvheight = vid.fbpheight;
flipped ^= true;
}
else
{

View File

@ -332,7 +332,7 @@ static void Font_Flush(void)
fontplanes.planechanged = false;
}
font_foremesh.istrifan = (font_foremesh.numvertexes == 4);
if (font_colourmask & CON_NONCLEARBG)
if ((font_colourmask & CON_NONCLEARBG) && font_foremesh.numindexes)
{
font_backmesh.numindexes = font_foremesh.numindexes;
font_backmesh.numvertexes = font_foremesh.numvertexes;
@ -1426,6 +1426,8 @@ void Font_Free(struct font_s *f)
//maps a given virtual screen coord to a pixel coord, which matches the font's height/width values
void Font_BeginString(struct font_s *font, float vx, float vy, int *px, int *py)
{
Font_Flush();
curfont = font;
*px = (vx*(int)vid.rotpixelwidth) / (float)vid.width;
*py = (vy*(int)vid.rotpixelheight) / (float)vid.height;
@ -1433,6 +1435,7 @@ void Font_BeginString(struct font_s *font, float vx, float vy, int *px, int *py)
curfont_scale[0] = curfont->charheight;
curfont_scale[1] = curfont->charheight;
curfont_scaled = false;
font_colourmask = ~0u; //force the colour to be recalculated.
}
void Font_Transform(float vx, float vy, int *px, int *py)
@ -1444,6 +1447,8 @@ void Font_Transform(float vx, float vy, int *px, int *py)
}
void Font_BeginScaledString(struct font_s *font, float vx, float vy, float szx, float szy, float *px, float *py)
{
Font_Flush();
curfont = font;
*px = (vx*(float)vid.rotpixelwidth) / (float)vid.width;
*py = (vy*(float)vid.rotpixelheight) / (float)vid.height;

View File

@ -1470,7 +1470,7 @@ static void Mod_LoadMiptex(model_t *loadmodel, char *loadname, texture_t *tx, mi
{
maps &= ~LMT_BUMP;
snprintf(altname, sizeof(altname)-1, "%s_norm", mt->name);
tx->texnums.bump = R_LoadReplacementTexture(altname, loadname, IF_NOGAMMA|IF_MIPCAP|IF_TRYBUMP, mipbase, mipwidth, mipheight, TF_HEIGHT8PAL);
tx->texnums.bump = R_LoadReplacementTexture(altname, loadname, IF_NOGAMMA|IF_MIPCAP|IF_TRYBUMP|(*mt->name == '*'?IF_LINEAR:0), mipbase, mipwidth, mipheight, TF_HEIGHT8PAL);
}
}

View File

@ -455,14 +455,21 @@ void R_SetupGL (float stereooffset)
fov_x = r_refdef.fov_x;//+sin(cl.time)*5;
fov_y = r_refdef.fov_y;//-sin(cl.time+1)*5;
GL_ViewportUpdate();
if ((r_refdef.flags & RDF_UNDERWATER) && !(r_refdef.flags & RDF_WATERWARP))
if (*r_refdef.rt_destcolour[0].texname || *r_refdef.rt_depth.texname)
{
r_refdef.pxrect.y = r_refdef.pxrect.maxheight - (r_refdef.pxrect.height+r_refdef.pxrect.y);
fov_y *= -1;
r_refdef.flipcull ^= SHADER_CULL_FLIP;
}
else if ((r_refdef.flags & RDF_UNDERWATER) && !(r_refdef.flags & RDF_WATERWARP))
{
fov_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
fov_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);
}
GL_ViewportUpdate();
if (r_refdef.useperspective)
{
int stencilshadows = Sh_StencilShadowsActive();
@ -826,7 +833,7 @@ void R_ObliqueNearClip(float *viewmat, mplane_t *wplane)
// by the inverse of the projection matrix
q[0] = (sgn(vplane[0]) + r_refdef.m_projection[8]) / r_refdef.m_projection[0];
q[1] = (sgn(vplane[1]) + r_refdef.m_projection[9]) / r_refdef.m_projection[5];
q[1] = (sgn(vplane[1]) + fabs(r_refdef.m_projection[9])) / fabs(r_refdef.m_projection[5]);
q[2] = -1.0F;
q[3] = (1.0F + r_refdef.m_projection[10]) / r_refdef.m_projection[14];
@ -1058,7 +1065,6 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2],
TransformDir(vup, paxis, vaxis, vup);
Matrix4x4_CM_ModelViewMatrixFromAxis(vmat, vpn, vright, vup, r_refdef.vieworg);
//transform the old surface plane into the new view matrix
if (Matrix4_Invert(r_refdef.m_view, ivmat))
{
@ -1163,6 +1169,8 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2],
r_refdef.flipcull |= SHADER_CULL_FLIP;
else
r_refdef.flipcull &= ~SHADER_CULL_FLIP;
if (r_refdef.m_projection[5]<0)
r_refdef.flipcull ^= SHADER_CULL_FLIP;
GL_CullFace(0);//make sure flipcull takes effect
//FIXME: just call Surf_DrawWorld instead?
@ -1687,6 +1695,7 @@ void GLR_RenderView (void)
vid.fbpwidth = vid.pixelwidth;
vid.fbpheight = vid.pixelheight;
}
r_refdef.flipcull = 0;
if (qglPNTrianglesiATI)
{
@ -1700,7 +1709,7 @@ void GLR_RenderView (void)
qglPNTrianglesiATI(GL_PN_TRIANGLES_NORMAL_MODE_ATI, GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI);
qglPNTrianglesiATI(GL_PN_TRIANGLES_POINT_MODE_ATI, GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI);
}
qglPNTrianglesfATI(GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, gl_ati_truform_tesselation.value);
qglPNTrianglesfATI(GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, gl_ati_truform_tesselation.value);
}
if (gl_finish.ival)

View File

@ -609,7 +609,7 @@ static int Shader_SetImageFlags(shader_t *shader, shaderpass_t *pass, char **nam
if (!Q_strnicmp(*name, "$rt:", 4))
{
*name += 4;
flags |= IF_RENDERTARGET;
flags |= IF_NOMIPMAP|IF_CLAMP|IF_LINEAR|IF_RENDERTARGET;
}
else if (!Q_strnicmp(*name, "$clamp:", 7))
{

View File

@ -40,6 +40,7 @@ typedef struct
typedef struct
{
int scoord[2];
float zicoord;
vec4_t vcoord;
vec2_t tccoord;
vec2_t lmcoord;

View File

@ -616,8 +616,11 @@ void SWBE_DrawWorld(qboolean drawworld, qbyte *vis)
}
void SWBE_Init(void)
{
memset(&r_config, 0, sizeof(r_config));
r_config.maxtexturesize = 512;
memset(&sh_config, 0, sizeof(sh_config));
sh_config.texfmt[PTI_BGRA8] = true;
sh_config.texfmt[PTI_BGRX8] = true;
sh_config.texfmt[PTI_RGBA8] = true;
sh_config.texfmt[PTI_RGBX8] = true;
BE_InitTables();
}
void SWBE_GenBrushModelVBO(struct model_s *mod)

View File

@ -14,6 +14,8 @@
#define restrict
#endif
#define ZI_MAX 0xffff
/*
Our software rendering basically works like this:
@ -39,8 +41,19 @@ struct workqueue_s spanqueue;
static void WT_Triangle(swthread_t *th, swimage_t *img, swvert_t *v1, swvert_t *v2, swvert_t *v3)
{
//affine vs correct:
//to correct perspective, divide interpolants by z.
//per pixel, divide by interpolated 1 (actually 1/z)
unsigned int tpix;
#if 1
#define PERSPECTIVE(v) (v>>16)
#else
#define PERSPECTIVE(v) (v/zi)
#define SPAN_ZI
#endif
#define SPAN_ST
#define SPAN_Z
#define PLOT_PIXEL(o) \
{ \
@ -48,8 +61,8 @@ static void WT_Triangle(swthread_t *th, swimage_t *img, swvert_t *v1, swvert_t *
{ \
*zb = z; \
tpix = img->data[ \
((unsigned)(s>>16)&img->pwidthmask) \
+ (((unsigned)(t>>16)&img->pheightmask) * img->pitch) \
((unsigned)PERSPECTIVE(s)&img->pwidthmask) \
+ (((unsigned)PERSPECTIVE(t)&img->pheightmask) * img->pitch) \
]; \
if (tpix&0xff000000) \
o = tpix; \
@ -74,11 +87,18 @@ SPAN_ST - interpolates S+T across the span. access with 'sc' and 'tc'
swvert_t *vt;
int y;
int secondhalf;
//l=value on left
//ld=change per y (on left)
//d=change per x
int xl,xld, xr,xrd;
#ifdef SPAN_ST
int sl,sld, sd;
int tl,tld, td;
#endif
#ifdef SPAN_ZI
int zil, zild, zid;
#endif
#ifdef SPAN_Z
int zl,zld, zd;
#endif
@ -136,8 +156,8 @@ SPAN_ST - interpolates S+T across the span. access with 'sc' and 'tc'
return;
if (v[i]->scoord[1] < 0 || v[i]->scoord[1] > th->vpheight)
return;
// if (v[i]->scoord[3] < 0)
// return;
if (v[i]->zicoord < 0)
return;
}
for (i = 0; i < 2; i++)
@ -178,9 +198,15 @@ SPAN_ST - interpolates S+T across the span. access with 'sc' and 'tc'
tld = fdx1*d2 - fdx2*d1;
td = fdy2*d1 - fdy1*d2;
#endif
#ifdef SPAN_ZI
d1 = (1<<16);
d2 = (1<<16);
zild = 0;//fdx1*d2 - fdx2*d1;
zid = 0;//fdy2*d1 - fdy1*d2;
#endif
#ifdef SPAN_Z
d1 = (v2->vcoord[3] - v1->vcoord[3])*(1<<16);
d2 = (v3->vcoord[3] - v1->vcoord[3])*(1<<16);
d1 = (v2->zicoord - v1->zicoord)*(1<<16);
d2 = (v3->zicoord - v1->zicoord)*(1<<16);
zld = fdx1*d2 - fdx2*d1;
zd = fdy2*d1 - fdy1*d2;
#endif
@ -208,6 +234,9 @@ SPAN_ST - interpolates S+T across the span. access with 'sc' and 'tc'
sl += sld*interlace;
tl += tld*interlace;
#endif
#ifdef SPAN_ZI
zil += zild*interlace;
#endif
#ifdef SPAN_Z
zl += zld*interlace;
#endif
@ -227,6 +256,9 @@ SPAN_ST - interpolates S+T across the span. access with 'sc' and 'tc'
sld -= (((long long)sd*xld)>>16);
tld -= (((long long)td*xld)>>16);
#endif
#ifdef SPAN_ZI
zild -= (((long long)zid*xld)>>16);
#endif
#ifdef SPAN_Z
zld -= (((long long)zd*xld)>>16);
#endif
@ -281,8 +313,12 @@ SPAN_ST - interpolates S+T across the span. access with 'sc' and 'tc'
tl = vlt->tccoord[1] * (img->pheight<<16);
tld = tld + (((long long)td*xld+32767)>>16);
#endif
#ifdef SPAN_ZI
zil = (1<<16);///vlt->zicoord;
zild = zild + (((long long)zid*xld)>>16);
#endif
#ifdef SPAN_Z
zl = vlt->vcoord[3] * (1<<16);
zl = vlt->zicoord * (1<<16);
zld = zld + (((long long)zd*xld)>>16);
#endif
}
@ -328,6 +364,9 @@ SPAN_ST - interpolates S+T across the span. access with 'sc' and 'tc'
sl += sld*interlace;
tl += tld*interlace;
#endif
#ifdef SPAN_ZI
zil += zild*interlace;
#endif
#ifdef SPAN_Z
zl += zld*interlace;
#endif
@ -344,6 +383,9 @@ SPAN_ST - interpolates S+T across the span. access with 'sc' and 'tc'
,sl += sld*th->interlacemod
,tl += tld*th->interlacemod
#endif
#ifdef SPAN_ZI
,zil += zild*th->interlacemod
#endif
#ifdef SPAN_Z
,zl += zld*th->interlacemod
#endif
@ -353,6 +395,11 @@ SPAN_ST - interpolates S+T across the span. access with 'sc' and 'tc'
unsigned int s = sl;
unsigned int t = tl;
#endif
#ifdef SPAN_ZI
unsigned int zi = zil;
#else
const unsigned int zi = (1<<16);
#endif
#ifdef SPAN_Z
unsigned int z = zl;
unsigned int *restrict zb = th->vpdbuf + y * th->vpwidth + (xl>>16);
@ -361,7 +408,7 @@ SPAN_ST - interpolates S+T across the span. access with 'sc' and 'tc'
spanlen = (xr - xl)>>16;
outbuf = vplout + (xl>>16);
while(spanlen-->=0)
while(spanlen-->0)
{
PLOT_PIXEL(*outbuf);
outbuf++;
@ -370,6 +417,9 @@ SPAN_ST - interpolates S+T across the span. access with 'sc' and 'tc'
s += sd;
t += td;
#endif
#ifdef SPAN_ZI
zi += zid;
#endif
#ifdef SPAN_Z
z += zd;
zb++;
@ -388,52 +438,52 @@ SPAN_ST - interpolates S+T across the span. access with 'sc' and 'tc'
static void WT_Clip_Top(swthread_t *th, swvert_t *out, swvert_t *in, swvert_t *result)
{
float frac;
frac = (1 - in->scoord[1]) /
(out->scoord[1] - in->scoord[1]);
frac = (0 - in->scoord[1]) /
(float)(out->scoord[1] - in->scoord[1]);
Vector2Interpolate(in->scoord, frac, out->scoord, result->scoord);
Vector2Interpolate(in->vcoord+2, frac, out->vcoord+2, result->vcoord+2);
// result->vcoord[1] = 0;
FloatInterpolate(in->zicoord, frac, out->zicoord, result->zicoord);
result->scoord[1] = 0;
Vector2Interpolate(in->tccoord, frac, out->tccoord, result->tccoord);
}
static void WT_Clip_Bottom(swthread_t *th, swvert_t *out, swvert_t *in, swvert_t *result)
{
float frac;
frac = ((th->vpheight) - in->vcoord[1]) /
(out->vcoord[1] - in->vcoord[1]);
frac = ((th->vpheight) - in->scoord[1]) /
(float)(out->scoord[1] - in->scoord[1]);
Vector2Interpolate(in->scoord, frac, out->scoord, result->scoord);
Vector2Interpolate(in->vcoord+2, frac, out->vcoord+2, result->vcoord+2);
// result->vcoord[1] = vid.pixelheight-1;
FloatInterpolate(in->zicoord, frac, out->zicoord, result->zicoord);
result->scoord[1] = th->vpheight;
Vector2Interpolate(in->tccoord, frac, out->tccoord, result->tccoord);
}
static void WT_Clip_Left(swthread_t *th, swvert_t *out, swvert_t *in, swvert_t *result)
{
float frac;
frac = (1 - in->vcoord[0]) /
(out->vcoord[0] - in->vcoord[0]);
frac = (0 - in->scoord[0]) /
(float)(out->scoord[0] - in->scoord[0]);
Vector2Interpolate(in->scoord, frac, out->scoord, result->scoord);
Vector2Interpolate(in->vcoord+2, frac, out->vcoord+2, result->vcoord+2);
// result->vcoord[0] = 0;
FloatInterpolate(in->zicoord, frac, out->zicoord, result->zicoord);
result->scoord[0] = 0;
Vector2Interpolate(in->tccoord, frac, out->tccoord, result->tccoord);
}
static void WT_Clip_Right(swthread_t *th, swvert_t *out, swvert_t *in, swvert_t *result)
{
float frac;
frac = ((th->vpwidth) - in->vcoord[0]) /
(out->vcoord[0] - in->vcoord[0]);
frac = ((th->vpwidth) - in->scoord[0]) /
(float)(out->scoord[0] - in->scoord[0]);
Vector2Interpolate(in->scoord, frac, out->scoord, result->scoord);
Vector2Interpolate(in->vcoord+2, frac, out->vcoord+2, result->vcoord+2);
// result->vcoord[0] = vid.pixelwidth-1;
FloatInterpolate(in->zicoord, frac, out->zicoord, result->zicoord);
result->scoord[0] = th->vpwidth;
Vector2Interpolate(in->tccoord, frac, out->tccoord, result->tccoord);
}
static void WT_Clip_Near(swthread_t *th, swvert_t *out, swvert_t *in, swvert_t *result)
{
float nearclip = 0;
double frac;
frac = (nearclip - in->vcoord[3]) /
(out->vcoord[3] - in->vcoord[3]);
Vector2Interpolate(in->scoord, frac, out->scoord, result->scoord);
Vector2Interpolate(in->vcoord+2, frac, out->vcoord+2, result->vcoord+2);
result->vcoord[3] = nearclip;
frac = (nearclip - in->zicoord) /
(out->zicoord - in->zicoord);
VectorInterpolate(in->vcoord, frac, out->vcoord, result->vcoord);
FloatInterpolate(in->zicoord, frac, out->zicoord, result->zicoord);
result->zicoord = nearclip;
Vector2Interpolate(in->tccoord, frac, out->tccoord, result->tccoord);
}
@ -441,11 +491,11 @@ static void WT_Clip_Far(swthread_t *th, swvert_t *out, swvert_t *in, swvert_t *r
{
float farclip = 1;
double frac;
frac = (farclip - in->vcoord[3]) /
(out->vcoord[3] - in->vcoord[3]);
Vector2Interpolate(in->scoord, frac, out->scoord, result->scoord);
Vector2Interpolate(in->vcoord+2, frac, out->vcoord+2, result->vcoord+2);
result->vcoord[3] = farclip;
frac = (farclip - in->zicoord) /
(out->zicoord - in->zicoord);
VectorInterpolate(in->vcoord, frac, out->vcoord, result->vcoord);
FloatInterpolate(in->zicoord, frac, out->zicoord, result->zicoord);
result->zicoord = farclip;
Vector2Interpolate(in->tccoord, frac, out->tccoord, result->tccoord);
}
@ -482,9 +532,9 @@ static int WT_ClipPoly(swthread_t *th, int incount, swvert_t *inv, swvert_t *out
if (outv[result].scoord[1] > th->vpheight)
outv[result].clipflags |= CLIP_BOTTOM_FLAG;
if (outv[result].scoord[3] < 0)
if (outv[result].zicoord < 0)
outv[result].clipflags |= CLIP_NEAR_FLAG;
if (outv[result].scoord[3] > 1)
if (outv[result].zicoord > ZI_MAX)
outv[result].clipflags |= CLIP_FAR_FLAG;
result++;
@ -522,6 +572,7 @@ static int WT_TransformVertXY(swthread_t *th, swvert_t *v)
result |= CLIP_TOP_FLAG;
if (v->scoord[1] > th->vpheight)
result |= CLIP_BOTTOM_FLAG;
v->clipflags = result;
return result;
@ -536,12 +587,12 @@ static void WT_ClipTriangle(swthread_t *th, swimage_t *img, swvert_t *v1, swvert
int count;
//check the near/far planes.
v1->vcoord[3] = DotProduct(v1->vcoord, th->u.viewplane) - th->u.viewplane[3];
if (v1->vcoord[3] < 0) v1->clipflags = CLIP_NEAR_FLAG; else if (v1->vcoord[3] > 1) v1->clipflags = CLIP_FAR_FLAG; else v1->clipflags = 0;
v2->vcoord[3] = DotProduct(v2->vcoord, th->u.viewplane) - th->u.viewplane[3];
if (v2->vcoord[3] < 0) v2->clipflags = CLIP_NEAR_FLAG; else if (v2->vcoord[3] > 1) v2->clipflags = CLIP_FAR_FLAG; else v2->clipflags = 0;
v3->vcoord[3] = DotProduct(v3->vcoord, th->u.viewplane) - th->u.viewplane[3];
if (v3->vcoord[3] < 0) v3->clipflags = CLIP_NEAR_FLAG; else if (v3->vcoord[3] > 1) v3->clipflags = CLIP_FAR_FLAG; else v3->clipflags = 0;
v1->zicoord = DotProduct(v1->vcoord, th->u.viewplane) - th->u.viewplane[3];
if (v1->zicoord < 0) v1->clipflags = CLIP_NEAR_FLAG; else if (v1->zicoord >= ZI_MAX) v1->clipflags = CLIP_FAR_FLAG; else v1->clipflags = 0;
v2->zicoord = DotProduct(v2->vcoord, th->u.viewplane) - th->u.viewplane[3];
if (v2->zicoord < 0) v2->clipflags = CLIP_NEAR_FLAG; else if (v2->zicoord >= ZI_MAX) v2->clipflags = CLIP_FAR_FLAG; else v2->clipflags = 0;
v3->zicoord = DotProduct(v3->vcoord, th->u.viewplane) - th->u.viewplane[3];
if (v3->zicoord < 0) v3->clipflags = CLIP_NEAR_FLAG; else if (v3->zicoord >= ZI_MAX) v3->clipflags = CLIP_FAR_FLAG; else v3->clipflags = 0;
if (v1->clipflags & v2->clipflags & v3->clipflags)
return; //all verticies are off at least one plane
@ -565,6 +616,7 @@ static void WT_ClipTriangle(swthread_t *th, swimage_t *img, swvert_t *v1, swvert
//clip to the screen
if (cflags & CLIP_NEAR_FLAG)
{
// return;
count = WT_ClipPoly(th, count, final[list], final[list^1], CLIP_NEAR_FLAG, WT_Clip_Near);
list ^= 1;
}
@ -889,63 +941,6 @@ void SW_R_RenderView(void)
cl_numvisedicts = tmpvisents;
}
void SW_R_NewMap(void)
{
char namebuf[MAX_QPATH];
extern cvar_t host_mapname, r_shadow_realtime_dlight, r_shadow_realtime_world;
int i;
for (i=0 ; i<256 ; i++)
d_lightstylevalue[i] = 264; // normal light value
memset (&r_worldentity, 0, sizeof(r_worldentity));
AngleVectors(r_worldentity.angles, r_worldentity.axis[0], r_worldentity.axis[1], r_worldentity.axis[2]);
VectorInverse(r_worldentity.axis[1]);
r_worldentity.model = cl.worldmodel;
Vector4Set(r_worldentity.shaderRGBAf, 1, 1, 1, 1);
COM_StripExtension(COM_SkipPath(cl.worldmodel->name), namebuf, sizeof(namebuf));
Cvar_Set(&host_mapname, namebuf);
Surf_DeInit();
r_viewleaf = NULL;
r_viewcluster = -1;
r_oldviewcluster = 0;
r_viewcluster2 = -1;
Mod_ParseInfoFromEntityLump(cl.worldmodel, cl.worldmodel->entities, cl.worldmodel->name);
P_ClearParticles ();
Surf_WipeStains();
CL_RegisterParticles();
Surf_BuildLightmaps ();
#ifdef VM_UI
UI_Reset();
#endif
TP_NewMap();
R_SetSky(cl.skyname);
#ifdef MAP_PROC
if (cl.worldmodel->fromgame == fg_doom3)
D3_GenerateAreas(cl.worldmodel);
#endif
#ifdef RTLIGHTS
Sh_PreGenerateLights();
#endif
}
void SW_R_PreNewMap(void)
{
r_viewleaf = NULL;
r_oldviewleaf = NULL;
r_viewleaf2 = NULL;
r_oldviewleaf2 = NULL;
}
void SW_SCR_UpdateScreen(void)
{
wqcom_t *com;
@ -982,6 +977,8 @@ void SW_SCR_UpdateScreen(void)
Shader_DoReload();
R2D_Font_Changed();
//FIXME: playfilm/editor+q3ui
SCR_SetUpToDrawConsole ();