diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index ad363cefe..32a697a2b 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -202,6 +202,10 @@ static int comparePolygons(const void *p1, const void *p2) diff = poly1->surf.LightInfo.fade_start - poly2->surf.LightInfo.fade_start; if (diff != 0) return diff; diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end; + + diff = poly1->surf.LightInfo.directional - poly2->surf.LightInfo.directional; + if (diff != 0) return diff; + return diff; } @@ -269,6 +273,7 @@ void HWR_RenderBatches(void) nextSurfaceInfo.LightInfo.fade_end = 0; nextSurfaceInfo.LightInfo.fade_start = 0; nextSurfaceInfo.LightInfo.light_level = 0; + nextSurfaceInfo.LightInfo.directional = false; currently_batching = false;// no longer collecting batches if (!polygonArraySize) @@ -424,7 +429,8 @@ void HWR_RenderBatches(void) currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba || currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level || currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || - currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end) + currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end || + currentSurfaceInfo.LightInfo.directional != nextSurfaceInfo.LightInfo.directional) { changeState = true; changeSurfaceInfo = true; diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index e631604cb..621cb9015 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -277,6 +277,7 @@ struct FLightInfo FUINT light_level; FUINT fade_start; FUINT fade_end; + boolean directional; }; typedef struct FLightInfo FLightInfo; @@ -321,6 +322,11 @@ typedef enum hwdshaderoption hwdshaderoption_t; enum hwdshaderinfo { HWD_SHADERINFO_LEVELTIME = 1, + HWD_SHADERINFO_LIGHT_X, + HWD_SHADERINFO_LIGHT_Y, + HWD_SHADERINFO_LIGHT_Z, + HWD_SHADERINFO_LIGHT_CONTRAST, + HWD_SHADERINFO_LIGHT_BACKLIGHT, }; typedef enum hwdshaderinfo hwdshaderinfo_t; diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 1c2b96a69..17b8ca800 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -100,6 +100,8 @@ typedef struct gl_vissprite_s mobj_t *mobj; // NOTE: This is a precipmobj_t if precip is true !!! Watch out. } gl_vissprite_t; +void HWR_ObjectLightLevelPost(gl_vissprite_t *spr, const sector_t *sector, INT32 *lightlevel, boolean model); + // -------- // hw_bsp.c // -------- diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 3595d7138..271076b05 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -199,13 +199,68 @@ boolean HWR_OverrideObjectLightLevel(mobj_t *thing, INT32 *lightlevel) *lightlevel = 255; else if (R_ThingIsFullDark(thing)) *lightlevel = 0; + else if (thing->renderflags & RF_ABSOLUTELIGHTLEVEL) + *lightlevel = R_ThingLightLevel(thing); else return false; return true; } -void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap) +void HWR_ObjectLightLevelPost(gl_vissprite_t *spr, const sector_t *sector, INT32 *lightlevel, boolean model) +{ + const boolean semibright = R_ThingIsSemiBright(spr->mobj); + const boolean papersprite = R_ThingIsPaperSprite(spr->mobj); + + *lightlevel += R_ThingLightLevel(spr->mobj); + + if (maplighting.directional == true && P_SectorUsesDirectionalLighting(sector)) + { + if (model == false) // this is implemented by shader + { + fixed_t extralight = R_GetSpriteDirectionalLighting( + papersprite + ? spr->angle + (spr->flip ? -ANGLE_90 : ANGLE_90) + : R_PointToAngle(spr->mobj->x, spr->mobj->y) // fixme + ); + + // Less change in contrast in dark sectors + extralight = FixedMul(extralight, min(max(0, *lightlevel), 255) * FRACUNIT / 255); + + if (papersprite) + { + // Papersprite contrast should match walls + *lightlevel += FixedFloor(extralight + (FRACUNIT / 2)) / FRACUNIT; + } + else + { + // simple OGL approximation + fixed_t tr = R_PointToDist(spr->mobj->x, spr->mobj->y); + fixed_t xscale = FixedDiv((vid.width / 2) << FRACBITS, tr); + + // Less change in contrast at further distances, to counteract DOOM diminished light + fixed_t n = FixedDiv(FixedMul(xscale, LIGHTRESOLUTIONFIX), ((MAXLIGHTSCALE-1) << LIGHTSCALESHIFT)); + extralight = FixedMul(extralight, min(n, FRACUNIT)); + + // Contrast is stronger for normal sprites, stronger than wall lighting is at the same distance + *lightlevel += FixedFloor((extralight * 2) + (FRACUNIT / 2)) / FRACUNIT; + } + } + + // Semibright objects will be made slightly brighter to compensate contrast + if (semibright) + { + *lightlevel += 16; + } + } + + if (semibright) + { + *lightlevel = 192 + (*lightlevel >> 1); + } +} + +void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap, const boolean directional) { RGBA_t poly_color, tint_color, fade_color; @@ -256,9 +311,12 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col Surface->PolyColor.rgba = poly_color.rgba; Surface->TintColor.rgba = tint_color.rgba; Surface->FadeColor.rgba = fade_color.rgba; + Surface->LightInfo.light_level = light_level; Surface->LightInfo.fade_start = (colormap != NULL) ? colormap->fadestart : 0; Surface->LightInfo.fade_end = (colormap != NULL) ? colormap->fadeend : 31; + + Surface->LightInfo.directional = (maplighting.directional == true && directional == true); } UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap) // Let's see if this can work @@ -306,13 +364,13 @@ static FUINT HWR_CalcWallLight(FUINT lightnum, seg_t *seg) return (FUINT)finallight; } -static FUINT HWR_CalcSlopeLight(FUINT lightnum, pslope_t *slope, const sector_t *sector) +static FUINT HWR_CalcSlopeLight(FUINT lightnum, pslope_t *slope, const sector_t *sector, const boolean fof) { INT16 finallight = lightnum; if (slope != NULL && sector != NULL && P_ApplyLightOffsetFine(lightnum, sector)) { - finallight += slope->hwLightOffset; + finallight += (fof ? -slope->hwLightOffset : slope->hwLightOffset); if (finallight > 255) finallight = 255; if (finallight < 0) finallight = 0; @@ -504,8 +562,8 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool for (i = 0, v3d = planeVerts; i < nrPlaneVerts; i++,v3d++,pv++) SETUP3DVERT(v3d, pv->x, pv->y); - lightlevel = HWR_CalcSlopeLight(lightlevel, slope, gl_frontsector); - HWR_Lighting(&Surf, lightlevel, planecolormap); + lightlevel = HWR_CalcSlopeLight(lightlevel, slope, gl_frontsector, (FOFsector != NULL)); + HWR_Lighting(&Surf, lightlevel, planecolormap, P_SectorUsesDirectionalLighting(gl_frontsector)); if (PolyFlags & PF_EnvironmentTrans) { @@ -744,7 +802,7 @@ static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIEL { INT32 shader = SHADER_DEFAULT; - HWR_Lighting(pSurf, lightlevel, wallcolormap); + HWR_Lighting(pSurf, lightlevel, wallcolormap, P_SectorUsesDirectionalLighting(gl_frontsector)); if (HWR_UseShader()) { @@ -2267,7 +2325,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, v3d->z = FIXED_TO_FLOAT(polysector->vertices[i]->y); } - HWR_Lighting(&Surf, lightlevel, planecolormap); + HWR_Lighting(&Surf, lightlevel, planecolormap, P_SectorUsesDirectionalLighting((FOFsector != NULL) ? FOFsector : gl_frontsector)); if (blendmode & PF_Translucent) { @@ -3151,7 +3209,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) colormap = thing->subsector->sector->extra_colormap; } - HWR_Lighting(&sSurf, 255, colormap); + HWR_Lighting(&sSurf, 255, colormap, P_SectorUsesDirectionalLighting(thing->subsector->sector)); sSurf.PolyColor.s.alpha = 255; if (thing->whiteshadow == true) @@ -3394,8 +3452,8 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) } } - if (R_ThingIsSemiBright(spr->mobj)) - lightlevel = 192 + (lightlevel>>1); + if (!lightset) + HWR_ObjectLightLevelPost(spr, sector, &lightlevel, false); for (i = 0; i < sector->numlights; i++) { @@ -3408,9 +3466,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) if (!lightset) { lightlevel = *list[i].lightlevel > 255 ? 255 : *list[i].lightlevel; - - if (R_ThingIsSemiBright(spr->mobj)) - lightlevel = 192 + (lightlevel>>1); + HWR_ObjectLightLevelPost(spr, sector, &lightlevel, false); } if (!R_ThingIsFullBright(spr->mobj) && !(spr->mobj->renderflags & RF_NOCOLORMAPS)) @@ -3477,7 +3533,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult; } - HWR_Lighting(&Surf, lightlevel, colormap); + HWR_Lighting(&Surf, lightlevel, colormap, P_SectorUsesDirectionalLighting(sector) && !R_ThingIsFullBright(spr->mobj)); Surf.PolyColor.s.alpha = alpha; @@ -3506,7 +3562,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) wallVerts[0].y = bot; wallVerts[1].y = endbot; - HWR_Lighting(&Surf, lightlevel, colormap); + HWR_Lighting(&Surf, lightlevel, colormap, P_SectorUsesDirectionalLighting(sector)); Surf.PolyColor.s.alpha = alpha; @@ -3582,7 +3638,9 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) if (!spr->mobj->subsector) return; - if (spr->mobj->subsector->sector->numlights && !splat) + if (spr->mobj->subsector->sector->numlights + && (spr->mobj->renderflags & RF_ABSOLUTELIGHTLEVEL) == 0 + && !splat) { HWR_SplitSprite(spr); return; @@ -3796,10 +3854,10 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) else if (!lightset) lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel; - if (R_ThingIsSemiBright(spr->mobj)) - lightlevel = 128 + (lightlevel>>1); + if (!lightset) + HWR_ObjectLightLevelPost(spr, sector, &lightlevel, false); - HWR_Lighting(&Surf, lightlevel, colormap); + HWR_Lighting(&Surf, lightlevel, colormap, P_SectorUsesDirectionalLighting(sector) && !R_ThingIsFullBright(spr->mobj)); } { @@ -3946,7 +4004,7 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) //lightlevel = 128 + (lightlevel>>1); - HWR_Lighting(&Surf, lightlevel, colormap); + HWR_Lighting(&Surf, lightlevel, colormap, P_SectorUsesDirectionalLighting(sector)); } // Determine the blendmode and translucency value @@ -4410,7 +4468,7 @@ static void HWR_DrawSprites(void) #ifdef BAD_MODEL_OPTIONS HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, cv_glmodellighting.value); #else - HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, false); + HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, 1); #endif for (i = 0; i < gl_visspritecount; i++) @@ -5867,8 +5925,18 @@ void HWR_RenderPlayerView(void) ClearColor.alpha = 1.0f; if (cv_glshaders.value) + { HWD.pfnSetShaderInfo(HWD_SHADERINFO_LEVELTIME, (INT32)leveltime); // The water surface shader needs the leveltime. + const angle_t light_angle = maplighting.angle - viewangle + ANGLE_90; // I fucking hate OGL's coordinate system + HWD.pfnSetShaderInfo(HWD_SHADERINFO_LIGHT_X, FINECOSINE(light_angle >> ANGLETOFINESHIFT)); + HWD.pfnSetShaderInfo(HWD_SHADERINFO_LIGHT_Y, 0); + HWD.pfnSetShaderInfo(HWD_SHADERINFO_LIGHT_Z, -FINESINE(light_angle >> ANGLETOFINESHIFT)); + + HWD.pfnSetShaderInfo(HWD_SHADERINFO_LIGHT_CONTRAST, maplighting.contrast); + HWD.pfnSetShaderInfo(HWD_SHADERINFO_LIGHT_BACKLIGHT, maplighting.backlight); + } + if (viewssnum == 0) // Only do it if it's the first screen being rendered HWD.pfnClearBuffer(true, false, &ClearColor); // Clear the Color Buffer, stops HOMs. Also seems to fix the skybox issue on Intel GPUs. @@ -6072,7 +6140,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, INT32 shader = SHADER_DEFAULT; // Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting - HWR_Lighting(pSurf, lightlevel, wallcolormap); + HWR_Lighting(pSurf, lightlevel, wallcolormap, P_SectorUsesDirectionalLighting(gl_frontsector)); pSurf->PolyColor.s.alpha = alpha; // put the alpha back after lighting diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 010d83327..0c5239d6f 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -72,7 +72,7 @@ void HWR_DrawScreenFinalTexture(int width, int height); // This stuff is put here so models can use them boolean HWR_OverrideObjectLightLevel(mobj_t *thing, INT32 *lightlevel); -void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap); +void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap, const boolean directional); UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work UINT8 HWR_GetTranstableAlpha(INT32 transtablenum); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 5720223a9..acddebc9c 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1355,10 +1355,10 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) colormap = sector->extra_colormap; } - if (R_ThingIsSemiBright(spr->mobj)) - lightlevel = 128 + (lightlevel>>1); + if (!lightset) + HWR_ObjectLightLevelPost(spr, sector, &lightlevel, true); - HWR_Lighting(&Surf, lightlevel, colormap); + HWR_Lighting(&Surf, lightlevel, colormap, P_SectorUsesDirectionalLighting(sector) && !R_ThingIsFullBright(spr->mobj)); } else Surf.PolyColor.rgba = 0xFFFFFFFF; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index b6c767043..d5366bf4d 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -591,6 +591,9 @@ typedef enum gluniform_lighting, gluniform_fade_start, gluniform_fade_end, + gluniform_light_dir, + gluniform_light_contrast, + gluniform_light_backlight, // misc. (custom shaders) gluniform_leveltime, @@ -621,6 +624,11 @@ static gl_shaderstate_t gl_shaderstate; // Shader info static INT32 shader_leveltime = 0; +static float shader_light_x = 0.0f; +static float shader_light_y = 0.0f; +static float shader_light_z = 0.0f; +static INT32 shader_light_contrast = 0; +static INT32 shader_light_backlight = 0; // Lactozilla: Shader functions static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar *vert_shader, const GLchar *frag_shader); @@ -629,56 +637,6 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; -// ================ -// Vertex shaders -// ================ - -// -// Generic vertex shader -// - -#define GLSL_DEFAULT_VERTEX_SHADER \ - "void main()\n" \ - "{\n" \ - "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ - "gl_FrontColor = gl_Color;\n" \ - "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ - "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ - "}\0" - -// replicates the way fixed function lighting is used by the model lighting option, -// stores the lighting result to gl_Color -// (ambient lighting of 0.75 and diffuse lighting from above) -#define GLSL_MODEL_LIGHTING_VERTEX_SHADER \ - "void main()\n" \ - "{\n" \ - "float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \ - "float light = 0.75 + max(nDotVP, 0.0);\n" \ - "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ - "gl_FrontColor = vec4(light, light, light, 1.0);\n" \ - "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ - "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ - "}\0" - -// ================== -// Fragment shaders -// ================== - -// -// Generic fragment shader -// - -#define GLSL_DEFAULT_FRAGMENT_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform vec4 poly_color;\n" \ - "void main(void) {\n" \ - "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \ - "}\0" - -// -// Software fragment shader -// - #define GLSL_DOOM_COLORMAP \ "float R_DoomColormap(float light, float z)\n" \ "{\n" \ @@ -707,7 +665,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "}\n" #define GLSL_SOFTWARE_FADE_EQUATION \ - "float darkness = R_DoomLightingEquation(lighting + light_gain);\n" \ + "float darkness = R_DoomLightingEquation(final_lighting);\n" \ "if (fade_start > 0.0 || fade_end < 31.0) {\n" \ "float fs = fade_start / 31.0;\n" \ "float fe = fade_end / 31.0;\n" \ @@ -746,7 +704,68 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "final_color.b += colorIntensity;\n" \ "} else {\n" \ "final_color.b -= colorIntensity;\n" \ - "}\n" \ + "}\n" + +// ================ +// Vertex shaders +// ================ + +// +// Generic vertex shader +// + +#define GLSL_DEFAULT_VERTEX_SHADER \ + "void main()\n" \ + "{\n" \ + "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ + "gl_FrontColor = gl_Color;\n" \ + "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ + "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ + "}\0" + +// reinterpretation of sprite lighting for models +// it's a combination of how it works for normal sprites & papersprites +#define GLSL_MODEL_LIGHTING_VERTEX_SHADER \ + "uniform float lighting;\n" \ + "uniform vec3 light_dir;\n" \ + "uniform float light_contrast;\n" \ + "uniform float light_backlight;\n" \ + "void main()\n" \ + "{\n" \ + "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ + "float light = lighting;\n" \ + "if (length(light_dir) > 0.000001) {\n" \ + "mat4 m4 = gl_ProjectionMatrix * gl_ModelViewMatrix;\n" \ + "mat3 m3 = mat3( m4[0].xyz, m4[1].xyz, m4[2].xyz );\n" \ + "float extralight = -dot(normalize(gl_Normal * m3), normalize(light_dir));\n" \ + "extralight *= light_contrast - light_backlight;\n" \ + "extralight *= lighting / 255.0;\n" \ + "light += extralight * 2.5;\n" \ + "}\n" \ + "light = clamp(light / 255.0, 0.0, 1.0);\n" \ + "gl_FrontColor = vec4(light, light, light, 1.0);\n" \ + "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ + "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ + "}\0" + +// ================== +// Fragment shaders +// ================== + +// +// Generic fragment shader +// + +#define GLSL_DEFAULT_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "void main(void) {\n" \ + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \ + "}\0" + +// +// Software fragment shader +// #define GLSL_SOFTWARE_FRAGMENT_SHADER \ "uniform sampler2D tex;\n" \ @@ -765,6 +784,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "vec4 final_color = base_color;\n" \ "float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \ "float light_gain = (255.0 - lighting) * brightmap_mix;\n" \ + "float final_lighting = lighting + light_gain;\n" \ GLSL_SOFTWARE_TINT_EQUATION \ GLSL_SOFTWARE_FADE_EQUATION \ "final_color.a = texel.a * poly_color.a;\n" \ @@ -779,7 +799,6 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "uniform vec4 poly_color;\n" \ "uniform vec4 tint_color;\n" \ "uniform vec4 fade_color;\n" \ - "uniform float lighting;\n" \ "uniform float fade_start;\n" \ "uniform float fade_end;\n" \ GLSL_DOOM_COLORMAP \ @@ -788,11 +807,12 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ "vec4 base_color = texel * poly_color;\n" \ "vec4 final_color = base_color;\n" \ + "float final_lighting = gl_Color.r * 255.0;\n" \ "float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \ - "float light_gain = (255.0 - lighting) * brightmap_mix;\n" \ + "float light_gain = (255.0 - final_lighting) * brightmap_mix;\n" \ + "final_lighting += light_gain;\n" \ GLSL_SOFTWARE_TINT_EQUATION \ GLSL_SOFTWARE_FADE_EQUATION \ - "final_color *= gl_Color;\n" \ "final_color.a = texel.a * poly_color.a;\n" \ "gl_FragColor = final_color;\n" \ "}\0" @@ -830,6 +850,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "vec4 final_color = base_color;\n" \ "float brightmap_mix = floor(texture2D(brightmap, gl_TexCoord[0].st).r);\n" \ "float light_gain = (255.0 - lighting) * brightmap_mix;\n" \ + "float final_lighting = lighting + light_gain;\n" \ GLSL_SOFTWARE_TINT_EQUATION \ GLSL_SOFTWARE_FADE_EQUATION \ "final_color.a = texel.a * poly_color.a;\n" \ @@ -855,6 +876,7 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; "vec4 final_color = base_color;\n" \ "float brightmap_mix = 0.0;\n" \ "float light_gain = 0.0;\n" \ + "float final_lighting = lighting + light_gain;\n" \ GLSL_SOFTWARE_TINT_EQUATION \ GLSL_SOFTWARE_FADE_EQUATION \ "gl_FragColor = final_color;\n" \ @@ -1036,6 +1058,21 @@ EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value) case HWD_SHADERINFO_LEVELTIME: shader_leveltime = value; break; + case HWD_SHADERINFO_LIGHT_X: + shader_light_x = FixedToFloat(value); + break; + case HWD_SHADERINFO_LIGHT_Y: + shader_light_y = FixedToFloat(value); + break; + case HWD_SHADERINFO_LIGHT_Z: + shader_light_z = FixedToFloat(value); + break; + case HWD_SHADERINFO_LIGHT_CONTRAST: + shader_light_contrast = value; + break; + case HWD_SHADERINFO_LIGHT_BACKLIGHT: + shader_light_backlight = value; + break; default: break; } @@ -2121,12 +2158,35 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF UNIFORM_4(shader->uniforms[gluniform_poly_color], poly->red, poly->green, poly->blue, poly->alpha, pglUniform4f); UNIFORM_4(shader->uniforms[gluniform_tint_color], tint->red, tint->green, tint->blue, tint->alpha, pglUniform4f); UNIFORM_4(shader->uniforms[gluniform_fade_color], fade->red, fade->green, fade->blue, fade->alpha, pglUniform4f); + + boolean directional = false; if (Surface != NULL) { UNIFORM_1(shader->uniforms[gluniform_lighting], Surface->LightInfo.light_level, pglUniform1f); UNIFORM_1(shader->uniforms[gluniform_fade_start], Surface->LightInfo.fade_start, pglUniform1f); UNIFORM_1(shader->uniforms[gluniform_fade_end], Surface->LightInfo.fade_end, pglUniform1f); + directional = Surface->LightInfo.directional; } + else + { + UNIFORM_1(shader->uniforms[gluniform_lighting], 255, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_fade_start], 0, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_fade_end], 31, pglUniform1f); + } + + if (directional) + { + UNIFORM_3(shader->uniforms[gluniform_light_dir], shader_light_x, shader_light_y, shader_light_z, pglUniform3f); + UNIFORM_1(shader->uniforms[gluniform_light_contrast], shader_light_contrast, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_light_backlight], shader_light_backlight, pglUniform1f); + } + else + { + UNIFORM_3(shader->uniforms[gluniform_light_dir], 0, 0, 0, pglUniform3f); + UNIFORM_1(shader->uniforms[gluniform_light_contrast], 0, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_light_backlight], 0, pglUniform1f); + } + UNIFORM_1(shader->uniforms[gluniform_leveltime], ((float)shader_leveltime) / TICRATE, pglUniform1f); #undef UNIFORM_1 @@ -2228,6 +2288,9 @@ static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar shader->uniforms[gluniform_lighting] = GETUNI("lighting"); shader->uniforms[gluniform_fade_start] = GETUNI("fade_start"); shader->uniforms[gluniform_fade_end] = GETUNI("fade_end"); + shader->uniforms[gluniform_light_dir] = GETUNI("light_dir"); + shader->uniforms[gluniform_light_contrast] = GETUNI("light_contrast"); + shader->uniforms[gluniform_light_backlight] = GETUNI("light_backlight"); // misc. (custom shaders) shader->uniforms[gluniform_leveltime] = GETUNI("leveltime"); @@ -2820,13 +2883,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float diffuse[2] = poly.blue; diffuse[3] = poly.alpha; - if (ambient[0] > 0.75f) - ambient[0] = 0.75f; - if (ambient[1] > 0.75f) - ambient[1] = 0.75f; - if (ambient[2] > 0.75f) - ambient[2] = 0.75f; - pglLightfv(GL_LIGHT0, GL_POSITION, LightPos); pglEnable(GL_LIGHTING); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 414fd210b..55529928a 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3658,23 +3658,26 @@ void P_UpdateSegLightOffset(seg_t *li) boolean P_SectorUsesDirectionalLighting(const sector_t *sector) { - // explicitly turned on - if (sector->flags & MSF_DIRECTIONLIGHTING) + if (sector != NULL) { - return true; - } + // explicitly turned on + if (sector->flags & MSF_DIRECTIONLIGHTING) + { + return true; + } - // explicitly turned off - if (sector->flags & MSF_FLATLIGHTING) - { - return false; - } + // explicitly turned off + if (sector->flags & MSF_FLATLIGHTING) + { + return false; + } - // automatically turned on - if (sector->ceilingpic == skyflatnum) - { - // sky is visible - return true; + // automatically turned on + if (sector->ceilingpic == skyflatnum) + { + // sky is visible + return true; + } } // default is off, for indoors diff --git a/src/r_things.cpp b/src/r_things.cpp index 6afe405b1..8dcd89df6 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1679,7 +1679,7 @@ static void R_ProjectBoundingBox(mobj_t *thing, vissprite_t *vis) box->x2test = 0; } -static fixed_t R_GetSpriteDirectionalLighting(angle_t angle) +fixed_t R_GetSpriteDirectionalLighting(angle_t angle) { // Copied from P_UpdateSegLightOffset const UINT8 contrast = std::min(std::max(0, maplighting.contrast - maplighting.backlight), UINT8_MAX); diff --git a/src/r_things.h b/src/r_things.h index 5ad5687e1..7148caacc 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -64,6 +64,7 @@ extern INT16 negonearray[MAXVIDWIDTH]; extern INT16 screenheightarray[MAXVIDWIDTH]; fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope); +fixed_t R_GetSpriteDirectionalLighting(angle_t angle); //SoM: 6/5/2000: Light sprites correctly! void R_AddSprites(sector_t *sec, INT32 lightlevel);