Light culling and proper diffuse material.

git-svn-id: https://svn.eduke32.com/eduke32@1233 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
plagman 2009-03-08 20:38:51 +00:00
parent 3da52aede8
commit ad1091b2df
2 changed files with 185 additions and 41 deletions

View file

@ -99,10 +99,30 @@ typedef struct s_prprogrambit {
char* frag_prog; char* frag_prog;
} _prprogrambit; } _prprogrambit;
// LIGHTS
#define PR_MAXLIGHTS 128
#define PR_SM3_MAXLIGHTS 4
#define STR_EXPAND(tok) #tok
#define STR(tok) STR_EXPAND(tok)
typedef enum {
PR_LIGHT_POINT,
PR_LIGHT_SPOT,
PR_LIGHT_DIRECTIONAL
} prlighttype;
typedef struct s_prlight {
int32_t x, y, z, horiz, faderange, range;
int16_t angle, sector;
char color[3];
prlighttype type;
} _prlight;
// BUILD DATA // BUILD DATA
typedef struct s_prplane { typedef struct s_prplane {
// geometry // geometry
GLfloat* buffer; GLfloat* buffer;
int32_t vertcount;
GLuint vbo; GLuint vbo;
// attributes // attributes
GLdouble plane[4]; GLdouble plane[4];
@ -110,6 +130,9 @@ typedef struct s_prplane {
// elements // elements
GLushort* indices; GLushort* indices;
GLuint ivbo; GLuint ivbo;
// lights
char lights[PR_MAXLIGHTS];
char lightcount;
} _prplane; } _prplane;
typedef struct s_prsector { typedef struct s_prsector {
@ -165,25 +188,6 @@ typedef struct s_pranimatespritesinfo {
int32_t x, y, a, smoothratio; int32_t x, y, a, smoothratio;
} _pranimatespritesinfo; } _pranimatespritesinfo;
// LIGHTS
#define PR_MAXLIGHTS 128
#define PR_SM3_MAXLIGHTS 4
#define STR_EXPAND(tok) #tok
#define STR(tok) STR_EXPAND(tok)
typedef enum {
PR_LIGHT_POINT,
PR_LIGHT_SPOT,
PR_LIGHT_DIRECTIONAL
} prlighttype;
typedef struct s_prlight {
int32_t x, y, z, horiz, faderange, range;
int16_t angle, sector;
char color[3];
prlighttype type;
} _prlight;
// PROGRAMS // PROGRAMS
// CONTROL // CONTROL
@ -241,11 +245,13 @@ static void polymer_loadmodelvbos(md3model_t* m);
// MATERIALS // MATERIALS
static void polymer_getscratchmaterial(_prmaterial* material); static void polymer_getscratchmaterial(_prmaterial* material);
static void polymer_getbuildmaterial(_prmaterial* material, int16_t tilenum, char pal, int8_t shade); static void polymer_getbuildmaterial(_prmaterial* material, int16_t tilenum, char pal, int8_t shade);
static int32_t polymer_bindmaterial(_prmaterial material, _prlight* lights, int lightcount); static int32_t polymer_bindmaterial(_prmaterial material, char* lights, int lightcount);
static void polymer_unbindmaterial(int32_t programbits); static void polymer_unbindmaterial(int32_t programbits);
static void polymer_compileprogram(int32_t programbits); static void polymer_compileprogram(int32_t programbits);
// LIGHTS // LIGHTS
static void polymer_transformlight(float* inpos, float* pos, float* matrix); static void polymer_transformlight(float* inpos, float* pos, float* matrix);
static int32_t polymer_planeinlight(_prplane* plane, _prlight* light);
static void polymer_culllight(char lightindex);
# endif // !POLYMER_C # endif // !POLYMER_C

View file

@ -194,7 +194,8 @@ _prprogrambit prprogrambits[PR_BIT_COUNT] = {
"uniform sampler2D diffuseMap;\n" "uniform sampler2D diffuseMap;\n"
"\n", "\n",
// frag_prog // frag_prog
" result *= texture2D(diffuseMap, gl_TexCoord[0].st);\n" " diffuseTexel = texture2D(diffuseMap, gl_TexCoord[0].st);\n"
" result *= diffuseTexel;\n"
"\n", "\n",
}, },
{ {
@ -270,9 +271,9 @@ _prprogrambit prprogrambits[PR_BIT_COUNT] = {
" lightAttenuation = 1.0 - (pointLightDistance - lightRange.x) /\n" " lightAttenuation = 1.0 - (pointLightDistance - lightRange.x) /\n"
" (lightRange.y - lightRange.x);\n" " (lightRange.y - lightRange.x);\n"
" }\n" " }\n"
" result += vec4(lightAttenuation * dotNormalLightDir * lightDiffuse, 0.0);\n" " result += diffuseTexel * vec4(lightAttenuation * dotNormalLightDir * lightDiffuse, 0.0);\n"
" float specular = pow( max(dot(reflect(-normalize(lightVector), fragmentNormal), normalize(-vertexPos)), 0.0), 60.0);\n" " float specular = pow( max(dot(reflect(-normalize(lightVector), fragmentNormal), normalize(-vertexPos)), 0.0), 60.0);\n"
" result += vec4(lightAttenuation * specular * vec3(1.0, 0.5, 0.5), 0.0);\n" " result += vec4(lightAttenuation * specular * vec3(1.0, 1.0, 1.0), 0.0);\n"
" }\n" " }\n"
"\n" "\n"
" l++;\n" " l++;\n"
@ -311,6 +312,7 @@ _prprogrambit prprogrambits[PR_BIT_COUNT] = {
"void main(void)\n" "void main(void)\n"
"{\n" "{\n"
" vec4 result = vec4(1.0, 1.0, 1.0, 1.0);\n" " vec4 result = vec4(1.0, 1.0, 1.0, 1.0);\n"
" vec4 diffuseTexel = vec4(1.0, 1.0, 1.0, 1.0);\n"
" int l = 0;\n" " int l = 0;\n"
"\n", "\n",
// frag_prog // frag_prog
@ -788,13 +790,46 @@ void polymer_setanimatesprites(animatespritesptr animatesprites,
void polymer_resetlights(void) void polymer_resetlights(void)
{ {
int32_t i;
_prsector *s;
_prwall *w;
i = 0;
while (i < numsectors)
{
s = prsectors[i];
s->floor.lightcount = 0;
s->ceil.lightcount = 0;
i++;
}
i = 0;
while (i < numwalls)
{
w = prwalls[i];
w->wall.lightcount = 0;
w->over.lightcount = 0;
w->mask.lightcount = 0;
i++;
}
lightcount = 0; lightcount = 0;
} }
void polymer_addlight(_prlight light) void polymer_addlight(_prlight light)
{ {
if (lightcount < PR_MAXLIGHTS) if (lightcount < PR_MAXLIGHTS)
prlights[lightcount++] = light; {
prlights[lightcount] = light;
polymer_culllight(lightcount);
lightcount++;
}
} }
// CORE // CORE
@ -1155,7 +1190,7 @@ static void polymer_drawplane(int16_t sectnum, int16_t wallnum, _prplane
bglNormal3f((float)(-plane->plane[0]), (float)(-plane->plane[1]), (float)(-plane->plane[2])); bglNormal3f((float)(-plane->plane[0]), (float)(-plane->plane[1]), (float)(-plane->plane[2]));
materialbits = polymer_bindmaterial(plane->material, prlights, lightcount); materialbits = polymer_bindmaterial(plane->material, plane->lights, plane->lightcount);
if (plane->vbo && (pr_vbos > 0)) if (plane->vbo && (pr_vbos > 0))
{ {
@ -1232,7 +1267,9 @@ static int32_t polymer_initsector(int16_t sectnum)
s->verts = calloc(sec->wallnum, sizeof(GLdouble) * 3); s->verts = calloc(sec->wallnum, sizeof(GLdouble) * 3);
s->floor.buffer = calloc(sec->wallnum, sizeof(GLfloat) * 5); s->floor.buffer = calloc(sec->wallnum, sizeof(GLfloat) * 5);
s->floor.vertcount = sec->wallnum;
s->ceil.buffer = calloc(sec->wallnum, sizeof(GLfloat) * 5); s->ceil.buffer = calloc(sec->wallnum, sizeof(GLfloat) * 5);
s->ceil.vertcount = sec->wallnum;
if ((s->verts == NULL) || (s->floor.buffer == NULL) || (s->ceil.buffer == NULL)) if ((s->verts == NULL) || (s->floor.buffer == NULL) || (s->ceil.buffer == NULL))
{ {
if (pr_verbosity >= 1) OSD_Printf("PR : Cannot initialize geometry of sector %i : malloc failed.\n", sectnum); if (pr_verbosity >= 1) OSD_Printf("PR : Cannot initialize geometry of sector %i : malloc failed.\n", sectnum);
@ -1260,8 +1297,7 @@ static int32_t polymer_initsector(int16_t sectnum)
return (1); return (1);
} }
static int32_t polymer_updatesector(int16_t sectnum) static int32_t polymer_updatesector(int16_t sectnum){
{
_prsector* s; _prsector* s;
sectortype *sec; sectortype *sec;
walltype *wal; walltype *wal;
@ -1618,8 +1654,10 @@ static int32_t polymer_initwall(int16_t wallnum)
return (0); return (0);
} }
if (w->mask.buffer == NULL) if (w->mask.buffer == NULL) {
w->mask.buffer = calloc(4, sizeof(GLfloat) * 5); w->mask.buffer = calloc(4, sizeof(GLfloat) * 5);
w->mask.vertcount = 4;
}
if (w->bigportal == NULL) if (w->bigportal == NULL)
w->bigportal = calloc(4, sizeof(GLfloat) * 3); w->bigportal = calloc(4, sizeof(GLfloat) * 3);
if (w->cap == NULL) if (w->cap == NULL)
@ -1687,8 +1725,10 @@ static void polymer_updatewall(int16_t wallnum)
nsec = NULL; nsec = NULL;
} }
if (w->wall.buffer == NULL) if (w->wall.buffer == NULL) {
w->wall.buffer = calloc(4, sizeof(GLfloat) * 5); w->wall.buffer = calloc(4, sizeof(GLfloat) * 5);
w->wall.vertcount = 4;
}
wallpicnum = wal->picnum; wallpicnum = wal->picnum;
if (picanm[wallpicnum]&192) wallpicnum += animateoffs(wallpicnum,wallnum+16384); if (picanm[wallpicnum]&192) wallpicnum += animateoffs(wallpicnum,wallnum+16384);
@ -1892,8 +1932,10 @@ static void polymer_updatewall(int16_t wallnum)
if ((overwall) || (wal->cstat & 16)) if ((overwall) || (wal->cstat & 16))
{ {
if (w->over.buffer == NULL) if (w->over.buffer == NULL) {
w->over.buffer = calloc(4, sizeof(GLfloat) * 5); w->over.buffer = calloc(4, sizeof(GLfloat) * 5);
w->over.vertcount = 4;
}
memcpy(w->over.buffer, &ns->ceil.buffer[(nnwallnum - nsec->wallptr) * 5], sizeof(GLfloat) * 3); memcpy(w->over.buffer, &ns->ceil.buffer[(nnwallnum - nsec->wallptr) * 5], sizeof(GLfloat) * 3);
memcpy(&w->over.buffer[5], &ns->ceil.buffer[(nwallnum - nsec->wallptr) * 5], sizeof(GLfloat) * 3); memcpy(&w->over.buffer[5], &ns->ceil.buffer[(nwallnum - nsec->wallptr) * 5], sizeof(GLfloat) * 3);
@ -2505,7 +2547,7 @@ static void polymer_drawmdsprite(spritetype *tspr)
mdspritematerial.nextframedatastride = sizeof(md3xyzn_t); mdspritematerial.nextframedatastride = sizeof(md3xyzn_t);
} }
materialbits = polymer_bindmaterial(mdspritematerial, prlights, lightcount); materialbits = polymer_bindmaterial(mdspritematerial, NULL, 0);
bglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m->indices[surfi]); bglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m->indices[surfi]);
bglDrawElements(GL_TRIANGLES, s->numtris * 3, GL_UNSIGNED_INT, 0); bglDrawElements(GL_TRIANGLES, s->numtris * 3, GL_UNSIGNED_INT, 0);
@ -2526,7 +2568,7 @@ static void polymer_drawmdsprite(spritetype *tspr)
mdspritematerial.nextframedatastride = sizeof(md3xyzn_t); mdspritematerial.nextframedatastride = sizeof(md3xyzn_t);
} }
materialbits = polymer_bindmaterial(mdspritematerial, prlights, lightcount); materialbits = polymer_bindmaterial(mdspritematerial, NULL, 0);
bglDrawElements(GL_TRIANGLES, s->numtris * 3, GL_UNSIGNED_INT, s->tris); bglDrawElements(GL_TRIANGLES, s->numtris * 3, GL_UNSIGNED_INT, s->tris);
@ -2671,7 +2713,7 @@ static void polymer_getbuildmaterial(_prmaterial* material, int16_t tile
} }
} }
static int32_t polymer_bindmaterial(_prmaterial material, _prlight* lights, int lightcount) static int32_t polymer_bindmaterial(_prmaterial material, char* lights, int lightcount)
{ {
int32_t programbits; int32_t programbits;
int32_t texunit; int32_t texunit;
@ -2779,18 +2821,18 @@ static int32_t polymer_bindmaterial(_prmaterial material, _prlight* lights,
while (i < ((glinfo.sm4) ? lightcount : PR_SM3_MAXLIGHTS)) while (i < ((glinfo.sm4) ? lightcount : PR_SM3_MAXLIGHTS))
{ {
inpos[0] = lights[i].y; inpos[0] = prlights[lights[i]].y;
inpos[1] = -lights[i].z / 16.0f; inpos[1] = -prlights[lights[i]].z / 16.0f;
inpos[2] = -lights[i].x; inpos[2] = -prlights[lights[i]].x;
polymer_transformlight(inpos, pos, rootmodelviewmatrix); polymer_transformlight(inpos, pos, rootmodelviewmatrix);
range[0] = lights[i].faderange / 1000.0f; range[0] = prlights[lights[i]].faderange / 1000.0f;
range[1] = lights[i].range / 1000.0f; range[1] = prlights[lights[i]].range / 1000.0f;
color[0] = lights[i].color[0] / 255.0f; color[0] = prlights[lights[i]].color[0] / 255.0f;
color[1] = lights[i].color[1] / 255.0f; color[1] = prlights[lights[i]].color[1] / 255.0f;
color[2] = lights[i].color[2] / 255.0f; color[2] = prlights[lights[i]].color[2] / 255.0f;
bglLightfv(GL_LIGHT0 + i, GL_AMBIENT, pos); bglLightfv(GL_LIGHT0 + i, GL_AMBIENT, pos);
bglLightfv(GL_LIGHT0 + i, GL_DIFFUSE, color); bglLightfv(GL_LIGHT0 + i, GL_DIFFUSE, color);
@ -2965,4 +3007,100 @@ static void polymer_transformlight(float* inpos, float* pos, float* matr
+ matrix[14]; + matrix[14];
} }
static int32_t polymer_planeinlight(_prplane* plane, _prlight* light)
{
float lightpos[3];
int i, j, k, l;
lightpos[0] = light->y;
lightpos[1] = -light->z / 16.0f;
lightpos[2] = -light->x;
i = 0;
while (i < 3)
{
j = k = l = 0;
while (j < plane->vertcount)
{
if (plane->buffer[(j * 5) + i] > (lightpos[i] + light->range)) k++;
if (plane->buffer[(j * 5) + i] < (lightpos[i] - light->range)) l++;
j++;
}
if ((k == plane->vertcount) || (l == plane->vertcount))
return 0;
i++;
}
return 1;
}
static void polymer_culllight(char lightindex)
{
_prlight* light;
int32_t front;
int32_t back;
int32_t i;
int16_t cullingstate[MAXSECTORS];
int16_t sectorqueue[MAXSECTORS];
_prsector *s;
_prwall *w;
sectortype *sec;
light = &prlights[lightindex];
front = 0;
back = 1;
memset(cullingstate, 0, sizeof(int16_t) * MAXSECTORS);
cullingstate[light->sector] = 1;
sectorqueue[0] = light->sector;
while (front != back)
{
s = prsectors[sectorqueue[front]];
sec = &sector[sectorqueue[front]];
if (polymer_planeinlight(&s->floor, light)) {
s->floor.lights[s->floor.lightcount] = lightindex;
s->floor.lightcount++;
}
if (polymer_planeinlight(&s->ceil, light)) {
s->ceil.lights[s->floor.lightcount] = lightindex;
s->ceil.lightcount++;
}
i = 0;
while (i < sec->wallnum)
{
w = prwalls[sec->wallptr + i];
if (polymer_planeinlight(&w->wall, light)) {
w->wall.lights[w->wall.lightcount] = lightindex;
w->wall.lightcount++;
}
if (polymer_planeinlight(&w->over, light)) {
w->over.lights[w->over.lightcount] = lightindex;
w->over.lightcount++;
}
if (polymer_planeinlight(&w->mask, light)) {
w->mask.lights[w->mask.lightcount] = lightindex;
w->mask.lightcount++;
if ((wall[sec->wallptr + i].nextsector != -1) &&
(!cullingstate[wall[sec->wallptr + i].nextsector])) {
cullingstate[wall[sec->wallptr + i].nextsector] = 1;
sectorqueue[back] = wall[sec->wallptr + i].nextsector;
back++;
}
}
i++;
}
front++;
}
}
#endif #endif