e6d1ae1a8f
gl_rsurf.c has been split into gl specific and generic code - the d3d renderer can now draw the world. ifdef removed the old server-side mvd playback which had been disabled all this time anyway. git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3426 fc73d0e0-1445-4013-8a0c-d673dee63da5
412 lines
11 KiB
C
412 lines
11 KiB
C
#include "quakedef.h"
|
|
#ifdef D3DQUAKE
|
|
#include "shader.h"
|
|
|
|
#include <d3d9.h>
|
|
extern LPDIRECT3DDEVICE9 pD3DDev9;
|
|
|
|
typedef struct
|
|
{
|
|
shader_t *curshader;
|
|
texnums_t *curtexnums;
|
|
texid_t curlightmap;
|
|
texid_t curdeluxmap;
|
|
} d3dbackend_t;
|
|
|
|
static d3dbackend_t d3dbackend;
|
|
|
|
extern int be_maxpasses;
|
|
|
|
void BE_Init(void)
|
|
{
|
|
be_maxpasses = 1;
|
|
}
|
|
|
|
static void D3DBE_ApplyShaderBits(unsigned int bits)
|
|
{
|
|
if (bits & SBITS_BLEND_BITS)
|
|
{
|
|
int src;
|
|
int dst;
|
|
|
|
switch(bits & SBITS_SRCBLEND_BITS)
|
|
{
|
|
case SBITS_SRCBLEND_ZERO: src = D3DBLEND_ZERO; break;
|
|
case SBITS_SRCBLEND_ONE: src = D3DBLEND_ONE; break;
|
|
case SBITS_SRCBLEND_DST_COLOR: src = D3DBLEND_DESTCOLOR; break;
|
|
case SBITS_SRCBLEND_ONE_MINUS_DST_COLOR: src = D3DBLEND_INVDESTCOLOR; break;
|
|
case SBITS_SRCBLEND_SRC_ALPHA: src = D3DBLEND_SRCALPHA; break;
|
|
case SBITS_SRCBLEND_ONE_MINUS_SRC_ALPHA: src = D3DBLEND_INVSRCALPHA; break;
|
|
case SBITS_SRCBLEND_DST_ALPHA: src = D3DBLEND_DESTALPHA; break;
|
|
case SBITS_SRCBLEND_ONE_MINUS_DST_ALPHA: src = D3DBLEND_INVDESTALPHA; break;
|
|
case SBITS_SRCBLEND_ALPHA_SATURATE: src = D3DBLEND_SRCALPHASAT; break;
|
|
default: Sys_Error("Bad shader blend src\n"); return;
|
|
}
|
|
switch(bits & SBITS_DSTBLEND_BITS)
|
|
{
|
|
case SBITS_DSTBLEND_ZERO: dst = D3DBLEND_ZERO; break;
|
|
case SBITS_DSTBLEND_ONE: dst = D3DBLEND_ONE; break;
|
|
case SBITS_DSTBLEND_SRC_ALPHA: dst = D3DBLEND_SRCALPHA; break;
|
|
case SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA: dst = D3DBLEND_INVSRCALPHA; break;
|
|
case SBITS_DSTBLEND_DST_ALPHA: dst = D3DBLEND_DESTALPHA; break;
|
|
case SBITS_DSTBLEND_ONE_MINUS_DST_ALPHA: dst = D3DBLEND_INVDESTALPHA; break;
|
|
case SBITS_DSTBLEND_SRC_COLOR: dst = D3DBLEND_SRCCOLOR; break;
|
|
case SBITS_DSTBLEND_ONE_MINUS_SRC_COLOR: dst = D3DBLEND_INVSRCCOLOR; break;
|
|
default: Sys_Error("Bad shader blend dst\n"); return;
|
|
}
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHABLENDENABLE, TRUE);
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_SRCBLEND, src);
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_DESTBLEND, dst);
|
|
}
|
|
else
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHABLENDENABLE, FALSE);
|
|
|
|
switch(bits & SBITS_ATEST_BITS)
|
|
{
|
|
case SBITS_ATEST_NONE:
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHATESTENABLE, FALSE);
|
|
// IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAREF, 0);
|
|
// IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAFUNC, 0);
|
|
break;
|
|
case SBITS_ATEST_GT0:
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHATESTENABLE, TRUE);
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAREF, 0);
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAFUNC, D3DCMP_GREATER);
|
|
break;
|
|
case SBITS_ATEST_LT128:
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHATESTENABLE, TRUE);
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAREF, 128);
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAFUNC, D3DCMP_LESS);
|
|
break;
|
|
case SBITS_ATEST_GE128:
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHATESTENABLE, TRUE);
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAREF, 128);
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
|
break;
|
|
}
|
|
|
|
if(bits & SBITS_MISC_DEPTHWRITE)
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ZWRITEENABLE, TRUE);
|
|
else
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ZWRITEENABLE, FALSE);
|
|
|
|
if(bits & SBITS_MISC_NODEPTHTEST)
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ZENABLE, FALSE);
|
|
else
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ZENABLE, TRUE);
|
|
|
|
switch(bits & (SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY))
|
|
{
|
|
default:
|
|
case 0:
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
|
|
break;
|
|
case SBITS_MISC_DEPTHEQUALONLY:
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ZFUNC, D3DCMP_EQUAL);
|
|
break;
|
|
case SBITS_MISC_DEPTHCLOSERONLY:
|
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ZFUNC, D3DCMP_LESS);
|
|
break;
|
|
}
|
|
}
|
|
|
|
unsigned int workingbuffer[65536];
|
|
static void BE_DrawMeshChain_Internal(mesh_t *meshchain)
|
|
{
|
|
float *xyz;
|
|
unsigned int *colour;
|
|
float *st[1];
|
|
unsigned int fmt = 0;
|
|
unsigned int stride;
|
|
int i;
|
|
|
|
if (!d3dbackend.curshader)
|
|
return;
|
|
if (!d3dbackend.curtexnums)
|
|
return;
|
|
|
|
stride = 0;
|
|
memset(workingbuffer, 0, sizeof(workingbuffer));
|
|
xyz = (float*)(workingbuffer+stride);
|
|
stride += 3;
|
|
fmt |= D3DFVF_XYZ;
|
|
|
|
colour = (unsigned int*)(workingbuffer+stride);
|
|
stride += 1;
|
|
fmt |= D3DFVF_DIFFUSE;
|
|
|
|
st[0] = (float*)(workingbuffer+stride);
|
|
stride += 2;
|
|
fmt |= D3DFVF_TEX1;
|
|
|
|
D3DBE_ApplyShaderBits(d3dbackend.curshader->passes[0].shaderbits);
|
|
|
|
IDirect3DDevice9_SetFVF(pD3DDev9, fmt);
|
|
|
|
switch(d3dbackend.curshader->passes[0].texgen)
|
|
{
|
|
default:
|
|
case T_GEN_DIFFUSE:
|
|
IDirect3DDevice9_SetTexture (pD3DDev9, 0, d3dbackend.curtexnums->base.ptr);
|
|
break;
|
|
case T_GEN_SINGLEMAP:
|
|
IDirect3DDevice9_SetTexture (pD3DDev9, 0, d3dbackend.curshader->passes[0].anim_frames[0].ptr);
|
|
break;
|
|
}
|
|
switch(d3dbackend.curshader->passes[1].texgen)
|
|
{
|
|
case T_GEN_LIGHTMAP:
|
|
IDirect3DDevice9_SetTexture (pD3DDev9, 1, d3dbackend.curlightmap.ptr);
|
|
|
|
IDirect3DDevice9_SetTextureStageState(pD3DDev9, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
|
IDirect3DDevice9_SetTextureStageState(pD3DDev9, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
|
|
IDirect3DDevice9_SetTextureStageState(pD3DDev9, 1, D3DTSS_COLOROP, D3DTOP_MODULATE2X);
|
|
break;
|
|
default:
|
|
IDirect3DDevice9_SetTexture (pD3DDev9, 1, NULL);
|
|
IDirect3DDevice9_SetTextureStageState(pD3DDev9, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
|
break;
|
|
}
|
|
|
|
if (meshchain->colors4b_array)
|
|
{
|
|
/*I'm guessing I ought to create a temp vertex buffer for this*/
|
|
for (; meshchain; meshchain = meshchain->next)
|
|
{
|
|
for (i = 0; i < meshchain->numvertexes; i++)
|
|
{
|
|
VectorCopy(meshchain->xyz_array[i], (xyz+stride*i));
|
|
*(colour+stride*i) = ((unsigned int)meshchain->colors4b_array[i][3]<<24) | ((unsigned int)meshchain->colors4b_array[i][0]<<16) | ((unsigned int)meshchain->colors4b_array[i][1]<<8) | ((unsigned int)meshchain->colors4b_array[i][2]);
|
|
Vector2Copy(meshchain->st_array[i], (st[0]+stride*i));
|
|
}
|
|
IDirect3DDevice9_DrawIndexedPrimitiveUP(pD3DDev9, D3DPT_TRIANGLELIST, 0, meshchain->numvertexes, meshchain->numindexes/3, meshchain->indexes, D3DFMT_QINDEX, workingbuffer, stride*4);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*I'm guessing I ought to create a temp vertex buffer for this*/
|
|
for (; meshchain; meshchain = meshchain->next)
|
|
{
|
|
for (i = 0; i < meshchain->numvertexes; i++)
|
|
{
|
|
VectorCopy(meshchain->xyz_array[i], (xyz+stride*i));
|
|
*(colour+stride*i) = 0xffffffff;//*(unsigned int*)meshchain->colors4b_array[i];
|
|
Vector2Copy(meshchain->st_array[i], (st[0]+stride*i));
|
|
}
|
|
IDirect3DDevice9_DrawIndexedPrimitiveUP(pD3DDev9, D3DPT_TRIANGLELIST, 0, meshchain->numvertexes, meshchain->numindexes/3, meshchain->indexes, D3DFMT_QINDEX, workingbuffer, stride*4);
|
|
}
|
|
}
|
|
}
|
|
|
|
void BE_DrawMeshChain(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums)
|
|
{
|
|
d3dbackend.curshader = shader;
|
|
d3dbackend.curtexnums = texnums;
|
|
BE_DrawMeshChain_Internal(meshchain);
|
|
}
|
|
|
|
void BE_SelectMode(backendmode_t mode, unsigned int flags)
|
|
{
|
|
}
|
|
|
|
/*Generates an optimised vbo for each of the given model's textures*/
|
|
void BE_GenBrushModelVBO(model_t *mod)
|
|
{
|
|
}
|
|
/*Wipes a vbo*/
|
|
void BE_ClearVBO(vbo_t *vbo)
|
|
{
|
|
}
|
|
|
|
/*upload all lightmaps at the start to reduce lags*/
|
|
void BE_UploadAllLightmaps(void)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void DrawSurfaceChain(msurface_t *s, shader_t *shader, vbo_t *vbo)
|
|
{ //doesn't merge surfaces, but tells gl to do each vertex arrayed surface individually, which means no vertex copying.
|
|
int i;
|
|
mesh_t *ml, *m;
|
|
|
|
if (!vbo)
|
|
return;
|
|
|
|
d3dbackend.curshader = shader;
|
|
d3dbackend.curtexnums = &shader->defaulttextures;
|
|
|
|
ml = NULL;
|
|
for (; s ; s=s->texturechain)
|
|
{
|
|
m = s->mesh;
|
|
if (!m) //urm.
|
|
continue;
|
|
if (m->numvertexes <= 1)
|
|
continue;
|
|
|
|
if (s->lightmaptexturenum < 0)
|
|
{
|
|
//pull out the surfaces with no lightmap info
|
|
m->next = ml;
|
|
ml = m;
|
|
}
|
|
else
|
|
{
|
|
//surfaces that do have a lightmap
|
|
m->next = lightmap[s->lightmaptexturenum]->meshchain;
|
|
lightmap[s->lightmaptexturenum]->meshchain = m;
|
|
}
|
|
}
|
|
|
|
if (ml)
|
|
{
|
|
//draw the lightmapless surfaces
|
|
BE_DrawMeshChain_Internal(ml);
|
|
}
|
|
|
|
//and then draw the lit chains
|
|
for (i = 0; i < numlightmaps; i++)
|
|
{
|
|
if (!lightmap[i] || !lightmap[i]->meshchain)
|
|
continue;
|
|
/*
|
|
if (lightmap[i]->modified)
|
|
{
|
|
glRect_t *theRect;
|
|
lightmap[i]->modified = false;
|
|
theRect = &lightmap[i]->rectchange;
|
|
GL_Bind(lightmap_textures[i]);
|
|
qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t,
|
|
LMBLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
|
|
lightmap[i]->lightmaps+(theRect->t) *LMBLOCK_WIDTH*lightmap_bytes);
|
|
theRect->l = LMBLOCK_WIDTH;
|
|
theRect->t = LMBLOCK_HEIGHT;
|
|
theRect->h = 0;
|
|
theRect->w = 0;
|
|
checkerror();
|
|
|
|
if (lightmap[i]->deluxmodified)
|
|
{
|
|
lightmap[i]->deluxmodified = false;
|
|
theRect = &lightmap[i]->deluxrectchange;
|
|
GL_Bind(deluxmap_textures[i]);
|
|
qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t,
|
|
LMBLOCK_WIDTH, theRect->h, GL_RGB, GL_UNSIGNED_BYTE,
|
|
lightmap[i]->deluxmaps+(theRect->t) *LMBLOCK_WIDTH*3);
|
|
theRect->l = LMBLOCK_WIDTH;
|
|
theRect->t = LMBLOCK_HEIGHT;
|
|
theRect->h = 0;
|
|
theRect->w = 0;
|
|
checkerror();
|
|
}
|
|
}
|
|
*/
|
|
d3dbackend.curlightmap = lightmap_textures[i];
|
|
d3dbackend.curdeluxmap = deluxmap_textures[i];
|
|
BE_DrawMeshChain_Internal(lightmap[i]->meshchain);
|
|
lightmap[i]->meshchain = NULL;
|
|
}
|
|
}
|
|
|
|
static void BE_BaseTextureChain(msurface_t *first)
|
|
{
|
|
texture_t *t, *tex;
|
|
shader_t *shader;
|
|
t = first->texinfo->texture;
|
|
tex = R_TextureAnimation (t);
|
|
|
|
//TEMP: use shader as an input parameter, not tex.
|
|
shader = tex->shader;
|
|
if (!shader)
|
|
{
|
|
shader = R_RegisterShader_Lightmap(tex->name);
|
|
tex->shader = shader;
|
|
}
|
|
DrawSurfaceChain(first, shader, &t->vbo);
|
|
}
|
|
|
|
void BE_BaseEntTextures(void)
|
|
{
|
|
extern model_t *currentmodel;
|
|
int i;
|
|
entity_t *ent;
|
|
|
|
if (!r_drawentities.ival)
|
|
return;
|
|
|
|
// draw sprites seperately, because of alpha blending
|
|
for (i=0 ; i<cl_numvisedicts ; i++)
|
|
{
|
|
ent = &cl_visedicts[i];
|
|
if (!ent->model)
|
|
continue;
|
|
if (ent->model->needload)
|
|
continue;
|
|
// if (!PPL_ShouldDraw())
|
|
// continue;
|
|
switch(ent->model->type)
|
|
{
|
|
case mod_brush:
|
|
// BaseBrushTextures(ent);
|
|
break;
|
|
case mod_alias:
|
|
R_DrawGAliasModel (ent, BEM_STANDARD);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void BE_SubmitMeshes (void)
|
|
{
|
|
texture_t *t;
|
|
msurface_t *s;
|
|
int i;
|
|
model_t *model = cl.worldmodel;
|
|
unsigned int fl;
|
|
|
|
for (i=0 ; i<model->numtextures ; i++)
|
|
{
|
|
t = model->textures[i];
|
|
if (!t)
|
|
continue;
|
|
s = t->texturechain;
|
|
if (!s)
|
|
continue;
|
|
|
|
fl = s->texinfo->texture->shader->flags;
|
|
BE_BaseTextureChain(s);
|
|
}
|
|
|
|
BE_BaseEntTextures();
|
|
}
|
|
|
|
void BE_DrawWorld (qbyte *vis)
|
|
{
|
|
RSpeedLocals();
|
|
|
|
//make sure the world draws correctly
|
|
r_worldentity.shaderRGBAf[0] = 1;
|
|
r_worldentity.shaderRGBAf[1] = 1;
|
|
r_worldentity.shaderRGBAf[2] = 1;
|
|
r_worldentity.shaderRGBAf[3] = 1;
|
|
r_worldentity.axis[0][0] = 1;
|
|
r_worldentity.axis[1][1] = 1;
|
|
r_worldentity.axis[2][2] = 1;
|
|
|
|
BE_SelectMode(BEM_STANDARD, 0);
|
|
|
|
RSpeedRemark();
|
|
BE_SubmitMeshes();
|
|
RSpeedEnd(RSPEED_WORLD);
|
|
}
|
|
|
|
|
|
#endif
|