From 61f6f92291491fe35ecd38747e37e6d569fec28d Mon Sep 17 00:00:00 2001 From: havoc Date: Wed, 18 Feb 2004 14:06:38 +0000 Subject: [PATCH] cubemap filters for rtlights are now supported git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@3905 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_models.c | 10 ++-- gl_rmain.c | 9 +-- gl_rsurf.c | 16 ++--- image.c | 32 ++++++++++ image.h | 4 ++ model_alias.c | 4 +- model_brush.c | 4 +- model_shared.h | 2 +- r_shadow.c | 160 ++++++++++++++++++++++++++++++++++++++++--------- todo | 5 +- 10 files changed, 195 insertions(+), 51 deletions(-) diff --git a/gl_models.c b/gl_models.c index 59f3d85e..1f6fc96f 100644 --- a/gl_models.c +++ b/gl_models.c @@ -328,7 +328,7 @@ void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightor } } -void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz) +void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap) { int c, meshnum, layernum; float fog, ifog, lightcolor2[3]; @@ -383,7 +383,7 @@ void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v if (layer->flags & ALIASLAYER_SPECULAR) { c_alias_polys += mesh->num_triangles; - R_Shadow_SpecularLighting(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, aliasvert_vertex3f, aliasvert_svector3f, aliasvert_tvector3f, aliasvert_normal3f, mesh->data_texcoord2f, relativelightorigin, relativeeyeorigin, lightradius, lightcolor2, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, layer->texture, layer->nmap, NULL); + R_Shadow_SpecularLighting(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, aliasvert_vertex3f, aliasvert_svector3f, aliasvert_tvector3f, aliasvert_normal3f, mesh->data_texcoord2f, relativelightorigin, relativeeyeorigin, lightradius, lightcolor2, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, layer->texture, layer->nmap, lightcubemap); } else if (layer->flags & ALIASLAYER_DIFFUSE) { @@ -412,7 +412,7 @@ void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v lightcolor2[2] *= bcolor[2] * (1.0f / 255.0f); } c_alias_polys += mesh->num_triangles; - R_Shadow_DiffuseLighting(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, aliasvert_vertex3f, aliasvert_svector3f, aliasvert_tvector3f, aliasvert_normal3f, mesh->data_texcoord2f, relativelightorigin, lightradius, lightcolor2, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, layer->texture, layer->nmap, NULL); + R_Shadow_DiffuseLighting(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, aliasvert_vertex3f, aliasvert_svector3f, aliasvert_tvector3f, aliasvert_normal3f, mesh->data_texcoord2f, relativelightorigin, lightradius, lightcolor2, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, layer->texture, layer->nmap, lightcubemap); } } } @@ -802,12 +802,12 @@ void R_Model_Zymotic_Draw(entity_render_t *ent) } } -void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor) +void R_Model_Zymotic_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius) { // FIXME } -void R_Model_Zymotic_DrawOntoLight(entity_render_t *ent) +void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap) { // FIXME } diff --git a/gl_rmain.c b/gl_rmain.c index 35e97598..c0d23b14 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -605,6 +605,7 @@ void R_ShadowVolumeLighting(int visiblevolumes) R_Shadow_Stage_LightWithoutShadows(); // calculate world to filter matrix + //Matrix4x4_CreateFromQuakeEntity(&matrix, wl->origin[0], wl->origin[1], wl->origin[2], wl->angles[0] + cl.time * 12, wl->angles[1] + cl.time * 45, wl->angles[2], lightradius); Matrix4x4_CreateFromQuakeEntity(&matrix, wl->origin[0], wl->origin[1], wl->origin[2], wl->angles[0], wl->angles[1], wl->angles[2], lightradius); Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix); // calculate world to attenuationxyz/xy matrix @@ -628,7 +629,7 @@ void R_ShadowVolumeLighting(int visiblevolumes) if (r_shadow_staticworldlights.integer) R_Shadow_DrawStaticWorldLight_Light(wl, &ent->matrix, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz); else - ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz); + ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, wl->cubemap); } if (r_drawentities.integer) { @@ -644,7 +645,7 @@ void R_ShadowVolumeLighting(int visiblevolumes) Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix); Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix); Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix); - ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz); + ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, wl->cubemap); } } } @@ -713,7 +714,7 @@ void R_ShadowVolumeLighting(int visiblevolumes) Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix); Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix); Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix); - ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz); + ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, NULL); } if (r_drawentities.integer) { @@ -729,7 +730,7 @@ void R_ShadowVolumeLighting(int visiblevolumes) Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix); Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix); Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix); - ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz); + ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, NULL); } } } diff --git a/gl_rsurf.c b/gl_rsurf.c index 13c97bed..253444ea 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -1851,7 +1851,7 @@ void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelighto } } -void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz) +void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap) { int surfnum; msurface_t *surf; @@ -1879,8 +1879,8 @@ void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v t = surf->texinfo->texture->currentframe; if (t->rendertype == SURFRENDER_OPAQUE && t->flags & SURF_SHADOWLIGHT) { - R_Shadow_DiffuseLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, NULL); - R_Shadow_SpecularLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.gloss, t->skin.nmap, NULL); + R_Shadow_DiffuseLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, lightcubemap); + R_Shadow_SpecularLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.gloss, t->skin.nmap, lightcubemap); } } } @@ -2395,15 +2395,15 @@ void R_Q3BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, } } -void R_Q3BSP_DrawFaceLight(entity_render_t *ent, q3mface_t *face, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz) +void R_Q3BSP_DrawFaceLight(entity_render_t *ent, q3mface_t *face, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap) { if ((face->texture->surfaceflags & Q3SURFACEFLAG_NODRAW) || !face->num_triangles) return; - R_Shadow_DiffuseLighting(face->num_vertices, face->num_triangles, face->data_element3i, face->data_vertex3f, face->data_svector3f, face->data_tvector3f, face->data_normal3f, face->data_texcoordtexture2f, relativelightorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, face->texture->skin.base, face->texture->skin.nmap, NULL); - R_Shadow_SpecularLighting(face->num_vertices, face->num_triangles, face->data_element3i, face->data_vertex3f, face->data_svector3f, face->data_tvector3f, face->data_normal3f, face->data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, face->texture->skin.gloss, face->texture->skin.nmap, NULL); + R_Shadow_DiffuseLighting(face->num_vertices, face->num_triangles, face->data_element3i, face->data_vertex3f, face->data_svector3f, face->data_tvector3f, face->data_normal3f, face->data_texcoordtexture2f, relativelightorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, face->texture->skin.base, face->texture->skin.nmap, lightcubemap); + R_Shadow_SpecularLighting(face->num_vertices, face->num_triangles, face->data_element3i, face->data_vertex3f, face->data_svector3f, face->data_tvector3f, face->data_normal3f, face->data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, face->texture->skin.gloss, face->texture->skin.nmap, lightcubemap); } -void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz) +void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap) { int i; q3mface_t *face; @@ -2427,7 +2427,7 @@ void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t //else for (i = 0, face = model->brushq3.data_thismodel->firstface;i < model->brushq3.data_thismodel->numfaces;i++, face++) if ((ent != &cl_entities[0].render || face->visframe == r_framecount) && BoxesOverlap(lightmins, lightmaxs, face->mins, face->maxs)) - R_Q3BSP_DrawFaceLight(ent, face, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz); + R_Q3BSP_DrawFaceLight(ent, face, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, lightcubemap); } } diff --git a/image.c b/image.c index 27fc7941..b46e3f4f 100644 --- a/image.c +++ b/image.c @@ -7,6 +7,38 @@ int image_width; int image_height; +void Image_CopyMux(qbyte *outpixels, const qbyte *inpixels, int width, int height, int flipx, int flipy, int flipdiagonal, int numincomponents, int numoutcomponents, int *inputcomponentindices) +{ + int c, x, y; + const qbyte *in, *inrow, *incolumn; + if (flipdiagonal) + { + for (y = 0;y < height;y++) + { + incolumn = inpixels + (flipx ? width - 1 - y : y) * numincomponents; + for (x = 0;x < width;x++) + { + in = incolumn + (flipy ? height - 1 - x : x) * width * numincomponents; + for (c = 0;c < numoutcomponents;c++) + *outpixels++ = in[inputcomponentindices[c]]; + } + } + } + else + { + for (y = 0;y < height;y++) + { + inrow = inpixels + (flipy ? height - 1 - y : y) * width * numincomponents; + for (x = 0;x < width;x++) + { + in = inrow + (flipx ? width - 1 - x : x) * numincomponents; + for (c = 0;c < numoutcomponents;c++) + *outpixels++ = in[inputcomponentindices[c]]; + } + } + } +} + void Image_GammaRemapRGB(const qbyte *in, qbyte *out, int pixels, const qbyte *gammar, const qbyte *gammag, const qbyte *gammab) { while (pixels--) diff --git a/image.h b/image.h index 71a5535b..f85a8060 100644 --- a/image.h +++ b/image.h @@ -2,6 +2,10 @@ #ifndef IMAGE_H #define IMAGE_H +// swizzle components (even converting number of components) and flip images +// (warning: input must be different than output due to non-linear read/write) +void Image_CopyMux(qbyte *outpixels, const qbyte *inpixels, int width, int height, int flipx, int flipy, int flipdiagonal, int numincomponents, int numoutcomponents, int *inputcomponentindices); + // applies gamma correction to RGB pixels, in can be the same as out void Image_GammaRemapRGB(const qbyte *in, qbyte *out, int pixels, const qbyte *gammar, const qbyte *gammag, const qbyte *gammab); diff --git a/model_alias.c b/model_alias.c index d0a9c3ca..d91ef816 100644 --- a/model_alias.c +++ b/model_alias.c @@ -312,7 +312,7 @@ void Mod_BuildAliasSkinsFromSkinFiles(aliasskin_t *skin, skinfile_t *skinfile, c #define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)\n", loadmodel->name, VALUE, MIN, MAX); extern void R_Model_Alias_Draw(entity_render_t *ent); extern void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius); -extern void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz); +extern void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap); void Mod_IDP0_Load(model_t *mod, void *buffer) { int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts; @@ -970,7 +970,7 @@ void Mod_IDP3_Load(model_t *mod, void *buffer) extern void R_Model_Zymotic_DrawSky(entity_render_t *ent); extern void R_Model_Zymotic_Draw(entity_render_t *ent); extern void R_Model_Zymotic_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius); -extern void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz); +extern void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap); void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer) { zymtype1header_t *pinmodel, *pheader; diff --git a/model_brush.c b/model_brush.c index 8acc3cea..22094635 100644 --- a/model_brush.c +++ b/model_brush.c @@ -2819,7 +2819,7 @@ static void Mod_Q1BSP_RoundUpToHullSize(model_t *cmodel, const vec3_t inmins, co extern void R_Model_Brush_DrawSky(entity_render_t *ent); extern void R_Model_Brush_Draw(entity_render_t *ent); extern void R_Model_Brush_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius); -extern void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz); +extern void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap); void Mod_Q1BSP_Load(model_t *mod, void *buffer) { int i, j, k; @@ -5259,7 +5259,7 @@ static int Mod_Q3BSP_NativeContentsFromSuperContents(model_t *model, int superco extern void R_Q3BSP_DrawSky(struct entity_render_s *ent); extern void R_Q3BSP_Draw(struct entity_render_s *ent); extern void R_Q3BSP_DrawShadowVolume(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius); -extern void R_Q3BSP_DrawLight(struct entity_render_s *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz); +extern void R_Q3BSP_DrawLight(struct entity_render_s *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap); void Mod_Q3BSP_Load(model_t *mod, void *buffer) { int i, j; diff --git a/model_shared.h b/model_shared.h index 00a11b28..0aafccca 100644 --- a/model_shared.h +++ b/model_shared.h @@ -576,7 +576,7 @@ typedef struct model_s // draw a shadow volume for the model based on light source void(*DrawShadowVolume)(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius); // draw the lighting on a model (through stencil) - void(*DrawLight)(struct entity_render_s *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz); + void(*DrawLight)(struct entity_render_s *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap); // trace a box against this model void (*TraceBox)(struct model_s *model, int frame, struct trace_s *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask); // fields belonging to each type of model diff --git a/r_shadow.c b/r_shadow.c index e92bafc6..bd0f1c0b 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -115,6 +115,7 @@ the (currently upcoming) game Doom3. #include "r_shadow.h" #include "cl_collision.h" #include "portals.h" +#include "image.h" extern void R_Shadow_EditLights_Init(void); @@ -147,6 +148,9 @@ rtexture_t *r_shadow_blankbumptexture; rtexture_t *r_shadow_blankglosstexture; rtexture_t *r_shadow_blankwhitetexture; +// used only for light filters (cubemaps) +rtexturepool_t *r_shadow_filters_texturepool; + cvar_t r_shadow_realtime_world_lightmaps = {0, "r_shadow_realtime_world_lightmaps", "0"}; cvar_t r_shadow_lightattenuationpower = {0, "r_shadow_lightattenuationpower", "0.5"}; cvar_t r_shadow_lightattenuationscale = {0, "r_shadow_lightattenuationscale", "1"}; @@ -201,6 +205,7 @@ void r_shadow_start(void) r_shadow_blankglosstexture = NULL; r_shadow_blankwhitetexture = NULL; r_shadow_texturepool = NULL; + r_shadow_filters_texturepool = NULL; R_Shadow_ClearWorldLights(); r_shadow_reloadlights = true; } @@ -216,6 +221,7 @@ void r_shadow_shutdown(void) r_shadow_blankglosstexture = NULL; r_shadow_blankwhitetexture = NULL; R_FreeTexturePool(&r_shadow_texturepool); + R_FreeTexturePool(&r_shadow_filters_texturepool); maxshadowelements = 0; shadowelements = NULL; maxvertexupdate = 0; @@ -1291,14 +1297,16 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(basetexture); - m.texcubemap[1] = R_GetTexture(lightcubemap); m.pointer_texcoord[0] = texcoord2f; - m.pointer_texcoord[1] = lightcubemap ? varray_texcoord3f[1] : NULL; + if (lightcubemap) + { + m.texcubemap[1] = R_GetTexture(lightcubemap); + m.pointer_texcoord[1] = varray_texcoord3f[1]; + R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); + } R_Mesh_State_Texture(&m); qglColorMask(1,1,1,0); GL_BlendFunc(GL_DST_ALPHA, GL_ONE); - if (lightcubemap) - R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); VectorScale(lightcolor, r_shadow_lightintensityscale.value, color2); for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) { @@ -1341,14 +1349,16 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(basetexture); - m.texcubemap[1] = R_GetTexture(lightcubemap); m.pointer_texcoord[0] = texcoord2f; - m.pointer_texcoord[1] = lightcubemap ? varray_texcoord3f[1] : NULL; + if (lightcubemap) + { + m.texcubemap[1] = R_GetTexture(lightcubemap); + m.pointer_texcoord[1] = varray_texcoord3f[1]; + R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); + } R_Mesh_State_Texture(&m); qglColorMask(1,1,1,0); GL_BlendFunc(GL_DST_ALPHA, GL_ONE); - if (lightcubemap) - R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); VectorScale(lightcolor, r_shadow_lightintensityscale.value, color2); for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) { @@ -1426,14 +1436,16 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(basetexture); - m.texcubemap[1] = R_GetTexture(lightcubemap); m.pointer_texcoord[0] = texcoord2f; - m.pointer_texcoord[1] = lightcubemap ? varray_texcoord3f[1] : NULL; + if (lightcubemap) + { + m.texcubemap[1] = R_GetTexture(lightcubemap); + m.pointer_texcoord[1] = varray_texcoord3f[1]; + R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); + } R_Mesh_State_Texture(&m); qglColorMask(1,1,1,0); GL_BlendFunc(GL_DST_ALPHA, GL_ONE); - if (lightcubemap) - R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); VectorScale(lightcolor, r_shadow_lightintensityscale.value, color2); for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) { @@ -1479,14 +1491,16 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(basetexture); - m.texcubemap[1] = R_GetTexture(lightcubemap); m.pointer_texcoord[0] = texcoord2f; - m.pointer_texcoord[1] = lightcubemap ? varray_texcoord3f[1] : NULL; + if (lightcubemap) + { + m.texcubemap[1] = R_GetTexture(lightcubemap); + m.pointer_texcoord[1] = varray_texcoord3f[1]; + R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); + } R_Mesh_State_Texture(&m); qglColorMask(1,1,1,0); GL_BlendFunc(GL_DST_ALPHA, GL_ONE); - if (lightcubemap) - R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); VectorScale(lightcolor, r_shadow_lightintensityscale.value, color2); for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) { @@ -1597,14 +1611,16 @@ void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elemen memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(glosstexture); - m.texcubemap[1] = R_GetTexture(lightcubemap); + if (lightcubemap) + { + m.texcubemap[1] = R_GetTexture(lightcubemap); + m.pointer_texcoord[1] = varray_texcoord3f[1]; + R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); + } m.pointer_texcoord[0] = texcoord2f; - m.pointer_texcoord[1] = lightcubemap ? varray_texcoord3f[1] : NULL; R_Mesh_State_Texture(&m); qglColorMask(1,1,1,0); GL_BlendFunc(GL_DST_ALPHA, GL_ONE); - if (lightcubemap) - R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); VectorScale(lightcolor, colorscale, color2); for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) { @@ -1719,14 +1735,16 @@ void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elemen memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(glosstexture); - m.texcubemap[1] = R_GetTexture(lightcubemap); + if (lightcubemap) + { + m.texcubemap[1] = R_GetTexture(lightcubemap); + m.pointer_texcoord[1] = varray_texcoord3f[1]; + R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); + } m.pointer_texcoord[0] = texcoord2f; - m.pointer_texcoord[1] = lightcubemap ? varray_texcoord3f[1] : NULL; R_Mesh_State_Texture(&m); qglColorMask(1,1,1,0); GL_BlendFunc(GL_DST_ALPHA, GL_ONE); - if (lightcubemap) - R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); VectorScale(lightcolor, colorscale, color2); for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) { @@ -1805,8 +1823,8 @@ void R_Shadow_DrawStaticWorldLight_Light(worldlight_t *light, matrix4x4_t *matri } for (mesh = light->meshchain_light;mesh;mesh = mesh->next) { - R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoord2f, relativelightorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, mesh->map_diffuse, mesh->map_normal, NULL); - R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoord2f, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, mesh->map_specular, mesh->map_normal, NULL); + R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoord2f, relativelightorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, mesh->map_diffuse, mesh->map_normal, light->cubemap); + R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoord2f, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, mesh->map_specular, mesh->map_normal, light->cubemap); } } @@ -1824,6 +1842,93 @@ vec3_t r_editlights_cursorlocation; static int lightpvsbytes; static qbyte lightpvs[(MAX_MAP_LEAFS + 7)/ 8]; +//static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"}; +typedef struct suffixinfo +{ + char *suffix; + int flipx, flipy, flipdiagonal; +} +suffixinfo_t; +static suffixinfo_t suffix[3][6] = +{ + { + {"posx", false, false, false}, + {"negx", false, false, false}, + {"posy", false, false, false}, + {"negy", false, false, false}, + {"posz", false, false, false}, + {"negz", false, false, false} + }, + { + {"px", false, false, false}, + {"nx", false, false, false}, + {"py", false, false, false}, + {"ny", false, false, false}, + {"pz", false, false, false}, + {"nz", false, false, false} + }, + { + {"ft", true, false, true}, + {"bk", false, true, true}, + {"lf", true, true, false}, + {"rt", false, false, false}, + {"up", false, false, false}, + {"dn", false, false, false} + } +}; + +static int componentorder[4] = {0, 1, 2, 3}; + +rtexture_t *R_Shadow_LoadCubemap(const char *basename) +{ + int i, j, cubemapsize; + qbyte *cubemappixels, *image_rgba; + rtexture_t *cubemaptexture; + char name[256]; + // must start 0 so the first loadimagepixels has no requested width/height + cubemapsize = 0; + cubemappixels = NULL; + cubemaptexture = NULL; + for (j = 0;j < 3 && !cubemappixels;j++) + { + for (i = 0;i < 6;i++) + { + snprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix); + if ((image_rgba = loadimagepixels(name, true, cubemapsize, cubemapsize))) + { + if (image_width == image_height) + { + if (!cubemappixels && image_width >= 1) + { + cubemapsize = image_width; + // note this clears to black, so unavailable sizes are black + cubemappixels = Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4); + } + if (cubemappixels) + Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_rgba, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder); + } + else + Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height); + Mem_Free(image_rgba); + } + } + } + if (cubemappixels) + { + if (!r_shadow_filters_texturepool) + r_shadow_filters_texturepool = R_AllocTexturePool(); + cubemaptexture = R_LoadTextureCubeMap(r_shadow_filters_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_RGBA, TEXF_PRECACHE, NULL); + Mem_Free(cubemappixels); + } + else + Con_Printf("Failed to load Cubemap \"%s\"\n", basename); + return cubemaptexture; +} + +void R_Shadow_FreeCubemaps(void) +{ + R_FreeTexturePool(&r_shadow_filters_texturepool); +} void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style, const char *cubemapname, int castshadow) { @@ -1863,7 +1968,7 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style { e->cubemapname = Mem_Alloc(r_shadow_mempool, strlen(cubemapname) + 1); strcpy(e->cubemapname, cubemapname); - // FIXME: add cubemap loading (and don't load a cubemap twice) + e->cubemap = R_Shadow_LoadCubemap(e->cubemapname); } // FIXME: rewrite this to store ALL geometry into a cache in the light if (e->castshadows) @@ -2066,6 +2171,7 @@ void R_Shadow_ClearWorldLights(void) while (r_shadow_worldlightchain) R_Shadow_FreeWorldLight(r_shadow_worldlightchain); r_shadow_selectedlight = NULL; + R_Shadow_FreeCubemaps(); } void R_Shadow_SelectLight(worldlight_t *light) diff --git a/todo b/todo index 0850de8a..fd77b166 100644 --- a/todo +++ b/todo @@ -35,8 +35,9 @@ -n darkplaces: server is starting before the "port" cvar is set by commandline and scripts? (yummyluv) -n darkplaces: typing ip in join game menu should show 'trying' and 'no response' after a while, or 'no network' if networking is not initialized (yummyluv) -n dpmod: make grapple off-hand (joe hill) -0 darkplaces: add r_shadow_realtime_world_lightmaps cvar to control lightmap brightness (Mitchell) -0 darkplaces: add gl_lightmaps cvar to disable texturing except lightmaps for testing (Vic) +-n darkplaces: implement cubemap support on rtlights (romi, Vermeulen, Mitchell) +d darkplaces: add r_shadow_realtime_world_lightmaps cvar to control lightmap brightness (Mitchell) +-n darkplaces: add gl_lightmaps cvar to disable texturing except lightmaps for testing (Vic) 0 hmap2: release hmap2 (Vic, Supajoe) 4 darkplaces: add capability for qc entities to act as bones in a model, and send them as compressed origins in the parent entity's updates, with perhaps a limit of 16 bones, this would allow some simple serverside ragdoll (Mitchell) 4 darkplaces: add .psk/.psa (ut2003/ut2004) model support (Mitchell) -- 2.39.2