diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 7e67d0d2c..047a0c96e 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -240,6 +240,7 @@ cvar_t show_speed = SCVAR("show_speed", "0"); cvar_t show_speed_x = SCVAR("show_speed_x", "-1"); cvar_t show_speed_y = SCVAR("show_speed_y", "-9"); cvar_t scr_loadingrefresh = SCVAR("scr_loadingrefresh", "0"); +cvar_t scr_showloading = CVAR("scr_showloading", "1"); cvar_t scr_showobituaries = CVAR("scr_showobituaries", "0"); void *scr_curcursor; @@ -252,6 +253,7 @@ void CLSCR_Init(void) Cvar_Register(&con_stayhidden, cl_screengroup); Cvar_Register(&scr_loadingrefresh, cl_screengroup); + Cvar_Register(&scr_showloading, cl_screengroup); Cvar_Register(&show_fps, cl_screengroup); Cvar_Register(&show_fps_x, cl_screengroup); Cvar_Register(&show_fps_y, cl_screengroup); @@ -729,7 +731,7 @@ void SCR_DrawCursor(void) if (key_customcursor[cmod].dirty) { - if (key_customcursor[cmod].scale <= 0) + if (key_customcursor[cmod].scale <= 0 || !*key_customcursor[cmod].name) { key_customcursor[cmod].hotspot[0] = cl_cursorbiasx.value; key_customcursor[cmod].hotspot[1] = cl_cursorbiasy.value; @@ -740,7 +742,9 @@ void SCR_DrawCursor(void) oldcurs = key_customcursor[cmod].handle; if (rf->VID_CreateCursor && strcmp(key_customcursor[cmod].name, "none")) { - key_customcursor[cmod].handle = rf->VID_CreateCursor(key_customcursor[cmod].name, key_customcursor[cmod].hotspot[0], key_customcursor[cmod].hotspot[1], key_customcursor[cmod].scale); + key_customcursor[cmod].handle = NULL; + if (!key_customcursor[cmod].handle && *key_customcursor[cmod].name) + key_customcursor[cmod].handle = rf->VID_CreateCursor(key_customcursor[cmod].name, key_customcursor[cmod].hotspot[0], key_customcursor[cmod].hotspot[1], key_customcursor[cmod].scale); if (!key_customcursor[cmod].handle) key_customcursor[cmod].handle = rf->VID_CreateCursor("gfx/cursor.tga", key_customcursor[cmod].hotspot[0], key_customcursor[cmod].hotspot[1], key_customcursor[cmod].scale); //try the fallback if (!key_customcursor[cmod].handle) @@ -1669,105 +1673,108 @@ void SCR_DrawLoading (qboolean opaque) else if (opaque) R2D_ConsoleBackground (0, vid.height, true); - qdepth = COM_FDepthFile("gfx/loading.lmp", true); - h2depth = COM_FDepthFile("gfx/menu/loading.lmp", true); + if (scr_showloading.ival) + { + qdepth = COM_FDepthFile("gfx/loading.lmp", true); + h2depth = COM_FDepthFile("gfx/menu/loading.lmp", true); - if (qdepth < h2depth || h2depth > 0xffffff) - { //quake files + if (qdepth < h2depth || h2depth > 0xffffff) + { //quake files - pic = R2D_SafeCachePic ("gfx/loading.lmp"); - if (R_GetShaderSizes(pic, &w, &h, true)) - { - x = (vid.width - w)/2; - y = (vid.height - 48 - h)/2; - R2D_ScalePic (x, y, w, h, pic); - x = (vid.width/2) - 96; - y += h + 8; + pic = R2D_SafeCachePic ("gfx/loading.lmp"); + if (R_GetShaderSizes(pic, &w, &h, true)) + { + x = (vid.width - w)/2; + y = (vid.height - 48 - h)/2; + R2D_ScalePic (x, y, w, h, pic); + x = (vid.width/2) - 96; + y += h + 8; + } + else + { + x = (vid.width/2) - 96; + y = (vid.height/2) - 8; + + Draw_FunString((vid.width-7*8)/2, y-16, "Loading"); + } + + if (!total_loading_size) + total_loading_size = 1; + if (loading_stage > LS_CONNECTION) + { + sizex = current_loading_size * 192 / total_loading_size; + if (loading_stage == LS_SERVER) + { + R2D_ImageColours(1.0, 0.0, 0.0, 1.0); + R2D_FillBlock(x, y, sizex, 16); + R2D_ImageColours(0.0, 0.0, 0.0, 1.0); + R2D_FillBlock(x+sizex, y, 192-sizex, 16); + } + else + { + R2D_ImageColours(1.0, 1.0, 0.0, 1.0); + R2D_FillBlock(x, y, sizex, 16); + R2D_ImageColours(1.0, 0.0, 0.0, 1.0); + R2D_FillBlock(x+sizex, y, 192-sizex, 16); + } + + Draw_FunString(x+8, y+4, va("Loading %s... %i%%", + (loading_stage == LS_SERVER) ? "server" : "client", + current_loading_size * 100 / total_loading_size)); + } + y += 16; + + if (loadingfile) + { + Draw_FunString(x+8, y+4, loadingfile); + y+=8; + } } else - { - x = (vid.width/2) - 96; - y = (vid.height/2) - 8; - - Draw_FunString((vid.width-7*8)/2, y-16, "Loading"); - } - - if (!total_loading_size) - total_loading_size = 1; - if (loading_stage > LS_CONNECTION) - { - sizex = current_loading_size * 192 / total_loading_size; - if (loading_stage == LS_SERVER) + { //hexen2 files + pic = R2D_SafeCachePic ("gfx/menu/loading.lmp"); + if (R_GetShaderSizes(pic, &w, &h, true)) { - R2D_ImageColours(1.0, 0.0, 0.0, 1.0); - R2D_FillBlock(x, y, sizex, 16); - R2D_ImageColours(0.0, 0.0, 0.0, 1.0); - R2D_FillBlock(x+sizex, y, 192-sizex, 16); + int size, count, offset; + + if (!scr_drawloading && loading_stage == 0) + return; + + offset = (vid.width - w)/2; + R2D_ScalePic (offset, 0, w, h, pic); + + if (loading_stage == LS_NONE) + return; + + if (total_loading_size) + size = current_loading_size * 106 / total_loading_size; + else + size = 0; + + if (loading_stage == LS_CLIENT) + count = size; + else + count = 106; + + R2D_ImagePaletteColour (136, 1.0); + R2D_FillBlock (offset+42, 87, count, 1); + R2D_FillBlock (offset+42, 87+5, count, 1); + R2D_ImagePaletteColour (138, 1.0); + R2D_FillBlock (offset+42, 87+1, count, 4); + + if (loading_stage == LS_SERVER) + count = size; + else + count = 0; + + R2D_ImagePaletteColour(168, 1.0); + R2D_FillBlock (offset+42, 97, count, 1); + R2D_FillBlock (offset+42, 97+5, count, 1); + R2D_ImagePaletteColour(170, 1.0); + R2D_FillBlock (offset+42, 97+1, count, 4); + + y = 104; } - else - { - R2D_ImageColours(1.0, 1.0, 0.0, 1.0); - R2D_FillBlock(x, y, sizex, 16); - R2D_ImageColours(1.0, 0.0, 0.0, 1.0); - R2D_FillBlock(x+sizex, y, 192-sizex, 16); - } - - Draw_FunString(x+8, y+4, va("Loading %s... %i%%", - (loading_stage == LS_SERVER) ? "server" : "client", - current_loading_size * 100 / total_loading_size)); - } - y += 16; - - if (loadingfile) - { - Draw_FunString(x+8, y+4, loadingfile); - y+=8; - } - } - else - { //hexen2 files - pic = R2D_SafeCachePic ("gfx/menu/loading.lmp"); - if (R_GetShaderSizes(pic, &w, &h, true)) - { - int size, count, offset; - - if (!scr_drawloading && loading_stage == 0) - return; - - offset = (vid.width - w)/2; - R2D_ScalePic (offset, 0, w, h, pic); - - if (loading_stage == LS_NONE) - return; - - if (total_loading_size) - size = current_loading_size * 106 / total_loading_size; - else - size = 0; - - if (loading_stage == LS_CLIENT) - count = size; - else - count = 106; - - R2D_ImagePaletteColour (136, 1.0); - R2D_FillBlock (offset+42, 87, count, 1); - R2D_FillBlock (offset+42, 87+5, count, 1); - R2D_ImagePaletteColour (138, 1.0); - R2D_FillBlock (offset+42, 87+1, count, 4); - - if (loading_stage == LS_SERVER) - count = size; - else - count = 0; - - R2D_ImagePaletteColour(168, 1.0); - R2D_FillBlock (offset+42, 97, count, 1); - R2D_FillBlock (offset+42, 97+5, count, 1); - R2D_ImagePaletteColour(170, 1.0); - R2D_FillBlock (offset+42, 97+1, count, 4); - - y = 104; } } R2D_ImageColours(1, 1, 1, 1); diff --git a/engine/client/pr_clcmd.c b/engine/client/pr_clcmd.c index 5f827039c..62929974c 100644 --- a/engine/client/pr_clcmd.c +++ b/engine/client/pr_clcmd.c @@ -355,6 +355,38 @@ void QCBUILTIN PF_cl_keynumtostring (pubprogfuncs_t *prinst, struct globalvars_s RETURN_TSTRING(Key_KeynumToString(code, 0)); } +//#343 +void QCBUILTIN PF_cl_setcursormode (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *world = prinst->parms->user; + if (G_FLOAT(OFS_PARM0)) + key_dest_absolutemouse |= world->keydestmask; + else + key_dest_absolutemouse &= ~world->keydestmask; + + if (prinst->callargc>1) + { + struct key_cursor_s *m = &key_customcursor[(world->keydestmask==kdm_game)?kc_game:kc_menu]; + Q_strncpyz(m->name, PR_GetStringOfs(prinst, OFS_PARM1), sizeof(m->name)); + m->hotspot[0] = (prinst->callargc>2)?G_FLOAT(OFS_PARM2+0):0; + m->hotspot[1] = (prinst->callargc>2)?G_FLOAT(OFS_PARM2+1):0; + m->scale = (prinst->callargc>2)?G_FLOAT(OFS_PARM2+2):0; + if (m->scale <= 0) + m->scale = 1; + m->dirty = true; + } +} + +void QCBUILTIN PF_cl_getcursormode (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *world = prinst->parms->user; + if (G_FLOAT(OFS_PARM0)) + G_FLOAT(OFS_RETURN) = Key_MouseShouldBeFree(); + else if (key_dest_absolutemouse & world->keydestmask) + G_FLOAT(OFS_RETURN) = true; + else + G_FLOAT(OFS_RETURN) = false; +} void QCBUILTIN PF_cl_playingdemo (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index ca525db87..c15ad317d 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -1253,7 +1253,7 @@ void QCBUILTIN PF_R_PolygonBegin(pubprogfuncs_t *prinst, struct globalvars_s *pr if (csqc_isdarkplaces || (flags & 0x400)) flags |= BEF_FORCETWOSIDED; - if (csqc_poly_2d) + if (twod) shader = R_RegisterPic(PR_GetStringOfs(prinst, OFS_PARM0)); else shader = R_RegisterSkin(PR_GetStringOfs(prinst, OFS_PARM0), NULL); @@ -2809,39 +2809,6 @@ static void cs_get_input_state (usercmd_t *cmd) cmd->cursor_entitynumber = *csqcg.input_cursor_entitynumber; } -//#343 -static void QCBUILTIN PF_cl_setcursormode (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - world_t *world = prinst->parms->user; - if (G_FLOAT(OFS_PARM0)) - key_dest_absolutemouse |= world->keydestmask; - else - key_dest_absolutemouse &= ~world->keydestmask; - - if (prinst->callargc>1) - { - struct key_cursor_s *m = &key_customcursor[(world->keydestmask==kdm_game)?kc_game:kc_menu]; - Q_strncpyz(m->name, PR_GetStringOfs(prinst, OFS_PARM1), sizeof(m->name)); - m->hotspot[0] = (prinst->callargc>2)?G_FLOAT(OFS_PARM2+0):0; - m->hotspot[1] = (prinst->callargc>2)?G_FLOAT(OFS_PARM2+1):0; - m->scale = (prinst->callargc>2)?G_FLOAT(OFS_PARM2+2):0; - if (m->scale <= 0) - m->scale = 1; - m->dirty = true; - } -} - -static void QCBUILTIN PF_cl_getcursormode (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - world_t *world = prinst->parms->user; - if (G_FLOAT(OFS_PARM0)) - G_FLOAT(OFS_RETURN) = Key_MouseShouldBeFree(); - else if (key_dest_absolutemouse & world->keydestmask) - G_FLOAT(OFS_RETURN) = true; - else - G_FLOAT(OFS_RETURN) = false; -} - //get the input commands, and stuff them into some globals. static void QCBUILTIN PF_cs_getinputstate (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { @@ -6666,12 +6633,12 @@ qboolean CSQC_DrawView(void) { if (csqc_isdarkplaces) { - static float oldtime; + static double oldtime; if (cl.paused) *csqcg.frametime = 0; //apparently people can't cope with microstutter when they're using this as a test to see if the game is paused. else - *csqcg.frametime = bound(0, cl.servertime - oldtime, 0.1); - oldtime = cl.servertime; + *csqcg.frametime = bound(0, cl.time - oldtime, 0.1); + oldtime = cl.time; } else *csqcg.frametime = host_frametime; diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index da35ced0b..cc0627450 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -57,10 +57,10 @@ void QCBUILTIN PF_CL_drawsetcliparea (pubprogfuncs_t *prinst, struct globalvars_ srect_t srect; csqc_dp_lastwas3d = false; - srect.x = G_FLOAT(OFS_PARM0) / (float)vid.width; - srect.y = (G_FLOAT(OFS_PARM1) / (float)vid.height); - srect.width = G_FLOAT(OFS_PARM2) / (float)vid.width; - srect.height = G_FLOAT(OFS_PARM3) / (float)vid.height; + srect.x = G_FLOAT(OFS_PARM0) / (float)vid.fbvwidth; + srect.y = G_FLOAT(OFS_PARM1) / (float)vid.fbvheight; + srect.width = G_FLOAT(OFS_PARM2) / (float)vid.fbvwidth; + srect.height = G_FLOAT(OFS_PARM3) / (float)vid.fbvheight; srect.dmin = -99999; srect.dmax = 99999; srect.y = (1-srect.y) - srect.height; @@ -2010,6 +2010,8 @@ static struct { {"keynumtostring_csqc", PF_cl_keynumtostring, 340}, {"stringtokeynum_csqc", PF_cl_stringtokeynum, 341}, {"getkeybind", PF_cl_getkeybind, 342}, + {"setcursormode", PF_cl_setcursormode, 343}, + {"getcursormode", PF_cl_getcursormode, 0}, //gap {"isdemo", PF_isdemo, 349}, //gap diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index b0be818af..ea2375ce4 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -294,8 +294,10 @@ void R2D_Init(void) "rgbgen const $r_menutint\n" "}\n" #else - "if $glsl && gl_menutint_shader != 0\n" + "if gl_menutint_shader != 0\n" "program menutint\n" + "endif\n" + "if $haveprogram\n" "{\n" "map $currentrender\n" "}\n" diff --git a/engine/client/screen.h b/engine/client/screen.h index 56b2b791f..3d67d5ec3 100644 --- a/engine/client/screen.h +++ b/engine/client/screen.h @@ -62,7 +62,6 @@ void SCR_CheckDrawCenterString (void); void SCR_DrawNet (void); void SCR_DrawTurtle (void); void SCR_DrawPause (void); -void SCR_VRectForPlayer(vrect_t *vrect, int pnum); //returns a region for the player's view qboolean SCR_HardwareCursorIsActive(void); void CLSCR_Init(void); //basically so I can register a few friendly cvars. diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 308ea830e..cb1d8c730 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -5886,6 +5886,7 @@ lh_extension_t QSG_Extensions[] = { #endif {"FTE_QC_CHECKCOMMAND", 1, NULL, {"checkcommand"}}, {"FTE_QC_CHECKPVS", 1, NULL, {"checkpvs"}}, + {"FTE_QC_HARDWARECURSORS", 0, NULL, {NULL}, "setcursormode exists in both csqc+menuqc, and accepts additional arguments to specify a cursor image to use when this module has focus. If the image exceeds hardware limits, it will be emulated using regular draws - this at least still avoids conflicting cursors."}, {"FTE_QC_HASHTABLES", 6, NULL, {"hash_createtab", "hash_destroytab", "hash_add", "hash_get", "hash_delete", "hash_getkey"}}, {"FTE_QC_INTCONV", 4, NULL, {"stoi", "itos", "stoh", "htos"}}, {"FTE_QC_MATCHCLIENTNAME", 1, NULL, {"matchclientname"}}, diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index b88fd35e7..e25f294f8 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -392,6 +392,8 @@ void QCBUILTIN PF_cl_stringtokeynum(pubprogfuncs_t *prinst, struct globalvars_s void QCBUILTIN PF_cl_getkeybind (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_cl_setmousetarget (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_cl_getmousetarget (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_cl_setcursormode (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_cl_getcursormode (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_cl_playingdemo (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_cl_runningserver (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_cs_media_create_http (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); diff --git a/engine/d3d/d3d11_backend.c b/engine/d3d/d3d11_backend.c index fb1eee76d..cf598e25f 100644 --- a/engine/d3d/d3d11_backend.c +++ b/engine/d3d/d3d11_backend.c @@ -240,10 +240,13 @@ typedef struct int indexstreamcycle; int indexstreamoffset; + texid_t currentrender; + int numlivevbos; int numliveshadowbuffers; } d3d11backend_t; +extern D3D_FEATURE_LEVEL d3dfeaturelevel; #define VERTEXSTREAMSIZE (1024*1024*2) //2mb = 1 PAE jumbo page @@ -315,6 +318,9 @@ void D3D11_UpdateFiltering(image_t *imagelist, int filtermip[3], int filterpic[3 sampdesc.MaxLOD = mipcap[1]; } + if (d3dfeaturelevel < D3D_FEATURE_LEVEL_10_0) //9.* sucks + sampdesc.MaxLOD = FLT_MAX; + if (shaderstate.sampstate[flags]) ID3D11SamplerState_Release(shaderstate.sampstate[flags]); shaderstate.sampstate[flags] = NULL; @@ -394,6 +400,8 @@ static void BE_DestroyVariousStates(void) shaderstate.ecbuffers[i] = NULL; } + D3D11_DestroyTexture(shaderstate.currentrender); + //make sure the device doesn't have any textures still referenced. for (i = 0; i < MAX_TMUS/*shaderstate.lastpasscount*/; i++) { @@ -503,7 +511,7 @@ static void *D3D11BE_GenerateBlendState(unsigned int bits) blend.RenderTarget[0].BlendEnable = FALSE; } blend.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; - blend.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;//blend.RenderTarget[0].SrcBlend; + blend.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;//blend.RenderTarget[0].SrcBlend; blend.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;//blend.RenderTarget[0].DestBlend; blend.RenderTarget[0].BlendOpAlpha = blend.RenderTarget[0].BlendOp; @@ -905,6 +913,57 @@ void D3D11BE_UnbindAllTextures(void) } } +const GUID DECLSPEC_SELECTANY IID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, { 0x9a,0xb4,0x48,0x95,0x35,0xd3,0x4f,0x9c } }; + +static texid_t T_Gen_CurrentRender(void) +{ + int vwidth, vheight; + int pwidth = vid.fbpwidth; + int pheight = vid.fbpheight; + + ID3D11Texture2D *backbuf; +#ifdef WINRT + extern IDXGISwapChain1 *d3dswapchain; +#else + extern IDXGISwapChain *d3dswapchain; +#endif + D3D11_TEXTURE2D_DESC tdesc = {0}; + + if (r_refdef.recurse) + return r_nulltex; + + //FIXME: should be willing to use the current rendertargets instead + IDXGISwapChain_GetBuffer(d3dswapchain, 0, &IID_ID3D11Texture2D, (LPVOID*)&backbuf); + ID3D11Texture2D_GetDesc(backbuf, &tdesc); + + // copy the scene to texture + if (!TEXVALID(shaderstate.currentrender) || tdesc.Width != shaderstate.currentrender->width || tdesc.Height != shaderstate.currentrender->height) + { + if (!shaderstate.currentrender) + shaderstate.currentrender = Image_CreateTexture("***$currentrender***", NULL, 0); + if (!shaderstate.currentrender) + return r_nulltex; //err + + shaderstate.currentrender->width = tdesc.Width; + shaderstate.currentrender->height = tdesc.Height; + + tdesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; + tdesc.CPUAccessFlags = 0; + + if (shaderstate.currentrender->ptr) + ID3D11Texture2D_Release((ID3D11Texture2D*)shaderstate.currentrender->ptr); + shaderstate.currentrender->ptr = NULL; + ID3D11Device_CreateTexture2D(pD3DDev11, &tdesc, NULL, (ID3D11Texture2D**)&shaderstate.currentrender->ptr); + } + ID3D11DeviceContext_CopyResource(d3ddevctx, (ID3D11Resource*)shaderstate.currentrender->ptr, (ID3D11Resource*)backbuf); + + if (shaderstate.currentrender->ptr2) + ID3D11ShaderResourceView_Release((ID3D11ShaderResourceView*)shaderstate.currentrender->ptr2); + shaderstate.currentrender->ptr2 = NULL; + + return shaderstate.currentrender; +} + static void SelectPassTexture(unsigned int tu, const shaderpass_t *pass) { extern texid_t r_whiteimage, missing_texture_gloss, missing_texture_normal; @@ -966,9 +1025,9 @@ static void SelectPassTexture(unsigned int tu, const shaderpass_t *pass) } break; - /*case T_GEN_CURRENTRENDER: - FIXME: no code to grab the current screen and convert to a texture - break;*/ + case T_GEN_CURRENTRENDER: + BindTexture(tu, T_Gen_CurrentRender()); + break; case T_GEN_VIDEOMAP: #ifndef NOMEDIA if (pass->cin) @@ -995,8 +1054,6 @@ static void SelectPassTexture(unsigned int tu, const shaderpass_t *pass) BindTexture(tu, r_nulltex); break; - case T_GEN_CURRENTRENDER://copy the current screen to a texture, and draw that - case T_GEN_SOURCECOLOUR: //used for render-to-texture targets case T_GEN_SOURCEDEPTH: //used for render-to-texture targets @@ -1898,9 +1955,12 @@ static void BE_ApplyUniforms(program_t *prog, int permu) ID3D11DeviceContext_IASetPrimitiveTopology(d3ddevctx, prog->permu[permu].handle.hlsl.topology); ID3D11DeviceContext_VSSetConstantBuffers(d3ddevctx, 0, 3, cbuf); - ID3D11DeviceContext_HSSetConstantBuffers(d3ddevctx, 0, 3, cbuf); - ID3D11DeviceContext_DSSetConstantBuffers(d3ddevctx, 0, 3, cbuf); - ID3D11DeviceContext_GSSetConstantBuffers(d3ddevctx, 0, 3, cbuf); + if (prog->permu[permu].handle.hlsl.hull) + ID3D11DeviceContext_HSSetConstantBuffers(d3ddevctx, 0, 3, cbuf); + if (prog->permu[permu].handle.hlsl.domain) + ID3D11DeviceContext_DSSetConstantBuffers(d3ddevctx, 0, 3, cbuf); + if (prog->permu[permu].handle.hlsl.geom) + ID3D11DeviceContext_GSSetConstantBuffers(d3ddevctx, 0, 3, cbuf); ID3D11DeviceContext_PSSetConstantBuffers(d3ddevctx, 0, 3, cbuf); } @@ -1950,7 +2010,10 @@ static void D3D11BE_Cull(unsigned int cullflags) D3D11_RASTERIZER_DESC rasterdesc; ID3D11RasterizerState *newrasterizerstate; - cullflags ^= r_refdef.flipcull; + if (shaderstate.flags & BEF_FORCETWOSIDED) + cullflags = 0; + else if (cullflags) + cullflags ^= r_refdef.flipcull; if (shaderstate.curcull != cullflags) { @@ -1985,7 +2048,7 @@ static void D3D11BE_Cull(unsigned int cullflags) rasterdesc.FillMode = 0?D3D11_FILL_WIREFRAME:D3D11_FILL_SOLID; rasterdesc.FrontCounterClockwise = false; rasterdesc.MultisampleEnable = false; - rasterdesc.ScissorEnable = false;//true; + rasterdesc.ScissorEnable = true; rasterdesc.SlopeScaledDepthBias = 0.0f; if (FAILED(hr=ID3D11Device_CreateRasterizerState(pD3DDev11, &rasterdesc, &newrasterizerstate))) @@ -2289,7 +2352,10 @@ static qboolean BE_GenTempMeshVBO(vbo_t **vbo, mesh_t *mesh) VectorClear(out[i].ndir); VectorClear(out[i].sdir); VectorClear(out[i].tdir); - Vector4Scale(mesh->colors4f_array[0][i], 255, out[i].colorsb); + out[i].colorsb[0] = bound(0, mesh->colors4f_array[0][i][0]*255, 255); + out[i].colorsb[1] = bound(0, mesh->colors4f_array[0][i][1]*255, 255); + out[i].colorsb[2] = bound(0, mesh->colors4f_array[0][i][2]*255, 255); + out[i].colorsb[3] = bound(0, mesh->colors4f_array[0][i][3]*255, 255); } } else if (!mesh->normals_array && mesh->colors4b_array) @@ -3520,17 +3586,22 @@ void D3D11BE_Scissor(srect_t *rect) D3D11_RECT drect; if (rect) { - drect.left = (rect->x)*vid.pixelwidth; - drect.right = (rect->x + rect->width)*vid.pixelwidth; - drect.bottom = (1-(rect->y))*vid.pixelheight; - drect.top = (1-(rect->y + rect->height))*vid.pixelheight; + drect.left = (rect->x)*vid.fbpwidth; + drect.right = (rect->x + rect->width)*vid.fbpwidth; + drect.bottom = (1-(rect->y))*vid.fbpheight; + drect.top = (1-(rect->y + rect->height))*vid.fbpheight; + + if (drect.left < 0) + drect.left = 0; + if (drect.top < 0) + drect.top = 0; } else { drect.left = 0; - drect.right = vid.pixelwidth; + drect.right = vid.fbpwidth; drect.top = 0; - drect.bottom = vid.pixelheight; + drect.bottom = vid.fbpheight; } ID3D11DeviceContext_RSSetScissorRects(d3ddevctx, 1, &drect); } diff --git a/engine/d3d/d3d11_shader.c b/engine/d3d/d3d11_shader.c index ecffd21fe..ba78e6bc6 100644 --- a/engine/d3d/d3d11_shader.c +++ b/engine/d3d/d3d11_shader.c @@ -668,7 +668,7 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned D3D11_SHADER_INPUT_BIND_DESC bdesc = {0}; for (i = prog->numsamplers; i < be_maxpasses; i++) { - if (SUCCEEDED(freflect->lpVtbl->GetResourceBindingDescByName(freflect, va("t_%i", i), &bdesc))) + if (SUCCEEDED(freflect->lpVtbl->GetResourceBindingDescByName(freflect, va("t_t%i", i), &bdesc))) prog->numsamplers = i+1; } diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index d8d90613d..9f1bdc055 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -770,9 +770,12 @@ static void SelectPassTexture(unsigned int tu, shaderpass_t *pass) { IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_CONSTANT, shaderstate.passcolour); last = D3DTA_CONSTANT; + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_COLORVERTEX, FALSE); } else { + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_COLORVERTEX, TRUE); +// IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1); last = D3DTA_DIFFUSE; } } @@ -2006,7 +2009,11 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertbase, unsigned in void D3D9BE_Cull(unsigned int cullflags) { - cullflags ^= r_refdef.flipcull; + if (shaderstate.flags & BEF_FORCETWOSIDED) + cullflags = 0; + else if (cullflags) + cullflags ^= r_refdef.flipcull; + if (shaderstate.curcull != cullflags) { shaderstate.curcull = cullflags; @@ -3333,10 +3340,10 @@ void D3D9BE_Scissor(srect_t *srect) RECT rect; if (srect) { - rect.left = srect->x; - rect.right = srect->x + srect->width; - rect.top = srect->y; - rect.bottom = srect->y + srect->height; + rect.left = (srect->x) * vid.fbpwidth; + rect.right = (srect->x + srect->width) * vid.fbpwidth; + rect.top = (srect->y) * vid.fbpheight; + rect.bottom = (srect->y + srect->height) * vid.fbpheight; } else { @@ -3346,6 +3353,7 @@ void D3D9BE_Scissor(srect_t *srect) rect.bottom = vid.pixelheight; } IDirect3DDevice9_SetScissorRect(pD3DDev9, &rect); + IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_SCISSORTESTENABLE, TRUE); } #endif diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index c7911313c..5ee0ddac0 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -929,6 +929,11 @@ static void (D3D9_SCR_UpdateScreen) (void) D3D9BE_Reset(false); + if (r_clear.ival) + { + d3d9error(IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB((r_clear.ival&1)?255:0,(r_clear.ival&2)?255:0,(r_clear.ival&4)?255:0), 1, 0)); + } + if (scr_disabled_for_loading) { extern float scr_disabled_time; @@ -1164,9 +1169,9 @@ static void (D3D9_R_RenderView) (void) D3D9_SetupViewPortProjection(); - if (r_clear.ival && !(r_refdef.flags & RDF_NOWORLDMODEL)) - d3d9error(IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255,0,0), 1, 0)); - else +// if (r_clear.ival && !(r_refdef.flags & RDF_NOWORLDMODEL)) +// d3d9error(IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255,0,0), 1, 0)); +// else d3d9error(IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1, 0)); R_SetFrustum (r_refdef.m_projection, r_refdef.m_view); diff --git a/engine/d3d/vid_d3d11.c b/engine/d3d/vid_d3d11.c index 068cfefed..979a5e8bf 100644 --- a/engine/d3d/vid_d3d11.c +++ b/engine/d3d/vid_d3d11.c @@ -1159,6 +1159,8 @@ void D3D11_Set2D (void) vid.fbvheight = vid.height; vid.fbpwidth = vid.pixelwidth; vid.fbpheight = vid.pixelheight; + + D3D11BE_Scissor(NULL); } static void (D3D11_SCR_UpdateScreen) (void) @@ -1174,7 +1176,7 @@ static void (D3D11_SCR_UpdateScreen) (void) if (r_clear.ival) { - float colours[4] = {(r_clear.ival==2)?0:1, 0, 0, 0}; + float colours[4] = {(r_clear.ival&1)?1:0, (r_clear.ival&2)?1:0, (r_clear.ival&4)?1:0, 1}; ID3D11DeviceContext_ClearRenderTargetView(d3ddevctx, fb_backbuffer, colours); } diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index 70efa9445..34460fb60 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -367,7 +367,7 @@ void Font_Init(void) "endif\n" "nomipmaps\n" "{\n" - "map $nearest:$diffuse\n" + "map $diffuse\n" "rgbgen vertex\n" "alphagen vertex\n" "blendfunc blend\n" diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 1c24dfda1..a054c0d7b 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -1060,6 +1060,72 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip } script = end; } + else if (!strncmp(script, "!!cvard3", 8)) + { + script += 8; + while (*script == ' ' || *script == '\t') + script++; + end = script; + while ((*end >= 'A' && *end <= 'Z') || (*end >= 'a' && *end <= 'z') || (*end >= '0' && *end <= '9') || *end == '_') + end++; + if (nummodifiers < MAXMODIFIERS && end - script < 64) + { + cvar_t *var; + char namebuf[64]; + char valuebuf[64]; + memcpy(namebuf, script, end - script); + namebuf[end - script] = 0; + while (*end == ' ' || *end == '\t') + end++; + if (*end == '=') + { + script = ++end; + while (*end && *end != '\n' && *end != '\r' && end < script+sizeof(namebuf)-1) + end++; + memcpy(valuebuf, script, end - script); + valuebuf[end - script] = 0; + } + else + strcpy(valuebuf, "0"); + var = Cvar_Get(namebuf, valuebuf, CVAR_SHADERSYSTEM, "GLSL Variables"); + if (var) + permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %s(%g,%g,%g)\n", namebuf, ((qrenderer == QR_OPENGL)?"vec3":"float3"), var->vec4[0], var->vec4[1], var->vec4[2])); + } + script = end; + } + else if (!strncmp(script, "!!cvard4", 8)) + { + script += 8; + while (*script == ' ' || *script == '\t') + script++; + end = script; + while ((*end >= 'A' && *end <= 'Z') || (*end >= 'a' && *end <= 'z') || (*end >= '0' && *end <= '9') || *end == '_') + end++; + if (nummodifiers < MAXMODIFIERS && end - script < 64) + { + cvar_t *var; + char namebuf[64]; + char valuebuf[64]; + memcpy(namebuf, script, end - script); + namebuf[end - script] = 0; + while (*end == ' ' || *end == '\t') + end++; + if (*end == '=') + { + script = ++end; + while (*end && *end != '\n' && *end != '\r' && end < script+sizeof(namebuf)-1) + end++; + memcpy(valuebuf, script, end - script); + valuebuf[end - script] = 0; + } + else + strcpy(valuebuf, "0"); + var = Cvar_Get(namebuf, valuebuf, CVAR_SHADERSYSTEM, "GLSL Variables"); + if (var) + permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %s(%g,%g,%g,%g)\n", namebuf, ((qrenderer == QR_OPENGL)?"vec4":"float4"), var->vec4[0], var->vec4[1], var->vec4[2], var->vec4[3])); + } + script = end; + } else if (!strncmp(script, "!!cvarf", 7)) { script += 7; @@ -5252,7 +5318,7 @@ void Shader_Default2D(const char *shortname, shader_t *s, const void *genargs) { if (Shader_ParseShader("default2d", s)) return; - if (sh_config.progs_supported) + if (sh_config.progs_supported && qrenderer != QR_DIRECT3D9) { //hexen2 needs premultiplied alpha to avoid looking ugly //but that results in problems where things are drawn with alpha not 0, so scale vertex colour by alpha in the fragment program diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index 56623a19e..2177e90c4 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -496,6 +496,9 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "SamplerState s_t0;\n" "float4 main (v2f inp) : SV_TARGET\n" "{\n" +"#ifdef PREMUL\n" +"inp.vcol.rgb *= inp.vcol.a;\n" +"#endif\n" "return t_t0.Sample(s_t0, inp.tc) * inp.vcol;\n" "}\n" "#endif\n" @@ -2540,6 +2543,54 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" }, #endif +#ifdef D3D11QUAKE +{QR_DIRECT3D11, 11, "menutint", +"!!cvard3 r_menutint=0.2 0.2 0.2\n" +"!!cvardf r_menutint_inverse=0.0\n" + +"struct a2v\n" +"{\n" +"float4 pos: POSITION;\n" +"float2 tc: TEXCOORD0;\n" +"float4 vcol: COLOR0;\n" +"};\n" +"struct v2f\n" +"{\n" +"float4 pos: SV_POSITION;\n" +"float2 tc: TEXCOORD0;\n" +"float4 vcol: COLOR0;\n" +"};\n" + +"#include \n" + +"#ifdef VERTEX_SHADER\n" +"v2f main (a2v inp)\n" +"{\n" +"v2f outp;\n" +"outp.pos = mul(m_projection, inp.pos);\n" +"outp.tc = inp.tc;\n" +"outp.vcol = inp.vcol;\n" +"return outp;\n" +"}\n" +"#endif\n" + +"#ifdef FRAGMENT_SHADER\n" +"Texture2D t_t0;\n" +"SamplerState s_t0;\n" +"static const float3 lumfactors = float3 (0.299, 0.587, 0.114);\n" +"float4 main (v2f inp) : SV_TARGET\n" +"{\n" +"float4 texcolor = t_t0.Sample(s_t0, inp.tc);\n" +"float luminance = dot(lumfactors, texcolor.rgb);\n" +"texcolor.rgb = float3(luminance, luminance, luminance);\n" +"texcolor.rgb *= r_menutint;\n" +"texcolor.rgb = (r_menutint_inverse > 0) ? (1.0 - texcolor.rgb) : texcolor.rgb;\n" + +"return texcolor * inp.vcol;\n" +"}\n" +"#endif\n" +}, +#endif #ifdef GLQUAKE {QR_OPENGL, 110, "terrain", "!!permu FOG\n" diff --git a/engine/shaders/hlsl11/default2d.hlsl b/engine/shaders/hlsl11/default2d.hlsl index 6c6bcd2c6..2ba8b7a4f 100644 --- a/engine/shaders/hlsl11/default2d.hlsl +++ b/engine/shaders/hlsl11/default2d.hlsl @@ -29,6 +29,9 @@ struct v2f SamplerState s_t0; float4 main (v2f inp) : SV_TARGET { +#ifdef PREMUL + inp.vcol.rgb *= inp.vcol.a; +#endif return t_t0.Sample(s_t0, inp.tc) * inp.vcol; } #endif \ No newline at end of file diff --git a/engine/shaders/hlsl11/menutint.hlsl b/engine/shaders/hlsl11/menutint.hlsl new file mode 100644 index 000000000..352d1c720 --- /dev/null +++ b/engine/shaders/hlsl11/menutint.hlsl @@ -0,0 +1,44 @@ +!!cvard3 r_menutint=0.2 0.2 0.2 +!!cvardf r_menutint_inverse=0.0 + +struct a2v +{ + float4 pos: POSITION; + float2 tc: TEXCOORD0; + float4 vcol: COLOR0; +}; +struct v2f +{ + float4 pos: SV_POSITION; + float2 tc: TEXCOORD0; + float4 vcol: COLOR0; +}; + +#include + +#ifdef VERTEX_SHADER + v2f main (a2v inp) + { + v2f outp; + outp.pos = mul(m_projection, inp.pos); + outp.tc = inp.tc; + outp.vcol = inp.vcol; + return outp; + } +#endif + +#ifdef FRAGMENT_SHADER + Texture2D t_t0; + SamplerState s_t0; + static const float3 lumfactors = float3 (0.299, 0.587, 0.114); + float4 main (v2f inp) : SV_TARGET + { + float4 texcolor = t_t0.Sample(s_t0, inp.tc); + float luminance = dot(lumfactors, texcolor.rgb); + texcolor.rgb = float3(luminance, luminance, luminance); + texcolor.rgb *= r_menutint; + texcolor.rgb = (r_menutint_inverse > 0) ? (1.0 - texcolor.rgb) : texcolor.rgb; + + return texcolor * inp.vcol; + } +#endif \ No newline at end of file