From 9cd425e94508a20c976db84bc020f3f774f7c171 Mon Sep 17 00:00:00 2001 From: Spoike Date: Thu, 30 Nov 2017 17:59:11 +0000 Subject: [PATCH] rework hlmdl subblends. apparently they're some sort of grid. fix decals again. clampmap should work properly with them, also removed the extra part. fix rtlight pvs issue with respect to portals fix vid_reload causing the d3d9 renderer to use nearest sampling terrain system should now mostly work with d3d9. still has issues. fix q3 volumetric fog not applying to models git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5174 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_ents.c | 4 +- engine/client/cl_ui.c | 2 + engine/client/m_options.c | 2 +- engine/client/merged.h | 5 +- engine/client/pr_csqc.c | 14 +- engine/client/r_surf.c | 24 +- engine/client/renderer.c | 5 +- engine/client/vid_headless.c | 2 +- engine/common/mathlib.c | 2 +- engine/d3d/d3d11_backend.c | 5 +- engine/d3d/d3d8_backend.c | 5 +- engine/d3d/d3d_backend.c | 41 +++- engine/d3d/d3d_shader.c | 126 ++++++++++- engine/d3d/vid_d3d.c | 7 + engine/dotnet2005/droid.vcproj | 4 +- engine/droid/AndroidManifest.xml | 162 ++++++------- .../droid/src/com/fteqw/FTEDroidActivity.java | 2 +- engine/gl/gl_alias.c | 2 +- engine/gl/gl_backend.c | 72 +++--- engine/gl/gl_draw.c | 18 +- engine/gl/gl_heightmap.c | 35 ++- engine/gl/gl_hlmdl.c | 194 ++++++++++++---- engine/gl/gl_model.c | 2 +- engine/gl/gl_rsurf.c | 15 +- engine/gl/gl_viddroid.c | 6 + engine/gl/r_bishaders.h | 213 +++++++++++++++++- engine/gl/shader.h | 8 +- engine/server/progdefs.h | 6 +- engine/server/svhl_game.c | 5 +- engine/shaders/glsl/terrain.glsl | 2 +- engine/shaders/hlsl9/terrain.hlsl | 207 +++++++++++++++++ engine/sw/sw.h | 2 +- engine/sw/sw_backend.c | 2 +- engine/vk/vk_backend.c | 14 +- engine/vk/vkrenderer.h | 2 +- 35 files changed, 995 insertions(+), 222 deletions(-) create mode 100644 engine/shaders/hlsl9/terrain.hlsl diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index d09cbfd62..b1888d620 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -2843,7 +2843,7 @@ static void CL_AddDecal_Callback(void *vctx, vec3_t *fte_restrict points, size_t for (v = 0; v < numpoints; v++) { VectorCopy(points[v], cl_strisvertv[cl_numstrisvert+v]); - cl_strisvertt[cl_numstrisvert+v][0] = (DotProduct(points[v], ctx->axis[1]) - ctx->offset[1]) * ctx->scale[1]; + cl_strisvertt[cl_numstrisvert+v][0] = 1+(DotProduct(points[v], ctx->axis[1]) - ctx->offset[1]) * ctx->scale[1]; cl_strisvertt[cl_numstrisvert+v][1] = -(DotProduct(points[v], ctx->axis[2]) - ctx->offset[2]) * ctx->scale[2]; cl_strisvertc[cl_numstrisvert+v][0] = ctx->rgbavalue[0]; cl_strisvertc[cl_numstrisvert+v][1] = ctx->rgbavalue[1]; @@ -2908,7 +2908,7 @@ void CL_AddDecal(shader_t *shader, vec3_t origin, vec3_t up, vec3_t side, vec3_t ctx.t = t; VectorCopy(rgbvalue, ctx.rgbavalue); ctx.rgbavalue[3] = alphavalue; - Mod_ClipDecal(cl.worldmodel, origin, ctx.axis[0], ctx.axis[1], ctx.axis[2], radius*2, 0,0, CL_AddDecal_Callback, &ctx); + Mod_ClipDecal(cl.worldmodel, origin, ctx.axis[0], ctx.axis[1], ctx.axis[2], radius, 0,0, CL_AddDecal_Callback, &ctx); if (!t->numidx) cl_numstris--; diff --git a/engine/client/cl_ui.c b/engine/client/cl_ui.c index 2e2b4f940..60296ff8d 100644 --- a/engine/client/cl_ui.c +++ b/engine/client/cl_ui.c @@ -604,6 +604,8 @@ void VQ3_RenderView(const q3refdef_t *ref) r_refdef.maxdist = gl_maxdist.value; r_refdef.playerview = &cl.playerview[0]; + memset(&r_refdef.globalfog, 0, sizeof(r_refdef.globalfog)); + if (r_torch.ival) { dlight_t *dl; diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 8103d4b34..8a160ca8b 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -720,7 +720,7 @@ const char *presetname[] = "Realtime", //everything on NULL }; -#define PRESET_NUM 6 +#define PRESET_NUM (countof(presetname)-1) // this is structured like this for a possible future feature // also don't include cvars that need a restart here diff --git a/engine/client/merged.h b/engine/client/merged.h index 574ce04e3..375a11ab2 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -53,7 +53,8 @@ typedef struct { float lerpweight[FRAME_BLENDS]; #ifdef HALFLIFEMODELS - float subblendfrac; //hl models are weird + float subblendfrac; //hl models are weird + float subblend2frac; //very weird. #endif int endbone; @@ -465,7 +466,7 @@ typedef struct rendererinfo_s { //Generates an optimised VBO, one for each texture on the map void (*BE_GenBrushModelVBO)(struct model_s *mod); //Destroys the given vbo - void (*BE_ClearVBO)(struct vbo_s *vbo); + void (*BE_ClearVBO)(struct vbo_s *vbo, qboolean dataonly); //Uploads all modified lightmaps void (*BE_UploadAllLightmaps)(void); void (*BE_SelectEntity)(struct entity_s *ent); diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index f34c8ab88..fa967c7da 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -588,7 +588,9 @@ static void cs_getframestate(csqcedict_t *in, unsigned int rflags, framestate_t out->bonecontrols[3] = in->xv->bonecontrol4; out->bonecontrols[4] = in->xv->bonecontrol5; out->g[FS_REG].subblendfrac = in->xv->subblendfrac; + out->g[FS_REG].subblend2frac = in->xv->subblend2frac; out->g[FST_BASE].subblendfrac = in->xv->subblendfrac; + out->g[FST_BASE].subblend2frac = in->xv->subblend2frac; #endif //FTE_CSQC_BASEFRAME @@ -1042,7 +1044,17 @@ static void QCBUILTIN PF_R_RemoveEntity(pubprogfuncs_t *prinst, struct globalvar void CL_AddDecal(shader_t *shader, vec3_t origin, vec3_t up, vec3_t side, vec3_t rgbvalue, float alphavalue); static void QCBUILTIN PF_R_AddDecal(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { - shader_t *shader = R_RegisterSkin(PR_GetStringOfs(prinst, OFS_PARM0), NULL); + shader_t *shader = R_RegisterShader(PR_GetStringOfs(prinst, OFS_PARM0), SUF_NONE, + "{\n" + "polygonOffset\n" + "surfaceparms nodlight\n" + "{\n" + "map $diffuse\n" + "rgbgen vertex\n" + "alphagen vertex\n" + "blendfunc gl_one gl_one_minus_src_alpha\n" + "}\n" + "}\n"); float *org = G_VECTOR(OFS_PARM1); float *up = G_VECTOR(OFS_PARM2); float *side = G_VECTOR(OFS_PARM3); diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 2fac5e056..5ef661743 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -2888,7 +2888,7 @@ R_DrawWorld ============= */ -static pvsbuffer_t surf_frustumvis; +static pvsbuffer_t surf_frustumvis[R_MAX_RECURSE]; void Surf_DrawWorld (void) { //surfvis vs entvis - the key difference is that surfvis is surfaces while entvis is volume. though surfvis should be frustum culled also for lighting. entvis doesn't care. @@ -3045,9 +3045,10 @@ void Surf_DrawWorld (void) #if defined(Q2BSPS) || defined(Q3BSPS) if (currentmodel->fromgame == fg_quake2 || currentmodel->fromgame == fg_quake3) { - if (surf_frustumvis.buffersize < currentmodel->pvsbytes) - surf_frustumvis.buffer = BZ_Realloc(surf_frustumvis.buffer, surf_frustumvis.buffersize=currentmodel->pvsbytes); - frustumvis = surf_frustumvis.buffer; + pvsbuffer_t *vis = &surf_frustumvis[r_refdef.recurse]; + if (vis->buffersize < currentmodel->pvsbytes) + vis->buffer = BZ_Realloc(vis->buffer, vis->buffersize=currentmodel->pvsbytes); + frustumvis = vis->buffer; memset(frustumvis, 0, currentmodel->pvsbytes); if (!r_refdef.areabitsknown) @@ -3106,13 +3107,15 @@ void Surf_DrawWorld (void) // entvis = surfvis = R_MarkLeafSurfaces_Q1(); // else { + pvsbuffer_t *vis = &surf_frustumvis[r_refdef.recurse]; + entvis = R_MarkLeaves_Q1 (false); if (!(r_novis.ival & 2)) VectorCopy (r_origin, modelorg); - if (surf_frustumvis.buffersize < currentmodel->pvsbytes) - surf_frustumvis.buffer = BZ_Realloc(surf_frustumvis.buffer, surf_frustumvis.buffersize=currentmodel->pvsbytes); - frustumvis = surf_frustumvis.buffer; + if (vis->buffersize < currentmodel->pvsbytes) + vis->buffer = BZ_Realloc(vis->buffer, vis->buffersize=currentmodel->pvsbytes); + frustumvis = vis->buffer; memset(frustumvis, 0, currentmodel->pvsbytes); if (r_refdef.useperspective) @@ -3189,8 +3192,9 @@ void Surf_DeInit(void) if (lightmap) BZ_Free(lightmap); - Z_Free(surf_frustumvis.buffer); - memset(&surf_frustumvis, 0, sizeof(surf_frustumvis)); + for (i = 0; i < R_MAX_RECURSE; i++) + Z_Free(surf_frustumvis[i].buffer); + memset(surf_frustumvis, 0, sizeof(surf_frustumvis)); lightmap=NULL; numlightmaps=0; @@ -3221,7 +3225,7 @@ void Surf_Clear(model_t *mod) { vbo = mod->vbos; mod->vbos = vbo->next; - BE_ClearVBO(vbo); + BE_ClearVBO(vbo, false); } if (!mod->submodelof) diff --git a/engine/client/renderer.c b/engine/client/renderer.c index b52eefb08..d54f3a07b 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -414,7 +414,7 @@ cvar_t r_shadows = CVARFD ("r_shadows", "0", CVAR_ARCHIVE, "Draw basic blo cvar_t r_showbboxes = CVARD("r_showbboxes", "0", "Debugging. Shows bounding boxes. 1=ssqc, 2=csqc. Red=solid, Green=stepping/toss/bounce, Blue=onground."); cvar_t r_showfields = CVARD("r_showfields", "0", "Debugging. Shows entity fields boxes (entity closest to crosshair). 1=ssqc, 2=csqc."); cvar_t r_showshaders = CVARD("r_showshaders", "0", "Debugging. Shows the name of the (worldmodel) shader being pointed to."); -cvar_t r_lightprepass_cvar = CVARFD("r_lightprepass", "0", CVAR_SHADERSYSTEM, "Experimental. Attempt to use a different lighting mechanism."); +cvar_t r_lightprepass_cvar = CVARFD("r_lightprepass", "0", CVAR_ARCHIVE, "Experimental. Attempt to use a different lighting mechanism. Requires vid_reload to take effect."); int r_lightprepass; cvar_t r_shadow_bumpscale_basetexture = CVARD ("r_shadow_bumpscale_basetexture", "0", "bumpyness scaler for generation of fallback normalmap textures from models"); @@ -1729,6 +1729,7 @@ void R_ReloadRenderer_f (void) Con_DPrintf("teardown = %f\n", Sys_DoubleTime() - time); //reloads textures without destroying video context. R_ApplyRenderer_Load(NULL); + Cvar_ApplyCallbacks(CVAR_RENDERERCALLBACK); } //use Cvar_ApplyLatches(CVAR_RENDERERLATCH) beforehand. @@ -1901,7 +1902,7 @@ void R_RestartRenderer (rendererstate_t *newr) return; } - TRACE(("dbg: R_RestartRenderer_f renderer %i\n", newr.renderer)); + TRACE(("dbg: R_RestartRenderer_f renderer %p\n", newr->renderer)); memcpy(&oldr, ¤trendererstate, sizeof(rendererstate_t)); if (!R_ApplyRenderer(newr)) diff --git a/engine/client/vid_headless.c b/engine/client/vid_headless.c index 8ec047200..f8d862d90 100644 --- a/engine/client/vid_headless.c +++ b/engine/client/vid_headless.c @@ -201,7 +201,7 @@ static void Headless_BE_Init (void) static void Headless_BE_GenBrushModelVBO (struct model_s *mod) { } -static void Headless_BE_ClearVBO (struct vbo_s *vbo) +static void Headless_BE_ClearVBO (struct vbo_s *vbo, qboolean dataonly) { } static void Headless_BE_UploadAllLightmaps (void) diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index 25f41f8b9..fc84652d2 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -940,7 +940,7 @@ void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt ) qt[3] = p[2]; sclp = sin( (1.0 - t) * 0.5 * M_PI); sclq = sin( t * 0.5 * M_PI); - for (i = 0; i < 3; i++) { + for (i = 0; i < 4; i++) { qt[i] = sclp * p[i] + sclq * qt[i]; } } diff --git a/engine/d3d/d3d11_backend.c b/engine/d3d/d3d11_backend.c index 1869b0fbc..b42f8e839 100644 --- a/engine/d3d/d3d11_backend.c +++ b/engine/d3d/d3d11_backend.c @@ -2674,7 +2674,7 @@ void D3D11BE_GenBrushModelVBO(model_t *mod) } /*Wipes a vbo*/ -void D3D11BE_ClearVBO(vbo_t *vbo) +void D3D11BE_ClearVBO(vbo_t *vbo, qboolean dataonly) { ID3D11Buffer *vbuff = vbo->coord.d3d.buff; ID3D11Buffer *ebuff = vbo->indicies.d3d.buff; @@ -2691,7 +2691,8 @@ void D3D11BE_ClearVBO(vbo_t *vbo) vbo->coord.d3d.buff = NULL; vbo->indicies.d3d.buff = NULL; - BZ_Free(vbo); + if (!dataonly) + BZ_Free(vbo); } /*upload all lightmaps at the start to reduce lags*/ diff --git a/engine/d3d/d3d8_backend.c b/engine/d3d/d3d8_backend.c index 76b167693..7f602b6ac 100644 --- a/engine/d3d/d3d8_backend.c +++ b/engine/d3d/d3d8_backend.c @@ -2620,7 +2620,7 @@ void D3D8BE_GenBrushModelVBO(model_t *mod) } #endif /*Wipes a vbo*/ -void D3D8BE_ClearVBO(vbo_t *vbo) +void D3D8BE_ClearVBO(vbo_t *vbo, qboolean dataonly) { IDirect3DVertexBuffer8 *vbuff = vbo->coord.d3d.buff; IDirect3DIndexBuffer8 *ebuff = vbo->indicies.d3d.buff; @@ -2631,7 +2631,8 @@ void D3D8BE_ClearVBO(vbo_t *vbo) vbo->coord.d3d.buff = NULL; vbo->indicies.d3d.buff = NULL; - free(vbo); + if (!dataonly) + free(vbo); } /*upload all lightmaps at the start to reduce lags*/ diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index a3dd3dcec..3b8aa7d84 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -1211,7 +1211,7 @@ static unsigned int BE_GenerateColourMods(unsigned int vertcount, const shaderpa ((pass->rgbgen == RGB_GEN_VERTEX_LIGHTING) || (pass->rgbgen == RGB_GEN_VERTEX_EXACT) || (pass->rgbgen == RGB_GEN_ONE_MINUS_VERTEX)) && - (pass->alphagen == ALPHA_GEN_VERTEX))) + (pass->alphagen == ALPHA_GEN_VERTEX)) && shaderstate.batchvbo->colours_bytes) { //fixme d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_COL, shaderstate.batchvbo->colours[0].d3d.buff, shaderstate.batchvbo->colours[0].d3d.offs, sizeof(vbovdata_t))); @@ -1957,11 +1957,13 @@ static void BE_ApplyUniforms(program_t *prog, int permu) case SP_E_TOPCOLOURS: R_FetchPlayerColour(shaderstate.curentity->topcolour, param4); - IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, param4, 3); + param4[3] = 1; + IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, param4, 1); break; case SP_E_BOTTOMCOLOURS: R_FetchPlayerColour(shaderstate.curentity->bottomcolour, param4); - IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, param4, 3); + param4[3] = 1; + IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, param4, 1); break; case SP_E_LMSCALE: @@ -1979,7 +1981,11 @@ static void BE_ApplyUniforms(program_t *prog, int permu) VectorSet(param4, identitylighting, identitylighting, identitylighting); } param4[3] = 1; - IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, h, param4, 3); + IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, h, param4, 1); + break; + + case SP_W_FOG: + IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, r_refdef.globalfog.colour, 2); //colour and density break; case SP_M_ENTBONES: @@ -1987,7 +1993,6 @@ static void BE_ApplyUniforms(program_t *prog, int permu) case SP_E_VLSCALE: case SP_E_ORIGIN: case SP_E_GLOWMOD: - case SP_W_FOG: case SP_M_INVVIEWPROJECTION: case SP_M_INVMODELVIEWPROJECTION: case SP_SOURCESIZE: @@ -2053,6 +2058,8 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertbase, unsigned in perm |= PERMUTATION_LIGHTSTYLES; #endif + vdec |= BE_GenerateColourMods(vertcount, s->passes); + BE_ApplyUniforms(p, perm); @@ -2547,7 +2554,7 @@ void D3D9BE_SelectEntity(entity_t *ent) } #if 1 -static void D3D9BE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch) +void D3D9BE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch) { int maxvboelements; int maxvboverts; @@ -2618,9 +2625,18 @@ static void D3D9BE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t * vbovdata->coord[3] = 1; Vector2Copy(m->st_array[i], vbovdata->tex); Vector2Copy(m->lmst_array[0][i], vbovdata->lm); - VectorCopy(m->normals_array[i], vbovdata->ndir); - VectorCopy(m->snormals_array[i], vbovdata->sdir); - VectorCopy(m->tnormals_array[i], vbovdata->tdir); + if (m->normals_array) + { + VectorCopy(m->normals_array[i], vbovdata->ndir); + VectorCopy(m->snormals_array[i], vbovdata->sdir); + VectorCopy(m->tnormals_array[i], vbovdata->tdir); + } + else + { + VectorSet(vbovdata->ndir, 0, 0, 1); + VectorSet(vbovdata->sdir, 1, 0, 0); + VectorSet(vbovdata->tdir, 0, 1, 0); + } Vector4Scale(m->colors4f_array[0][i], 255, vbovdata->colorsb); vbovdata++; @@ -2719,7 +2735,7 @@ void D3D9BE_GenBrushModelVBO(model_t *mod) if (!mod->textures[t]) continue; vbo = &mod->textures[t]->vbo; - BE_ClearVBO(vbo); + BE_ClearVBO(vbo, false); maxvboverts = 0; maxvboelements = 0; @@ -2869,7 +2885,7 @@ void D3D9BE_GenBrushModelVBO(model_t *mod) } #endif /*Wipes a vbo*/ -void D3D9BE_ClearVBO(vbo_t *vbo) +void D3D9BE_ClearVBO(vbo_t *vbo, qboolean dataonly) { IDirect3DVertexBuffer9 *vbuff = vbo->coord.d3d.buff; IDirect3DIndexBuffer9 *ebuff = vbo->indicies.d3d.buff; @@ -2880,7 +2896,8 @@ void D3D9BE_ClearVBO(vbo_t *vbo) vbo->coord.d3d.buff = NULL; vbo->indicies.d3d.buff = NULL; - free(vbo); + if (!dataonly) + free(vbo); } /*upload all lightmaps at the start to reduce lags*/ diff --git a/engine/d3d/d3d_shader.c b/engine/d3d/d3d_shader.c index 5b8d0d0ec..c5beb789d 100644 --- a/engine/d3d/d3d_shader.c +++ b/engine/d3d/d3d_shader.c @@ -11,12 +11,25 @@ extern LPDIRECT3DDEVICE9 pD3DDev9; typedef struct { - LPCSTR Name; - LPCSTR Definition; + LPCSTR Name; + LPCSTR Definition; } D3DXMACRO; #define D3DXHANDLE void * -#define LPD3DXINCLUDE void * +typedef enum D3DXINCLUDE_TYPE { + D3DXINC_LOCAL = 0, + D3DXINC_SYSTEM = 1, + D3DXINC_FORCE_DWORD = 0x7fffffff +} D3DXINCLUDE_TYPE, *LPD3DXINCLUDE_TYPE; + +#undef INTERFACE +#define INTERFACE myID3DXInclude +DECLARE_INTERFACE(myID3DXInclude) +{ + STDMETHOD_(HRESULT,Open)(THIS_ D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes) PURE; + STDMETHOD_(HRESULT,Close)(THIS_ LPCVOID pData) PURE; +}; +typedef struct myID3DXInclude *LPD3DXINCLUDE; #undef INTERFACE #define INTERFACE d3dxbuffer @@ -141,8 +154,111 @@ static dllhandle_t *shaderlib; (This)->lpVtbl -> Release(This) #endif +static HRESULT STDMETHODCALLTYPE myID3DXIncludeVtbl_Close(myID3DXInclude *cls, LPCVOID pData) +{ + return S_OK; +} +static HRESULT STDMETHODCALLTYPE myID3DXIncludeVtbl_Open(myID3DXInclude *cls, D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes) +{ + char *file = NULL; +// "sys/defs.h" +// "sys/skeletal.h" +// "sys/offsetmapping.h" + if (!strcmp(pFileName, "sys/fog.h")) + { + file = + "#ifdef FRAGMENT_SHADER\n" + "#ifdef FOG\n" + "#ifndef DEFS_DEFINED\n" + "float4 w_fog[2];\n" + "#define w_fogcolour w_fog[0].rgb\n" + "#define w_fogalpha w_fog[0].a\n" + "#define w_fogdensity w_fog[1].x\n" + "#define w_fogdepthbias w_fog[1].y\n" + "#endif\n" + "static const float r_fog_exp2 = 1.0;\n" + + "float3 fog3(float3 regularcolour, float distance)" + "{" + "float z = w_fogdensity * -distance;\n" + "z = max(0.0,z-w_fogdepthbias);\n" + "if (r_fog_exp2)\n" + "z *= z;\n" + "float fac = exp2(-(z * 1.442695));\n" + "fac = (1.0-w_fogalpha) + (clamp(fac, 0.0, 1.0)*w_fogalpha);\n" + "return lerp(w_fogcolour, regularcolour, fac);\n" + "}\n" + "float3 fog3additive(float3 regularcolour, float distance)" + "{" + "float z = w_fogdensity * -distance;\n" + "z = max(0.0,z-w_fogdepthbias);\n" + "if (r_fog_exp2)\n" + "z *= z;\n" + "float fac = exp2(-(z * 1.442695));\n" + "fac = (1.0-w_fogalpha) + (clamp(fac, 0.0, 1.0)*w_fogalpha);\n" + "return regularcolour * fac;\n" + "}\n" + "float4 fog4(float4 regularcolour, float distance)" + "{" + "return float4(fog3(regularcolour.rgb, distance), 1.0) * regularcolour.a;\n" + "}\n" + "float4 fog4additive(float4 regularcolour, float distance)" + "{" + "float z = w_fogdensity * -distance;\n" + "z = max(0.0,z-w_fogdepthbias);\n" + "if (r_fog_exp2)\n" + "z *= z;\n" + "float fac = exp2(-(z * 1.442695));\n" + "fac = (1.0-w_fogalpha) + (clamp(fac, 0.0, 1.0)*w_fogalpha);\n" + "return regularcolour * float4(fac, fac, fac, 1.0);\n" + "}\n" + "float4 fog4blend(float4 regularcolour, float distance)" + "{" + "float z = w_fogdensity * -distance;\n" + "z = max(0.0,z-w_fogdepthbias);\n" + "if (r_fog_exp2)\n" + "z *= z;\n" + "float fac = exp2(-(z * 1.442695));\n" + "fac = (1.0-w_fogalpha) + (clamp(fac, 0.0, 1.0)*w_fogalpha);\n" + "return regularcolour * float4(1.0, 1.0, 1.0, fac);\n" + "}\n" + "#else\n" + /*don't use macros for this - mesa bugs out*/ + "float3 fog3(float3 regularcolour, float4 fragcoord) { return regularcolour; }\n" + "float3 fog3additive(float3 regularcolour, float4 fragcoord) { return regularcolour; }\n" + "float4 fog4(float4 regularcolour, float4 fragcoord) { return regularcolour; }\n" + "float4 fog4additive(float4 regularcolour, float4 fragcoord) { return regularcolour; }\n" + "float4 fog4blend(float4 regularcolour, float4 fragcoord) { return regularcolour; }\n" + "#endif\n" + "#endif\n" + ; + } + else if (!strcmp(pFileName, "sys/pcf.h")) + { + file = + "#define ShadowmapFilter(smap,proj) 1.0\n" + ; + } + + if (file) + { + *ppData = file; + *pBytes = strlen(file); + return S_OK; + } + else + return E_FAIL; +} +static struct myID3DXIncludeVtbl myID3DXIncludeVtbl_C = +{ + myID3DXIncludeVtbl_Open, + myID3DXIncludeVtbl_Close +}; +static struct myID3DXInclude myID3DXIncludeVtbl_Instance = {&myID3DXIncludeVtbl_C}; + static qboolean D3D9Shader_CreateProgram (program_t *prog, const char *sname, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean silent, vfsfile_t *blobfile) { + D3DXMACRO defines[64]; LPD3DXBUFFER code = NULL, errors = NULL; qboolean success = false; @@ -209,7 +325,7 @@ static qboolean D3D9Shader_CreateProgram (program_t *prog, const char *sname, un success = true; defines[0].Name = "VERTEX_SHADER"; - if (FAILED(pD3DXCompileShader(vert, strlen(vert), defines, NULL, "main", "vs_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&prog->permu[permu].h.hlsl.ctabv))) + if (FAILED(pD3DXCompileShader(vert, strlen(vert), defines, &myID3DXIncludeVtbl_Instance, "main", "vs_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&prog->permu[permu].h.hlsl.ctabv))) success = false; else { @@ -224,7 +340,7 @@ static qboolean D3D9Shader_CreateProgram (program_t *prog, const char *sname, un } defines[0].Name = "FRAGMENT_SHADER"; - if (FAILED(pD3DXCompileShader(frag, strlen(frag), defines, NULL, "main", "ps_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&prog->permu[permu].h.hlsl.ctabf))) + if (FAILED(pD3DXCompileShader(frag, strlen(frag), defines, &myID3DXIncludeVtbl_Instance, "main", "ps_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&prog->permu[permu].h.hlsl.ctabf))) success = false; else { diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index 2c5bddf31..3bcde8cac 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -1268,6 +1268,13 @@ static void (D3D9_R_RenderView) (void) { Surf_SetupFrame(); + if (!r_refdef.globalfog.density) + { + int fogtype = ((r_refdef.flags & RDF_UNDERWATER) && cl.fog[1].density)?1:0; + CL_BlendFog(&r_refdef.globalfog, &cl.oldfog[fogtype], realtime, &cl.fog[fogtype]); + r_refdef.globalfog.density /= 64; //FIXME + } + //check if we can do underwater warp if (cls.protocol != CP_QUAKE2) //quake2 tells us directly { diff --git a/engine/dotnet2005/droid.vcproj b/engine/dotnet2005/droid.vcproj index c19950ddb..4c009e2dd 100644 --- a/engine/dotnet2005/droid.vcproj +++ b/engine/dotnet2005/droid.vcproj @@ -23,7 +23,7 @@ > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/engine/droid/src/com/fteqw/FTEDroidActivity.java b/engine/droid/src/com/fteqw/FTEDroidActivity.java index a1e25e717..14df3db23 100644 --- a/engine/droid/src/com/fteqw/FTEDroidActivity.java +++ b/engine/droid/src/com/fteqw/FTEDroidActivity.java @@ -242,7 +242,7 @@ public class FTEDroidActivity extends Activity { int flags = FTEDroidEngine.frame(); //fixme: check return value for events to respond to - + if (flags != notifiedflags) { if (((flags ^ notifiedflags) & 1) != 0) diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 88fe5302a..2bc29dc01 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -1577,7 +1577,7 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches) b->buildmeshes = R_GAlias_DrawBatch; b->ent = e; -#ifdef Q3BSPS +#if defined(Q3BSPS) || defined(RFBSPS) b->fog = Mod_FogForOrigin(cl.worldmodel, e->origin); #endif b->mesh = NULL; diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 706e08285..f8ed1b0d2 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -1619,28 +1619,34 @@ static void tcgen_fog(float *st, unsigned int numverts, float *xyz, mfog_t *fog) Vector4Scale(zmat, shaderstate.fogfar, zmat); - if (fog->visibleplane) - eye = (DotProduct(r_refdef.vieworg, fog->visibleplane->normal) - fog->visibleplane->dist); - else - eye = 1; -// if (eye < 1) -// eye = 1; - - for (i = 0 ; i < numverts ; i++, xyz += sizeof(vecV_t)/sizeof(vec_t), st += 2 ) + if (fog && fog->visibleplane) { - z = DotProduct(xyz, zmat) + zmat[3]; - st[0] = z; + eye = (DotProduct(r_refdef.vieworg, fog->visibleplane->normal) - fog->visibleplane->dist); + if (eye < 1) + eye = 1; //avoids a nan - if (fog->visibleplane) - point = (DotProduct(xyz, fog->visibleplane->normal) - fog->visibleplane->dist); - else - point = 1; - if (eye < 0) - st[1] = (point < 0)?1:0; - else + for (i = 0 ; i < numverts ; i++, xyz += sizeof(vecV_t)/sizeof(vec_t), st += 2 ) + { + z = DotProduct(xyz, zmat) + zmat[3]; + st[0] = z; + + if (fog->visibleplane) + point = (DotProduct(xyz, fog->visibleplane->normal) - fog->visibleplane->dist); + else + point = 1; st[1] = point / (point - eye); - if (st[1] > 31/32.0) + if (st[1] > 31/32.0) + st[1] = 31/32.0; + } + } + else + { + for (i = 0 ; i < numverts ; i++, xyz += sizeof(vecV_t)/sizeof(vec_t), st += 2 ) + { + z = DotProduct(xyz, zmat) + zmat[3]; + st[0] = z; st[1] = 31/32.0; + } } } static void GenerateTCFog(int passnum, mfog_t *fog) @@ -3832,18 +3838,21 @@ void GLBE_SelectEntity(entity_t *ent) shaderstate.lastuniform = 0; } -#if 0 +#if 1 static void BE_SelectFog(vec3_t colour, float alpha, float density) { float zscale; - density /= 64; + GL_DeSelectProgram(); zscale = 2048; /*this value is meant to be the distance at which fog the value becomes as good as fully fogged, just hack it to 2048...*/ GenerateFogTexture(&shaderstate.fogtexture, density, zscale); shaderstate.fogfar = 1/zscale; /*scaler for z coords*/ - qglColor4f(colour[0], colour[1], colour[2], alpha); + VectorCopy(colour, shaderstate.pendingcolourflat); + shaderstate.pendingcolourflat[3] = alpha; + shaderstate.pendingcolourvbo = 0; + shaderstate.pendingcolourpointer = NULL; } #endif #ifdef RTLIGHTS @@ -4256,10 +4265,8 @@ static void DrawMeshes(void) case BEM_FOG: #ifndef GLSLONLY - GL_DeSelectProgram(); - GenerateTCFog(0, NULL); - BE_EnableShaderAttributes((1u<fog && shaderstate.curbatch->fog->shader) { + //FIXME: if glsl, do this fog volume crap properly! + GL_DeSelectProgram(); GenerateFogTexture(&shaderstate.fogtexture, shaderstate.curbatch->fog->shader->fog_dist, 2048); @@ -5761,7 +5770,7 @@ void GLBE_DrawWorld (batch_t **worldbatches) shaderstate.depthrange = 0; - TRACE(("GLBE_DrawWorld: %i %p\n", drawworld, vis)); + TRACE(("GLBE_DrawWorld: %p\n", worldbatches)); //reset batches if we needed more mem, to avoid allocations mid-frame. if (!r_refdef.recurse) @@ -5866,13 +5875,16 @@ void GLBE_DrawWorld (batch_t **worldbatches) GLBE_SubmitMeshes(worldbatches, SHADER_SORT_SEETHROUGH+1, SHADER_SORT_NEAREST); RSpeedEnd(RSPEED_TRANSPARENTS); -/* if (r_refdef.gfog_alpha) - { +#ifndef GLSLONLY + if (r_refdef.globalfog.density && !gl_config.arb_shader_objects) + { //fixed function-only. with global fog. that means we need to hack something in. + //FIXME: should really be doing this on a per-shader basis, for custom shaders that don't use glsl BE_SelectMode(BEM_FOG); - BE_SelectFog(r_refdef.gfog_rgb, r_refdef.gfog_alpha, r_refdef.gfog_density); - GLBE_SubmitMeshes(true, batches, SHADER_SORT_PORTAL, SHADER_SORT_NEAREST); + + BE_SelectFog(r_refdef.globalfog.colour, r_refdef.globalfog.alpha, r_refdef.globalfog.density); + GLBE_SubmitMeshes(worldbatches, SHADER_SORT_PORTAL, SHADER_SORT_NEAREST); } -*/ +#endif #ifdef GL_LINE //no gles if (r_wireframe.ival && qglPolygonMode) diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index f29fbcc69..51511b3bb 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -333,10 +333,20 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips) if (tex->flags&IF_CLAMP) { - qglTexParameteri(targ, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - qglTexParameteri(targ, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (targ != GL_TEXTURE_2D) - qglTexParameteri(targ, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + if (gl_config.glversion < 1.2 && !gl_config_gles) + { //warning: crappy path! gl1.1 is shite and doesn't support clamp-to-edge! there's ALWAYS some wrap component! + qglTexParameteri(targ, GL_TEXTURE_WRAP_S, GL_CLAMP); + qglTexParameteri(targ, GL_TEXTURE_WRAP_T, GL_CLAMP); + if (targ != GL_TEXTURE_2D) + qglTexParameteri(targ, GL_TEXTURE_WRAP_R, GL_CLAMP); + } + else + { + qglTexParameteri(targ, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + qglTexParameteri(targ, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (targ != GL_TEXTURE_2D) + qglTexParameteri(targ, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + } } else { diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index 44ec04e09..c4cf702e9 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -1952,15 +1952,21 @@ void Terr_DestroySection(heightmap_t *hm, hmsection_t *s, qboolean lightmapreusa hm->relight = NULL; #ifdef GLQUAKE - if (qrenderer == QR_OPENGL && qglDeleteBuffersARB) + if (qrenderer == QR_OPENGL) { - qglDeleteBuffersARB(1, &s->vbo.coord.gl.vbo); - s->vbo.coord.gl.vbo = 0; - qglDeleteBuffersARB(1, &s->vbo.indicies.gl.vbo); - s->vbo.indicies.gl.vbo = 0; + if (qglDeleteBuffersARB) + { + qglDeleteBuffersARB(1, &s->vbo.coord.gl.vbo); + s->vbo.coord.gl.vbo = 0; + qglDeleteBuffersARB(1, &s->vbo.indicies.gl.vbo); + s->vbo.indicies.gl.vbo = 0; + } } + else #endif - //FIXME: BE_ClearVBO(&s->vbo); + { + BE_ClearVBO(&s->vbo, true); + } Z_Free(s->ents); Z_Free(s->mesh.xyz_array); @@ -2713,6 +2719,21 @@ static void Terr_RebuildMesh(model_t *model, hmsection_t *s, int x, int y) s->vbo = *vbo; } #endif +#ifdef D3D9QUAKE + if (qrenderer == QR_DIRECT3D9) + { + void D3D9BE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch); + batch_t batch = {0}; + mesh_t *meshes = &s->mesh; + vbo_t *vbo = NULL; + batch.maxmeshes = 1; + batch.mesh = &meshes; + + //BE_ClearVBO(&s->vbo); + D3D9BE_GenBatchVBOs(&vbo, &batch, NULL); + s->vbo = *vbo; + } +#endif #ifdef D3D11QUAKE if (qrenderer == QR_DIRECT3D11) { @@ -5409,6 +5430,8 @@ void Terr_FinishTerrain(model_t *mod) //FIXME: these maps are a legacy thing, and could be removed if third-party glsl properly contains s_diffuse "{\n" "map $diffuse\n" + "rgbgen vertex\n" + "alphagen vertex\n" "}\n" "{\n" "map $upperoverlay\n" diff --git a/engine/gl/gl_hlmdl.c b/engine/gl/gl_hlmdl.c index ed0ed92eb..195fe49dc 100644 --- a/engine/gl/gl_hlmdl.c +++ b/engine/gl/gl_hlmdl.c @@ -540,14 +540,14 @@ void HL_CalcBoneAdj(hlmodel_t *model) ======================================================================================================================= */ void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt ); -void HL_SetupBones(hlmodel_t *model, int seqnum, int firstbone, int lastbone, float subblendfrac, float frametime, float *matrix) +void HL_SetupBones(hlmodel_t *model, int seqnum, int firstbone, int lastbone, float subblendfrac1, float subblendfrac2, float frametime, float *matrix) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ - int i; + int i, j; vec3_t organg1[2]; vec3_t organg2[2]; vec3_t organgb[2]; - vec4_t quat1, quat2, quatb; + vec4_t quat1, quat2; int frame1, frame2; @@ -654,54 +654,170 @@ void HL_SetupBones(hlmodel_t *model, int seqnum, int firstbone, int lastbone, fl FIXME: we don't handle frame2. */ - if (sequence->hasblendseq>1 && sequence->hasblendseq<9) + if (sequence->hasblendseq>1) { - //I have no idea how to deal with > 1. - //some CS models seem to have 9 here, but some look like they're fucked. - if (subblendfrac < 0) - subblendfrac = 0; - if (subblendfrac > 1) - subblendfrac = 1; + int bf0, bf1; + int bweights; + struct + { + int frame; + float weight; + hlmdl_anim_t *anim; + } blend[8]; + //right, so, this stuff is annoying. + //we have two different blend factors. + //we have up to 9 blend weights. figure out which frames are what + switch(sequence->hasblendseq) + { + case 0: //erk? + return; + case 1: //no blending. + bf0 = bf1 = 1; + break; + default: + case 2: //mix(0, 1, weight0) + case 3: //mix(0, 1, 2, weight0); + case 8: //weight0 only... + bf0 = sequence->hasblendseq; + bf1 = 1; + break; + case 4: //mix(mix(0, 1, weight0), mix(2, 3, weight0), weight1) + bf0 = bf1 = 2; + break; + //case 6: //??? + // bf[0] = 3; bf[1] = 2; + // break; + case 9: //mix(mix(0, 1, 2, weight0), mix(2, 3, 4, weight0), mix(5, 6, 7, weight0), weight1) + bf0 = bf1 = 3; + break; + } + + subblendfrac1 = (subblendfrac1+1)/2; + subblendfrac2 = (subblendfrac2+1)/2; + bweights = 0; + if (bf0 > 1) + { + float frac = (bf0-1) * bound(0, subblendfrac1, 1); + int f1 = bound(0, frac, bf0-1); + int f2 = bound(0, f1+1, bf0-1); + frac = (frac-f1); + frac = bound(0, frac, 1); + if (bf1 > 1) + { + float frac2 = (bf1-1) * bound(0, subblendfrac2, 1); + int a1 = bound(0, frac2, bf1-1); + int a2 = bound(0, a1+1, bf1-1); + frac2 = (frac2-a1); + frac2 = bound(0, frac2, 1); + + if (frac2) + { + if (frac) + { + blend[bweights].frame = frame1; + blend[bweights].anim = animation + model->header->numbones * (f2 + a2*bf0); + blend[bweights++].weight = frac*frac2; + } + if (1-frac) + { + blend[bweights].frame = frame1; + blend[bweights].anim = animation + model->header->numbones * (f1 + a2*bf0); + blend[bweights++].weight = (1-frac)*frac2; + } + } + + if (1-frac2) + { + if (frac) + { + blend[bweights].frame = frame1; + blend[bweights].anim = animation + model->header->numbones * (f2 + a1*bf0); + blend[bweights++].weight = frac*(1-frac2); + } + if (1-frac) + { + blend[bweights].frame = frame1; + blend[bweights].anim = animation + model->header->numbones * (f1 + a1*bf0); + blend[bweights++].weight = (1-frac)*(1-frac2); + } + } + } + else + { + if (frac) + { + blend[bweights].frame = frame1; + blend[bweights].anim = animation + model->header->numbones * f1; + blend[bweights++].weight = frac; + } + if (1-frac) + { + blend[bweights].frame = frame1; + blend[bweights].anim = animation + model->header->numbones * f2; + blend[bweights++].weight = 1-frac; + } + } + } + else + { + blend[bweights].frame = frame1; + blend[bweights].anim = animation; + blend[bweights++].weight = 1; + } + if (frame1 != frame2) + { + for (i = 0; i < bweights; i++) + { + blend[bweights+i].frame = frame2; + blend[bweights+i].anim = blend[i].anim; + blend[bweights+i].weight = blend[i].weight; + + blend[i].weight *= 1-frametime; + blend[bweights+i].weight *= frametime; + } + bweights *= 2; + } + for(i = firstbone; i < lastbone; i++, matrix+=12) { - //calc first blend (writes organgb+quatb) - HL_CalculateBones(frame1, model->adjust, model->bones + i, animation + i, organgb[0]); - QuaternionGLAngle(organgb[1], quatb); /* A quaternion */ - if (frame1 != frame2) - { - HL_CalculateBones(frame2, model->adjust, model->bones + i, animation + i, organg2[0]); - QuaternionGLAngle(organg2[1], quat2); /* A quaternion */ + vec3_t t; + float len; - QuaternionSlerp(quatb, quat2, frametime, quatb); - VectorInterpolate(organgb[0], frametime, organg2[0], organgb[0]); + HL_CalculateBones(blend[0].frame, model->adjust, model->bones + i, blend[0].anim + i, organgb[0]); + QuaternionGLAngle(organgb[1], quat2); + Vector4Scale(quat2, blend[0].weight, quat1); + VectorScale(organgb[0], blend[0].weight, t); + + for (j = 1; j < bweights; j++) + { + HL_CalculateBones(blend[j].frame, model->adjust, model->bones + i, blend[j].anim + i, organgb[0]); + QuaternionGLAngle(organgb[1], quat2); + if (DotProduct4(quat2, quat1) < 0) //negative quats are annoying + Vector4MA(quat1, -blend[j].weight, quat2, quat1); + else + Vector4MA(quat1, blend[j].weight, quat2, quat1); + VectorMA(t, blend[j].weight, organgb[0], t); } - //calc first blend (writes organg1+quat1) - HL_CalculateBones(frame1, model->adjust, model->bones + i, animation + i + model->header->numbones, organg1[0]); - QuaternionGLAngle(organg1[1], quat1); /* A quaternion */ - if (frame1 != frame2) + //we were lame and didn't use slerp. boo hiss. now we need to normalise the things and hope we didn't hit any singularities + len = sqrt(DotProduct4(quat1,quat1)); + if (len && len != 1) { - HL_CalculateBones(frame2, model->adjust, model->bones + i, animation + i + model->header->numbones, organg2[0]); - QuaternionGLAngle(organg2[1], quat2); /* A quaternion */ - - QuaternionSlerp(quat1, quat2, frametime, quat1); - VectorInterpolate(organg1[0], frametime, organg2[0], organg1[0]); + len = 1/len; + quat1[0] *= len; + quat1[1] *= len; + quat1[2] *= len; + quat1[3] *= len; } - //blend the two, figure out a matrix. - QuaternionSlerp(quatb, quat1, subblendfrac, quat1); QuaternionGLMatrix(quat1[0], quat1[1], quat1[2], quat1[3], (vec4_t*)matrix); - FloatInterpolate(organgb[0][0], subblendfrac, organg1[0][0], matrix[0*4+3]); - FloatInterpolate(organgb[0][1], subblendfrac, organg1[0][1], matrix[1*4+3]); - FloatInterpolate(organgb[0][2], subblendfrac, organg1[0][2], matrix[2*4+3]); + matrix[0*4+3] = t[0]; + matrix[1*4+3] = t[1]; + matrix[2*4+3] = t[2]; } } else { - //FIXME: disgusting hack to get CS player models not looking like total idiots. but merely regular ones instead. - if (sequence->hasblendseq == 9) - animation += 4*model->header->numbones; - for(i = firstbone; i < lastbone; i++, matrix+=12) { HL_CalculateBones(frame1, model->adjust, model->bones + i, animation + i, organg1[0]); @@ -797,7 +913,7 @@ static int HLMDL_GetBoneData_Internal(hlmodel_t *model, int firstbone, int lastb lastbone = model->header->numbones; if (cbone >= lastbone) continue; - HL_SetupBones(model, fstate->g[bgroup].frame[0], cbone, lastbone, (fstate->g[bgroup].subblendfrac+1)*0.5, fstate->g[bgroup].frametime[0], result); /* Setup the bones */ + HL_SetupBones(model, fstate->g[bgroup].frame[0], cbone, lastbone, fstate->g[bgroup].subblendfrac, fstate->g[bgroup].subblend2frac, fstate->g[bgroup].frametime[0], result); /* Setup the bones */ cbone = lastbone; } return cbone; @@ -1064,7 +1180,7 @@ void R_HL_BuildFrame(hlmodel_t *model, hlmdl_submodel_t *amodel, entity_t *curen lastbone = model->header->numbones; if (cbone >= lastbone) continue; - HL_SetupBones(model, curent->framestate.g[bgroup].frame[0], cbone, lastbone, (curent->framestate.g[bgroup].subblendfrac+1)*0.5, curent->framestate.g[bgroup].frametime[0], relatives); // Setup the bones + HL_SetupBones(model, curent->framestate.g[bgroup].frame[0], cbone, lastbone, curent->framestate.g[bgroup].subblendfrac, curent->framestate.g[bgroup].frametime[0], relatives); // Setup the bones cbone = lastbone; } */ diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index fe4dc99b2..11db50fe8 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -3351,7 +3351,7 @@ TRACE(("dbg: Mod_LoadTextures: inittexturedescs\n")); } mt = (miptex_t *)((qbyte *)m + m->dataofs[i]); - TRACE(("dbg: Mod_LoadTextures: texture %s\n", loadname)); + TRACE(("dbg: Mod_LoadTextures: texture %s\n", mt->name)); if (!*mt->name) //I HATE MAPPERS! { diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index 1c788c0b4..1140e3029 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -28,7 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern cvar_t gl_lightmap_nearest; -void GLBE_ClearVBO(vbo_t *vbo) +void GLBE_ClearVBO(vbo_t *vbo, qboolean dataonly) { int vboh[6 + MAXRLIGHTMAPS]; int i, j; @@ -41,6 +41,14 @@ void GLBE_ClearVBO(vbo_t *vbo) for (i = 0; i < MAXRLIGHTMAPS; i++) vboh[6+i] = vbo->lmcoord[i].gl.vbo; + memset (&vbo->indicies, 0, sizeof(vbo->indicies)); + memset (&vbo->coord, 0, sizeof(vbo->coord)); + memset (&vbo->texcoord, 0, sizeof(vbo->texcoord)); + memset (&vbo->normals, 0, sizeof(vbo->normals)); + memset (&vbo->svector, 0, sizeof(vbo->svector)); + memset (&vbo->tvector, 0, sizeof(vbo->tvector)); + memset (&vbo->lmcoord, 0, sizeof(vbo->lmcoord)); + for (i = 0; i < 7; i++) { if (!vboh[i]) @@ -55,8 +63,11 @@ void GLBE_ClearVBO(vbo_t *vbo) } if (vbo->vertdata) BZ_Free(vbo->vertdata); + vbo->vertdata = NULL; BZ_Free(vbo->meshlist); - BZ_Free(vbo); + vbo->meshlist = NULL; + if (!dataonly) + BZ_Free(vbo); } void GLBE_SetupVAO(vbo_t *vbo, unsigned int vaodynamic, unsigned int vaostatic); diff --git a/engine/gl/gl_viddroid.c b/engine/gl/gl_viddroid.c index d2836163f..2ac5d0f85 100644 --- a/engine/gl/gl_viddroid.c +++ b/engine/gl/gl_viddroid.c @@ -64,6 +64,11 @@ JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_setwindow(JNIEnv *env, jobj r_forceheadless = (sys_jsurface == NULL); + if (r_forceheadless) + Sys_Printf("Running without a window\n"); + else + Sys_Printf("Got a window\n"); + if (qrenderer) //if the window changed then we need to restart everything to match it, BEFORE we return from this function... :( R_RestartRenderer_f(); } @@ -276,6 +281,7 @@ static qboolean VKVID_Init (rendererstate_t *info, unsigned char *palette) //this is simpler than most platforms, as the window itself is handled by java code, and we can't create/destroy it here //(android surfaces can be resized/resampled separately from their window, and are always 'fullscreen' anyway, so this isn't actually an issue for once) const char *extnames[] = {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, NULL}; + Sys_Printf("initialising vulkan...\n"); if (!sys_jsurface) { Sys_Printf("VKVID_Init failed: no window known yet\n"); diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index 1a4990d29..c0c3b7d0d 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -10658,7 +10658,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "colorscale *= 1.0-(dot(spot,spot));\n" "#endif\n" "#ifdef PCF\n" -"colorscale *= ShadowmapFilter(s_t5);\n" +"colorscale *= ShadowmapFilter(s_t5, vtexprojcoord);\n" "#endif\n" "r.rgb *= colorscale * l_lightcolour;\n" @@ -10677,6 +10677,217 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" }, #endif +#ifdef D3D9QUAKE +{QR_DIRECT3D9, 9, "terrain", +"!!permu FOG\n" +"!!samps 5\n" + +"#include \"sys/fog.h\"\n" + +//FIXME: too lazy to implement this right now. +"#undef RTLIGHT\n" +"#undef PCF\n" +"#undef CUBE\n" + +"struct a2v\n" +"{\n" +"float3 pos: POSITION0;\n" +"float2 tc: TEXCOORD0;\n" +"float2 lm: TEXCOORD1;\n" +"float4 vc: COLOR;\n" + +"#ifdef RTLIGHT\n" +"attribute vec3 v_normal;\n" +"attribute vec3 v_svector;\n" +"attribute vec3 v_tvector;\n" +"#endif\n" +"};\n" +"struct v2f\n" +"{\n" +"float1 depth: TEXCOORD1;\n" +"float4 tclm: TEXCOORD0;\n" +"float4 vc: COLOR;\n" + +"#ifdef RTLIGHT\n" +"varying vec3 lightvector;\n" +// #if defined(SPECULAR) || defined(OFFSETMAPPING) +// varying vec3 eyevector; +// #endif +"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n" +"varying vec4 vtexprojcoord;\n" +"#endif\n" +"#endif\n" + +"#ifndef FRAGMENT_SHADER\n" +"float4 pos: POSITION;\n" +"#endif\n" +"};\n" + + + + + +"#ifdef VERTEX_SHADER\n" + +"float4x4 m_model;\n" +"float4x4 m_view;\n" +"float4x4 m_projection;\n" + +"#ifdef RTLIGHT\n" +"uniform vec3 l_lightposition;\n" +// #if defined(SPECULAR) || defined(OFFSETMAPPING) +// uniform vec3 e_eyepos; +// #endif +"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n" +"uniform mat4 l_cubematrix;\n" +"#endif\n" +"#endif\n" + +"float3 e_lmscale;\n" + +"v2f main (a2v inp)\n" +"{\n" +"v2f outp;\n" +"outp.tclm = float4(inp.tc, inp.lm);\n" +"outp.vc = inp.vc;\n" + +"float4 pos = float4(inp.pos, 1);\n" +"pos = mul(m_model, pos);\n" +"pos = mul(m_view, pos);\n" +"outp.depth = pos.z;\n" +"pos = mul(m_projection, pos);\n" +"outp.pos = pos;\n" + +"#ifdef RTLIGHT\n" +//light position is in model space, which is handy. +"vec3 lightminusvertex = l_lightposition - v_position.xyz;\n" + +//no bumpmapping, so we can just use distance without regard for actual surface direction. we still do scalecos stuff. you might notice it on steep slopes. +"lightvector = lightminusvertex;\n" +// lightvector.x = dot(lightminusvertex, v_svector.xyz); +// lightvector.y = dot(lightminusvertex, v_tvector.xyz); +// lightvector.z = dot(lightminusvertex, v_normal.xyz); + +// #if defined(SPECULAR)||defined(OFFSETMAPPING) +// vec3 eyeminusvertex = e_eyepos - v_position.xyz; +// eyevector.x = dot(eyeminusvertex, v_svector.xyz); +// eyevector.y = dot(eyeminusvertex, v_tvector.xyz); +// eyevector.z = dot(eyeminusvertex, v_normal.xyz); +// #endif +"#if defined(PCF) || defined(SPOT) || defined(CUBE)\n" +//for texture projections/shadowmapping on dlights +"vtexprojcoord = (l_cubematrix*vec4(v_position.xyz, 1.0));\n" +"#endif\n" +"#else\n" +"outp.vc.rgb *= e_lmscale.rgb;\n" +"#endif\n" + +"return outp;\n" +"}\n" +"#endif\n" + + + + +"#ifdef FRAGMENT_SHADER\n" +//four texture passes +"sampler s_t0;\n" +"sampler s_t1;\n" +"sampler s_t2;\n" +"sampler s_t3;\n" + +//mix values +"sampler s_t4;\n" + +"#ifdef PCF\n" +"uniform sampler2DShadow s_t5;\n" +"#include \"sys/pcf.h\"\n" +"#endif\n" +"#ifdef CUBE\n" +"uniform samplerCube s_t6;\n" +"#endif\n" + +"#ifdef RTLIGHT\n" +"uniform float l_lightradius;\n" +"uniform vec3 l_lightcolour;\n" +"uniform vec3 l_lightcolourscale;\n" +"#endif\n" + + + + + + + + + + + + + + +"float4 main (v2f inp) : COLOR\n" +"{\n" +"float2 lm = inp.tclm.zw;\n" +"float2 tc = inp.tclm.xy;\n" +"float4 vc = inp.vc;\n" + +"float4 r;\n" +"float4 m = tex2D(s_t4, lm);\n" + +"r = tex2D(s_t0, tc)*m.r;\n" +"r += tex2D(s_t1, tc)*m.g;\n" +"r += tex2D(s_t2, tc)*m.b;\n" +"r += tex2D(s_t3, tc)*(1.0 - (m.r + m.g + m.b));\n" +"r.a = 1.0;\n" + +//vertex colours provide a scaler that applies even through rtlights. +"r *= vc;\n" + +"#ifdef RTLIGHT\n" +"vec3 nl = normalize(lightvector);\n" +"float colorscale = max(1.0 - (dot(lightvector, lightvector)/(l_lightradius*l_lightradius)), 0.0);\n" +"vec3 diff;\n" +// #ifdef BUMP +// colorscale *= (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(bumps, nl), 0.0)); +// #else +"colorscale *= (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0));\n" +// #endif + +// #ifdef SPECULAR +// vec3 halfdir = normalize(normalize(eyevector) + nl); +// float spec = pow(max(dot(halfdir, bumps), 0.0), 32.0 * specs.a); +// diff += l_lightcolourscale.z * spec * specs.rgb; +// #endif + + + +"#if defined(SPOT)\n" +"if (vtexprojcoord.w < 0.0) discard;\n" +"vec2 spot = ((vtexprojcoord.st)/vtexprojcoord.w);\n" +"colorscale *= 1.0-(dot(spot,spot));\n" +"#endif\n" +"#ifdef PCF\n" +"colorscale *= ShadowmapFilter(s_t5);\n" +"#endif\n" + +"r.rgb *= colorscale * l_lightcolour;\n" + +"#ifdef CUBE\n" +"r.rgb *= textureCube(s_t6, vtexprojcoord.xyz).rgb;\n" +"#endif\n" + +"r = fog4additive(r, inp.pos);\n" +"#else\n" +//lightmap is greyscale in m.a. probably we should just scale the texture mix, but precision errors when editing make me paranoid. +"r.rgb *= m.aaa;\n" +"r = fog4(r, inp.depth);\n" +"#endif\n" +"return r;\n" +"}\n" +"#endif\n" +}, +#endif #ifdef D3D11QUAKE {QR_DIRECT3D11, 11, "terrain", "struct a2v\n" diff --git a/engine/gl/shader.h b/engine/gl/shader.h index c6ed1d9ff..5d8dda4cd 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -787,7 +787,7 @@ void GLBE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, unsig void GLBE_SubmitBatch(batch_t *batch); batch_t *GLBE_GetTempBatch(void); void GLBE_GenBrushModelVBO(model_t *mod); -void GLBE_ClearVBO(vbo_t *vbo); +void GLBE_ClearVBO(vbo_t *vbo, qboolean dataonly); void GLBE_UploadAllLightmaps(void); void GLBE_DrawWorld (batch_t **worldbatches); qboolean GLBE_LightCullModel(vec3_t org, model_t *model); @@ -817,7 +817,7 @@ void D3D8BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, uns void D3D8BE_SubmitBatch(batch_t *batch); batch_t *D3D8BE_GetTempBatch(void); void D3D8BE_GenBrushModelVBO(model_t *mod); -void D3D8BE_ClearVBO(vbo_t *vbo); +void D3D8BE_ClearVBO(vbo_t *vbo, qboolean dataonly); void D3D8BE_UploadAllLightmaps(void); void D3D8BE_DrawWorld (batch_t **worldbatches); qboolean D3D8BE_LightCullModel(vec3_t org, model_t *model); @@ -842,7 +842,7 @@ void D3D9BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, uns void D3D9BE_SubmitBatch(batch_t *batch); batch_t *D3D9BE_GetTempBatch(void); void D3D9BE_GenBrushModelVBO(model_t *mod); -void D3D9BE_ClearVBO(vbo_t *vbo); +void D3D9BE_ClearVBO(vbo_t *vbo, qboolean dataonly); void D3D9BE_UploadAllLightmaps(void); void D3D9BE_DrawWorld (batch_t **worldbatches); qboolean D3D9BE_LightCullModel(vec3_t org, model_t *model); @@ -867,7 +867,7 @@ void D3D11BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, un void D3D11BE_SubmitBatch(batch_t *batch); batch_t *D3D11BE_GetTempBatch(void); void D3D11BE_GenBrushModelVBO(model_t *mod); -void D3D11BE_ClearVBO(vbo_t *vbo); +void D3D11BE_ClearVBO(vbo_t *vbo, qboolean dataonly); void D3D11BE_UploadAllLightmaps(void); void D3D11BE_DrawWorld (batch_t **worldbatches); qboolean D3D11BE_LightCullModel(vec3_t org, model_t *model); diff --git a/engine/server/progdefs.h b/engine/server/progdefs.h index 6e02582d3..90bf24606 100644 --- a/engine/server/progdefs.h +++ b/engine/server/progdefs.h @@ -318,8 +318,10 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldfloat(bonecontrol3,"Halflife model format bone controller. On player models, this typically affects the spine's yaw.") /*FTE_CSQC_HALFLIFE_MODELS*/\ comfieldfloat(bonecontrol4,"Halflife model format bone controller. On player models, this typically affects the spine's yaw.") /*FTE_CSQC_HALFLIFE_MODELS*/\ comfieldfloat(bonecontrol5,"Halflife model format bone controller. This typically affects the mouth.") /*FTE_CSQC_HALFLIFE_MODELS*/\ - comfieldfloat(subblendfrac,"Weird animation value specific to halflife models. On player models, this typically affects the spine's pitch.") /*FTE_CSQC_HALFLIFE_MODELS*/\ - comfieldfloat(basesubblendfrac,"See basebone") /*FTE_CSQC_HALFLIFE_MODELS+FTE_CSQC_BASEFRAME*/ + comfieldfloat(subblendfrac,"Weird animation value specific to halflife models. On player models, this typically affects the spine's pitch, or yaw, or...") /*FTE_CSQC_HALFLIFE_MODELS*/\ + comfieldfloat(subblend2frac,"Weird animation value specific to halflife models. I've no idea what this does, probably nothing for most models.") /*FTE_CSQC_HALFLIFE_MODELS*/\ + comfieldfloat(basesubblendfrac,"See basebone") /*FTE_CSQC_HALFLIFE_MODELS+FTE_CSQC_BASEFRAME*/\ + comfieldfloat(basesubblend2frac,"See basebone") /*FTE_CSQC_HALFLIFE_MODELS+FTE_CSQC_BASEFRAME*/ #else #define HALFLIFEMODEL_FIELDS #endif diff --git a/engine/server/svhl_game.c b/engine/server/svhl_game.c index 6a6932f92..d410ab5fd 100644 --- a/engine/server/svhl_game.c +++ b/engine/server/svhl_game.c @@ -1041,9 +1041,10 @@ static void GHL_GetFrameState(hledict_t *ent, framestate_t *fstate) fstate->g[FS_REG].frametime[0] = (SVHL_Globals.time - ent->v.framestarttime) * ent->v.framerate; fstate->g[FS_REG].frame[0] = ent->v.frame; fstate->g[FS_REG].lerpweight[0] = 1; - fstate->g[FS_REG].subblendfrac = ent->v.blending[0]; //fixme: which is upper? + fstate->g[FS_REG].subblendfrac = ent->v.blending[0]; + fstate->g[FS_REG].subblend2frac = ent->v.blending[1]; - //FIXME: no lower parts. + //FIXME: no lower parts set here. fstate->bonecontrols[0] = ent->v.controller[0] / 255.0; fstate->bonecontrols[1] = ent->v.controller[1] / 255.0; diff --git a/engine/shaders/glsl/terrain.glsl b/engine/shaders/glsl/terrain.glsl index 5421be096..38377c4d4 100644 --- a/engine/shaders/glsl/terrain.glsl +++ b/engine/shaders/glsl/terrain.glsl @@ -135,7 +135,7 @@ void main (void) colorscale *= 1.0-(dot(spot,spot)); #endif #ifdef PCF - colorscale *= ShadowmapFilter(s_t5); + colorscale *= ShadowmapFilter(s_t5, vtexprojcoord); #endif r.rgb *= colorscale * l_lightcolour; diff --git a/engine/shaders/hlsl9/terrain.hlsl b/engine/shaders/hlsl9/terrain.hlsl new file mode 100644 index 000000000..461e91b77 --- /dev/null +++ b/engine/shaders/hlsl9/terrain.hlsl @@ -0,0 +1,207 @@ +!!permu FOG +!!samps 5 + +#include "sys/fog.h" + +//FIXME: too lazy to implement this right now. +#undef RTLIGHT +#undef PCF +#undef CUBE + +struct a2v +{ + float3 pos: POSITION0; + float2 tc: TEXCOORD0; + float2 lm: TEXCOORD1; + float4 vc: COLOR; + +#ifdef RTLIGHT + attribute vec3 v_normal; + attribute vec3 v_svector; + attribute vec3 v_tvector; +#endif +}; +struct v2f +{ + float1 depth: TEXCOORD1; + float4 tclm: TEXCOORD0; + float4 vc: COLOR; + +#ifdef RTLIGHT + varying vec3 lightvector; +// #if defined(SPECULAR) || defined(OFFSETMAPPING) +// varying vec3 eyevector; +// #endif + #if defined(PCF) || defined(CUBE) || defined(SPOT) + varying vec4 vtexprojcoord; + #endif +#endif + +#ifndef FRAGMENT_SHADER + float4 pos: POSITION; +#endif +}; + + + + + +#ifdef VERTEX_SHADER + +float4x4 m_model; +float4x4 m_view; +float4x4 m_projection; + +#ifdef RTLIGHT + uniform vec3 l_lightposition; +// #if defined(SPECULAR) || defined(OFFSETMAPPING) +// uniform vec3 e_eyepos; +// #endif + #if defined(PCF) || defined(CUBE) || defined(SPOT) + uniform mat4 l_cubematrix; + #endif +#endif + +float3 e_lmscale; + +v2f main (a2v inp) +{ + v2f outp; + outp.tclm = float4(inp.tc, inp.lm); + outp.vc = inp.vc; + + float4 pos = float4(inp.pos, 1); + pos = mul(m_model, pos); + pos = mul(m_view, pos); + outp.depth = pos.z; + pos = mul(m_projection, pos); + outp.pos = pos; + + #ifdef RTLIGHT + //light position is in model space, which is handy. + vec3 lightminusvertex = l_lightposition - v_position.xyz; + + //no bumpmapping, so we can just use distance without regard for actual surface direction. we still do scalecos stuff. you might notice it on steep slopes. + lightvector = lightminusvertex; +// lightvector.x = dot(lightminusvertex, v_svector.xyz); +// lightvector.y = dot(lightminusvertex, v_tvector.xyz); +// lightvector.z = dot(lightminusvertex, v_normal.xyz); + +// #if defined(SPECULAR)||defined(OFFSETMAPPING) +// vec3 eyeminusvertex = e_eyepos - v_position.xyz; +// eyevector.x = dot(eyeminusvertex, v_svector.xyz); +// eyevector.y = dot(eyeminusvertex, v_tvector.xyz); +// eyevector.z = dot(eyeminusvertex, v_normal.xyz); +// #endif + #if defined(PCF) || defined(SPOT) || defined(CUBE) + //for texture projections/shadowmapping on dlights + vtexprojcoord = (l_cubematrix*vec4(v_position.xyz, 1.0)); + #endif + #else + outp.vc.rgb *= e_lmscale.rgb; + #endif + + return outp; +} +#endif + + + + +#ifdef FRAGMENT_SHADER +//four texture passes +sampler s_t0; +sampler s_t1; +sampler s_t2; +sampler s_t3; + +//mix values +sampler s_t4; + +#ifdef PCF + uniform sampler2DShadow s_t5; + #include "sys/pcf.h" +#endif +#ifdef CUBE + uniform samplerCube s_t6; +#endif + +#ifdef RTLIGHT + uniform float l_lightradius; + uniform vec3 l_lightcolour; + uniform vec3 l_lightcolourscale; +#endif + + + + + + + + + + + + + + +float4 main (v2f inp) : COLOR +{ + float2 lm = inp.tclm.zw; + float2 tc = inp.tclm.xy; + float4 vc = inp.vc; + + float4 r; + float4 m = tex2D(s_t4, lm); + + r = tex2D(s_t0, tc)*m.r; + r += tex2D(s_t1, tc)*m.g; + r += tex2D(s_t2, tc)*m.b; + r += tex2D(s_t3, tc)*(1.0 - (m.r + m.g + m.b)); + r.a = 1.0; + + //vertex colours provide a scaler that applies even through rtlights. + r *= vc; + +#ifdef RTLIGHT + vec3 nl = normalize(lightvector); + float colorscale = max(1.0 - (dot(lightvector, lightvector)/(l_lightradius*l_lightradius)), 0.0); + vec3 diff; +// #ifdef BUMP +// colorscale *= (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(bumps, nl), 0.0)); +// #else + colorscale *= (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0)); +// #endif + +// #ifdef SPECULAR +// vec3 halfdir = normalize(normalize(eyevector) + nl); +// float spec = pow(max(dot(halfdir, bumps), 0.0), 32.0 * specs.a); +// diff += l_lightcolourscale.z * spec * specs.rgb; +// #endif + + + + #if defined(SPOT) + if (vtexprojcoord.w < 0.0) discard; + vec2 spot = ((vtexprojcoord.st)/vtexprojcoord.w); + colorscale *= 1.0-(dot(spot,spot)); + #endif + #ifdef PCF + colorscale *= ShadowmapFilter(s_t5); + #endif + + r.rgb *= colorscale * l_lightcolour; + + #ifdef CUBE + r.rgb *= textureCube(s_t6, vtexprojcoord.xyz).rgb; + #endif + + r = fog4additive(r, inp.pos); +#else + //lightmap is greyscale in m.a. probably we should just scale the texture mix, but precision errors when editing make me paranoid. + r.rgb *= m.aaa; + r = fog4(r, inp.depth); +#endif + return r; +} +#endif \ No newline at end of file diff --git a/engine/sw/sw.h b/engine/sw/sw.h index 455258b34..79f1883da 100644 --- a/engine/sw/sw.h +++ b/engine/sw/sw.h @@ -170,7 +170,7 @@ struct batch_s *SWBE_GetTempBatch(void); void SWBE_DrawWorld(batch_t **worldbatches); void SWBE_Init(void); void SWBE_GenBrushModelVBO(struct model_s *mod); -void SWBE_ClearVBO(struct vbo_s *vbo); +void SWBE_ClearVBO(struct vbo_s *vbo, qboolean dataonly); void SWBE_UploadAllLightmaps(void); void SWBE_SelectEntity(struct entity_s *ent); qboolean SWBE_SelectDLight(struct dlight_s *dl, vec3_t colour, vec3_t axis[3], unsigned int lmode); diff --git a/engine/sw/sw_backend.c b/engine/sw/sw_backend.c index 949a03de9..c613c2aeb 100644 --- a/engine/sw/sw_backend.c +++ b/engine/sw/sw_backend.c @@ -654,7 +654,7 @@ void SWBE_Init(void) void SWBE_GenBrushModelVBO(struct model_s *mod) { } -void SWBE_ClearVBO(struct vbo_s *vbo) +void SWBE_ClearVBO(struct vbo_s *vbo, qboolean dataonly) { } void SWBE_UploadAllLightmaps(void) diff --git a/engine/vk/vk_backend.c b/engine/vk/vk_backend.c index 2d83a548e..0603ed2ac 100644 --- a/engine/vk/vk_backend.c +++ b/engine/vk/vk_backend.c @@ -4010,8 +4010,20 @@ static void VKBE_SafeClearVBO(void *vboptr) BZ_Free(vbo); } /*Wipes a vbo*/ -void VKBE_ClearVBO(vbo_t *vbo) +void VKBE_ClearVBO(vbo_t *vbo, qboolean dataonly) { + if (dataonly) + { + //create one for the safe callback to clear. + vbo_t *nvbo = BZ_Malloc(sizeof(*vbo)); + nvbo->indicies = vbo->indicies; + nvbo->coord = vbo->coord; + + //scrub it now + memset(&vbo->indicies, 0, sizeof(vbo->indicies)); + memset(&vbo->coord, 0, sizeof(vbo->coord)); + vbo = nvbo; + } VK_AtFrameEnd(VKBE_SafeClearVBO, &vbo, sizeof(vbo)); } diff --git a/engine/vk/vkrenderer.h b/engine/vk/vkrenderer.h index 3fccf50b3..6378e1ad3 100644 --- a/engine/vk/vkrenderer.h +++ b/engine/vk/vkrenderer.h @@ -410,7 +410,7 @@ void VKBE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, unsig void VKBE_SubmitBatch(batch_t *batch); batch_t *VKBE_GetTempBatch(void); void VKBE_GenBrushModelVBO(model_t *mod); -void VKBE_ClearVBO(vbo_t *vbo); +void VKBE_ClearVBO(vbo_t *vbo, qboolean dataonly); void VKBE_UploadAllLightmaps(void); void VKBE_DrawWorld (batch_t **worldbatches); qboolean VKBE_LightCullModel(vec3_t org, model_t *model);