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);