" myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
" //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
" //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
-" color = mix(myhalf4(texture2D(Texture_SecondaryColor, TexCoord)), color, terrainblend);\n"
+" color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord)), color.rgb, terrainblend);\n"
+" color.a = 1.0;\n"
" //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
"#endif\n"
"\n"
" myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
"# endif\n"
"# else\n"
-" myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
+" myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
"# ifdef USESPECULAR\n"
" myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
"# endif\n"
" myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
"# endif\n"
"# ifdef USESPECULAR\n"
-" myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
-"\n"
" // calculate directional shading\n"
-" color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * glosscolor);\n"
+" color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower)) * glosscolor);\n"
"# else\n"
"# ifdef USEDIFFUSE\n"
" // calculate directional shading\n"
"# ifdef USESPECULAR\n"
" // calculate directional shading\n"
" color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
-" myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
-" color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
+" color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
"# else\n"
"# ifdef USEDIFFUSE\n"
"\n"
" // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
"\n"
" // get the light normal\n"
-" myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5);\n"
-" myhalf3 diffusenormal = normalize(myhalf3(dot(diffusenormal_modelspace, myhalf3(VectorS)), dot(diffusenormal_modelspace, myhalf3(VectorT)), dot(diffusenormal_modelspace, myhalf3(VectorR))));\n"
+" myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
+" myhalf3 diffusenormal;\n"
+" diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
+" diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
+" diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
" // calculate directional shading\n"
" myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
"# ifdef USESPECULAR\n"
-" myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
-" tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
+" tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
"# endif\n"
"\n"
" // apply lightmap color\n"
" // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
"\n"
" // get the light normal\n"
-" myhalf3 diffusenormal = normalize(myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5));\n"
+" myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
" // calculate directional shading\n"
" myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
"# ifdef USESPECULAR\n"
-" myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
-" tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
+" tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
"# endif\n"
"\n"
" // apply lightmap color\n"
{
int i;
- qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
+ qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
if(!file)
{
Con_Printf("failed to write to glsl/default.glsl\n");
return item;
}
-skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
+skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
{
// FIXME: it should be possible to disable loading various layers using
// cvars, to prevent wasted loading time and memory usage if the user does
int basepixels_height;
skinframe_t *skinframe;
+ *has_alpha = false;
+
if (cls.state == ca_dedicated)
return NULL;
if (j < basepixels_width * basepixels_height * 4)
{
// has transparent pixels
+ *has_alpha = true;
pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
for (j = 0;j < image_width * image_height * 4;j += 4)
{
{
if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
{
- skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
+ skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
Mem_Free(pixels);
pixels = NULL;
}
{
pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
- skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
+ skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
Mem_Free(pixels);
Mem_Free(bumppixels);
}
{
pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
- skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
+ skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
Mem_Free(pixels);
}
}
return skinframe;
}
+skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
+{
+ qboolean has_alpha;
+ return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
+}
+
static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force)
{
int i;
if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
{
// worldmodel can check visibility
+ memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
for (i = 0;i < r_refdef.scene.numentities;i++)
{
ent = r_refdef.scene.entities[i];
- r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs)) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs));
-
+ if (!(ent->flags & renderimask))
+ if (!R_CullBox(ent->mins, ent->maxs) || (ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
+ if ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
+ r_refdef.viewcache.entityvisible[i] = true;
}
if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
{
}
// update currentskinframe to be a qw skin or animation frame
- if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
+ if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[i].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl"))
{
if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
{
}
extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
+int r_maxsurfacelist = 0;
+msurface_t **r_surfacelist = NULL;
void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
{
int i, j, endj, f, flagsmask;
- msurface_t *surface;
texture_t *t;
dp_model_t *model = r_refdef.scene.worldmodel;
- const int maxsurfacelist = 1024;
+ msurface_t *surfaces;
+ unsigned char *update;
int numsurfacelist = 0;
- msurface_t *surfacelist[1024];
if (model == NULL)
return;
+ if (r_maxsurfacelist < model->num_surfaces)
+ {
+ r_maxsurfacelist = model->num_surfaces;
+ if (r_surfacelist)
+ Mem_Free(r_surfacelist);
+ r_surfacelist = Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
+ }
+
RSurf_ActiveWorldEntity();
+ surfaces = model->data_surfaces;
+ update = model->brushq1.lightmapupdateflags;
+
// update light styles on this submodel
if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
{
{
if (style->value != r_refdef.scene.lightstylevalue[style->style])
{
- msurface_t *surfaces = model->data_surfaces;
int *list = style->surfacelist;
style->value = r_refdef.scene.lightstylevalue[style->style];
for (j = 0;j < style->numsurfaces;j++)
- surfaces[list[j]].cached_dlight = true;
+ update[list[j]] = true;
}
}
}
rsurface.texture = NULL;
rsurface.rtlight = NULL;
numsurfacelist = 0;
+ // add visible surfaces to draw list
j = model->firstmodelsurface;
endj = j + model->nummodelsurfaces;
- while (j < endj)
+ if (update)
{
- // quickly skip over non-visible surfaces
- for (;j < endj && !r_refdef.viewcache.world_surfacevisible[j];j++)
- ;
- // quickly iterate over visible surfaces
- for (;j < endj && r_refdef.viewcache.world_surfacevisible[j];j++)
+ for (;j < endj;j++)
{
- // process this surface
- surface = model->data_surfaces + j;
- // if this surface fits the criteria, add it to the list
- if (surface->num_triangles)
+ if (r_refdef.viewcache.world_surfacevisible[j])
{
- // if lightmap parameters changed, rebuild lightmap texture
- if (surface->cached_dlight)
- R_BuildLightMap(r_refdef.scene.worldentity, surface);
- // add face to draw list
- surfacelist[numsurfacelist++] = surface;
- r_refdef.stats.world_triangles += surface->num_triangles;
- if (numsurfacelist >= maxsurfacelist)
- {
- r_refdef.stats.world_surfaces += numsurfacelist;
- R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
- numsurfacelist = 0;
- }
+ r_surfacelist[numsurfacelist++] = surfaces + j;
+ // update lightmap if needed
+ if (update[j])
+ R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
}
}
}
- r_refdef.stats.world_surfaces += numsurfacelist;
- if (numsurfacelist)
- R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
+ else
+ for (;j < endj;j++)
+ if (r_refdef.viewcache.world_surfacevisible[j])
+ r_surfacelist[numsurfacelist++] = surfaces + j;
+ // don't do anything if there were no surfaces
+ if (!numsurfacelist)
+ return;
+ R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
GL_AlphaTest(false);
+
+ // add to stats if desired
+ if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes)
+ {
+ r_refdef.stats.world_surfaces += numsurfacelist;
+ for (j = 0;j < numsurfacelist;j++)
+ r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
+ }
}
void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
{
- int i, j, f, flagsmask;
- msurface_t *surface, *endsurface;
+ int i, j, endj, f, flagsmask;
texture_t *t;
dp_model_t *model = ent->model;
- const int maxsurfacelist = 1024;
+ msurface_t *surfaces;
+ unsigned char *update;
int numsurfacelist = 0;
- msurface_t *surfacelist[1024];
if (model == NULL)
return;
+ if (r_maxsurfacelist < model->num_surfaces)
+ {
+ r_maxsurfacelist = model->num_surfaces;
+ if (r_surfacelist)
+ Mem_Free(r_surfacelist);
+ r_surfacelist = Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
+ }
+
// if the model is static it doesn't matter what value we give for
// wantnormals and wanttangents, so this logic uses only rules applicable
// to a model, knowing that they are meaningless otherwise
else
RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
+ surfaces = model->data_surfaces;
+ update = model->brushq1.lightmapupdateflags;
+
// update light styles
if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
{
{
if (style->value != r_refdef.scene.lightstylevalue[style->style])
{
- msurface_t *surfaces = model->data_surfaces;
int *list = style->surfacelist;
style->value = r_refdef.scene.lightstylevalue[style->style];
for (j = 0;j < style->numsurfaces;j++)
- surfaces[list[j]].cached_dlight = true;
+ update[list[j]] = true;
}
}
}
rsurface.texture = NULL;
rsurface.rtlight = NULL;
numsurfacelist = 0;
- surface = model->data_surfaces + model->firstmodelsurface;
- endsurface = surface + model->nummodelsurfaces;
- for (;surface < endsurface;surface++)
+ // add visible surfaces to draw list
+ j = model->firstmodelsurface;
+ endj = j + model->nummodelsurfaces;
+ for (;j < endj;j++)
+ r_surfacelist[numsurfacelist++] = surfaces + j;
+ // don't do anything if there were no surfaces
+ if (!numsurfacelist)
+ return;
+ // update lightmaps if needed
+ if (update)
+ for (j = model->firstmodelsurface;j < endj;j++)
+ if (update[j])
+ R_BuildLightMap(ent, surfaces + j);
+ R_QueueSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
+ GL_AlphaTest(false);
+
+ // add to stats if desired
+ if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes)
{
- // if this surface fits the criteria, add it to the list
- if (surface->num_triangles)
- {
- // if lightmap parameters changed, rebuild lightmap texture
- if (surface->cached_dlight)
- R_BuildLightMap(ent, surface);
- // add face to draw list
- surfacelist[numsurfacelist++] = surface;
- r_refdef.stats.entities_triangles += surface->num_triangles;
- if (numsurfacelist >= maxsurfacelist)
- {
- r_refdef.stats.entities_surfaces += numsurfacelist;
- R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
- numsurfacelist = 0;
- }
- }
+ r_refdef.stats.entities++;
+ r_refdef.stats.entities_surfaces += numsurfacelist;
+ for (j = 0;j < numsurfacelist;j++)
+ r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
}
- r_refdef.stats.entities_surfaces += numsurfacelist;
- if (numsurfacelist)
- R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
- GL_AlphaTest(false);
}