mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 21:57:57 +03:00
729 lines
17 KiB
C++
729 lines
17 KiB
C++
/*
|
|
===========================================================================
|
|
Copyright (C) 2023-2024 the OpenMoHAA team
|
|
|
|
This file is part of OpenMoHAA source code.
|
|
|
|
OpenMoHAA source code is free software; you can redistribute it
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
or (at your option) any later version.
|
|
|
|
OpenMoHAA source code is distributed in the hope that it will be
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OpenMoHAA source code; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
===========================================================================
|
|
*/
|
|
|
|
// tr_sun_flare.cpp: Sun flares
|
|
|
|
#include "tr_local.h"
|
|
|
|
#define MAX_FLARES 20
|
|
|
|
class flare_s
|
|
{
|
|
public:
|
|
float size;
|
|
float where;
|
|
shader_t *shader;
|
|
float alphascale;
|
|
};
|
|
|
|
class lens_flare
|
|
{
|
|
public:
|
|
static int max_flares;
|
|
|
|
float dot_min;
|
|
float fullscale;
|
|
|
|
// List of flares
|
|
int num_flares;
|
|
flare_s flares[MAX_FLARES];
|
|
|
|
shader_t *fullscreen;
|
|
int fullfade;
|
|
qboolean blend_active;
|
|
|
|
// Flare location
|
|
vec3_t trace_v;
|
|
vec3_t v;
|
|
|
|
// Color and alpha
|
|
vec3_t color;
|
|
float alpha;
|
|
|
|
// Screen projection
|
|
vec2_t screen;
|
|
float dot;
|
|
|
|
int lasttime;
|
|
float lastbright;
|
|
|
|
// Whether or not it's inside a portal sky
|
|
bool inportalsky;
|
|
|
|
qboolean initted;
|
|
|
|
public:
|
|
lens_flare()
|
|
{
|
|
color[0] = 1.0;
|
|
color[1] = 1.0;
|
|
color[2] = 1.0;
|
|
alpha = 1.0;
|
|
initted = false;
|
|
}
|
|
|
|
bool CheckRange();
|
|
bool CheckRay();
|
|
bool ScreenCalc();
|
|
virtual void Try();
|
|
virtual void Init(const char *which);
|
|
void ScreenBlend();
|
|
void InPortalSky();
|
|
void NotInPortalSky();
|
|
void SetVect(const float *vect);
|
|
|
|
void SetColor(const float *c) { VectorCopy(c, color); }
|
|
|
|
void SetAlpha(float a) { alpha = a; }
|
|
};
|
|
|
|
class dlight_lens_flare : public lens_flare
|
|
{
|
|
public:
|
|
shader_t *corona_shader;
|
|
|
|
public:
|
|
dlight_lens_flare() { corona_shader = NULL; }
|
|
|
|
void Try() override;
|
|
|
|
void Init(const char *which) override
|
|
{
|
|
lens_flare::Init(which);
|
|
corona_shader = R_FindShader("textures/sprites/corona", -1, qfalse, qfalse, qfalse, qfalse);
|
|
}
|
|
};
|
|
|
|
class sun_flare_class : public lens_flare
|
|
{
|
|
public:
|
|
bool SunCheckRay();
|
|
void SunScreenCalc();
|
|
void SunTry();
|
|
};
|
|
|
|
lens_flare torches;
|
|
dlight_lens_flare dlights;
|
|
sun_flare_class sunFlare;
|
|
int lens_flare::max_flares;
|
|
|
|
void lens_flare::SetVect(const float *vect)
|
|
{
|
|
if (inportalsky) {
|
|
vec3_t offset;
|
|
vec3_t rot_offset;
|
|
|
|
VectorSubtract(vect, tr.refdef.sky_origin, offset);
|
|
VectorRotate(offset, tr.refdef.sky_axis, rot_offset);
|
|
VectorAdd(tr.refdef.vieworg, rot_offset, v);
|
|
|
|
VectorNormalize(offset);
|
|
VectorMA(tr.refdef.vieworg, 16384, offset, trace_v);
|
|
} else {
|
|
VectorCopy(vect, v);
|
|
VectorCopy(vect, trace_v);
|
|
}
|
|
}
|
|
|
|
void lens_flare::InPortalSky()
|
|
{
|
|
inportalsky = true;
|
|
}
|
|
|
|
void lens_flare::NotInPortalSky()
|
|
{
|
|
inportalsky = false;
|
|
}
|
|
|
|
bool lens_flare::CheckRange()
|
|
{
|
|
vec3_t diff;
|
|
|
|
VectorSubtract(v, backEnd.viewParms.ori.origin, diff);
|
|
VectorNormalizeFast(diff);
|
|
dot = DotProduct(backEnd.viewParms.ori.axis[0], diff);
|
|
|
|
return dot > dot_min;
|
|
}
|
|
|
|
bool lens_flare::CheckRay()
|
|
{
|
|
trace_t trace;
|
|
|
|
ri.CM_BoxTrace(&trace, backEnd.viewParms.ori.origin, trace_v, vec3_origin, vec3_origin, 0, CONTENTS_SOLID, qfalse);
|
|
if (inportalsky) {
|
|
return (trace.surfaceFlags & 4) != 0;
|
|
}
|
|
|
|
return trace.fraction == 1.0;
|
|
}
|
|
|
|
bool lens_flare::ScreenCalc()
|
|
{
|
|
vec4_t eye;
|
|
vec4_t clip;
|
|
vec4_t point;
|
|
bool retval;
|
|
int i, j;
|
|
|
|
retval = true;
|
|
|
|
VectorCopy(v, point);
|
|
point[3] = 1.0;
|
|
|
|
VectorClear4(eye);
|
|
for (i = 0; i < 4; i++) {
|
|
for (j = 0; j < 4; j++) {
|
|
eye[i] += point[j] * tr.ori.modelMatrix[i + j * 4];
|
|
}
|
|
}
|
|
|
|
VectorClear4(clip);
|
|
for (i = 0; i < 4; i++) {
|
|
for (j = 0; j < 4; j++) {
|
|
clip[i] += eye[j] * tr.viewParms.projectionMatrix[i + j * 4];
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
if (clip[i] >= clip[3] || clip[i] <= -clip[3]) {
|
|
retval = false;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
screen[i] = clip[i] / clip[3];
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
void lens_flare::Try()
|
|
{
|
|
vec2_t diff;
|
|
vec2_t point;
|
|
float alpha;
|
|
int i;
|
|
|
|
if (!ScreenCalc()) {
|
|
return;
|
|
}
|
|
if (!CheckRange()) {
|
|
return;
|
|
}
|
|
if (!CheckRay()) {
|
|
return;
|
|
}
|
|
|
|
VectorScale2D(screen, -2.0, diff);
|
|
alpha = (dot - dot_min) / (1.0 - dot_min);
|
|
|
|
for (i = 0; i < num_flares; i++) {
|
|
flare_s *flare = &flares[i];
|
|
|
|
VectorMA2D(screen, flare->where, diff, point);
|
|
|
|
RB_Color4f(color[0], color[1], color[2], alpha * this->alpha * flare->alphascale);
|
|
RB_StreamBegin(flare->shader);
|
|
RB_Texcoord2f(0.0, 0.0);
|
|
|
|
RB_Vertex2f(point[0] - flare->size, point[1] + flare->size);
|
|
RB_Texcoord2f(1.0, 0.0);
|
|
|
|
RB_Vertex2f(point[0] + flare->size, point[1] + flare->size);
|
|
RB_Texcoord2f(0.0, 1.0);
|
|
|
|
RB_Vertex2f(point[0] - flare->size, point[1] - flare->size);
|
|
RB_Texcoord2f(1.0, 1.0);
|
|
|
|
RB_Vertex2f(point[0] + flare->size, point[1] - flare->size);
|
|
RB_StreamEnd();
|
|
}
|
|
|
|
lasttime = backEnd.refdef.time;
|
|
blend_active = true;
|
|
lastbright = Square(alpha) * Square(alpha) * this->fullscale;
|
|
}
|
|
|
|
void dlight_lens_flare::Try()
|
|
{
|
|
float size;
|
|
|
|
size = r_lightcoronasize->value;
|
|
lens_flare::Try();
|
|
lens_flare::CheckRange();
|
|
|
|
if (dot <= 0) {
|
|
return;
|
|
}
|
|
|
|
if (!CheckRay()) {
|
|
return;
|
|
}
|
|
|
|
RB_Color4f(color[0], color[1], color[2], alpha);
|
|
RB_StreamBegin(corona_shader);
|
|
RB_Texcoord2f(0.0, 0.0);
|
|
|
|
RB_Vertex2f(screen[0] - size, screen[1] + size);
|
|
RB_Texcoord2f(1.0, 0.0);
|
|
|
|
RB_Vertex2f(screen[0] + size, screen[1] + size);
|
|
RB_Texcoord2f(0.0, 1.0);
|
|
|
|
RB_Vertex2f(screen[0] - size, screen[1] - size);
|
|
RB_Texcoord2f(1.0, 1.0);
|
|
|
|
RB_Vertex2f(screen[0] + size, screen[1] - size);
|
|
RB_StreamEnd();
|
|
}
|
|
|
|
void lens_flare::ScreenBlend()
|
|
{
|
|
float alpha;
|
|
int timediff;
|
|
|
|
if (!fullscreen || !blend_active) {
|
|
return;
|
|
}
|
|
|
|
timediff = backEnd.refdef.time - lasttime;
|
|
if (timediff > fullfade) {
|
|
blend_active = false;
|
|
return;
|
|
}
|
|
|
|
alpha = (float)(fullfade - timediff) / fullfade * lastbright;
|
|
if (alpha <= 0.0001) {
|
|
blend_active = false;
|
|
return;
|
|
}
|
|
|
|
RB_Color4f(1.0, 1.0, 1.0, alpha);
|
|
|
|
RB_StreamBegin(fullscreen);
|
|
RB_Vertex2f(-1.0, -1.0);
|
|
RB_Vertex2f(1.0, -1.0);
|
|
RB_Vertex2f(-1.0, 1.0);
|
|
RB_Vertex2f(1.0, 1.0);
|
|
|
|
RB_StreamEnd();
|
|
}
|
|
|
|
class tmpRiFile
|
|
{
|
|
private:
|
|
bool file_exists;
|
|
void *buf;
|
|
|
|
public:
|
|
tmpRiFile()
|
|
{
|
|
file_exists = false;
|
|
buf = NULL;
|
|
}
|
|
|
|
~tmpRiFile() { close(); }
|
|
|
|
int open(const char *which, void **buffer)
|
|
{
|
|
close();
|
|
|
|
if (ri.FS_ReadFile(which, buffer) != -1) {
|
|
file_exists = true;
|
|
buf = *buffer;
|
|
}
|
|
|
|
return file_exists;
|
|
}
|
|
|
|
bool exists() const { return file_exists; }
|
|
|
|
void close()
|
|
{
|
|
if (file_exists) {
|
|
ri.FS_FreeFile(buf);
|
|
file_exists = false;
|
|
}
|
|
}
|
|
};
|
|
|
|
void lens_flare::Init(const char *which)
|
|
{
|
|
char *file;
|
|
const char *token;
|
|
tmpRiFile theFile;
|
|
|
|
initted = false;
|
|
theFile.open("global/lensflaredefs.txt", (void **)&file);
|
|
|
|
if (!theFile.exists()) {
|
|
ri.Printf(PRINT_WARNING, "WARNING: Could not open lens flare info file!\n");
|
|
return;
|
|
}
|
|
|
|
while ((token = COM_ParseExt(&file, qtrue))) {
|
|
if (!file) {
|
|
ri.Printf(PRINT_WARNING, "WARNING: could not find begin for section '%s' in lensflares\n", which);
|
|
return;
|
|
}
|
|
|
|
if (!Q_stricmp(token, "begin")) {
|
|
token = COM_ParseExt(&file, qfalse);
|
|
if (!Q_stricmp(token, which)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
dot_min = 0.8f;
|
|
fullscale = 0.7f;
|
|
num_flares = 0;
|
|
fullscreen = NULL;
|
|
initted = true;
|
|
fullfade = 0;
|
|
blend_active = false;
|
|
|
|
while ((token = COM_ParseExt(&file, qtrue))) {
|
|
if (!file) {
|
|
ri.Printf(PRINT_WARNING, "WARNING: could not find end for section '%s' in lensflares\n", which);
|
|
break;
|
|
}
|
|
|
|
if (!Q_stricmp(token, "dot_min")) {
|
|
token = COM_ParseExt(&file, qfalse);
|
|
if (!token[0]) {
|
|
ri.Printf(PRINT_WARNING, "WARNING: invalid dot_min in lensflares\n");
|
|
continue;
|
|
}
|
|
dot_min = atof(token);
|
|
} else if (!Q_stricmp(token, "flare")) {
|
|
assert(num_flares < MAX_FLARES);
|
|
|
|
flares[num_flares].alphascale = 1.0;
|
|
|
|
token = COM_ParseExt(&file, qfalse);
|
|
if (!token[0]) {
|
|
ri.Printf(PRINT_WARNING, "WARNING: no flare arg 1 for flare '%d' in lensflares\n", num_flares);
|
|
continue;
|
|
}
|
|
flares[num_flares].size = atof(token);
|
|
|
|
token = COM_ParseExt(&file, qfalse);
|
|
if (!token[0]) {
|
|
ri.Printf(PRINT_WARNING, "WARNING: no flare arg 2 for flare '%d' in lensflares\n", num_flares);
|
|
continue;
|
|
}
|
|
flares[num_flares].where = atof(token);
|
|
|
|
token = COM_ParseExt(&file, qfalse);
|
|
if (!token[0]) {
|
|
ri.Printf(PRINT_WARNING, "WARNING: no flare arg 3 for flare '%d' in lensflares\n", num_flares);
|
|
continue;
|
|
}
|
|
flares[num_flares].shader = R_FindShader(token, -1, qfalse, qfalse, qfalse, qfalse);
|
|
|
|
token = COM_ParseExt(&file, qfalse);
|
|
if (token[0]) {
|
|
flares[num_flares].alphascale = atof(token);
|
|
}
|
|
|
|
num_flares++;
|
|
} else if (!Q_stricmp(token, "fullscale")) {
|
|
token = COM_ParseExt(&file, qfalse);
|
|
if (!token[0]) {
|
|
ri.Printf(PRINT_WARNING, "WARNING: no arg for fullscale, assuming default (in lensflares)\n");
|
|
continue;
|
|
}
|
|
fullscale = atof(token);
|
|
} else if (!Q_stricmp(token, "fullscreen")) {
|
|
token = COM_ParseExt(&file, qfalse);
|
|
if (!token[0]) {
|
|
ri.Printf(PRINT_WARNING, "WARNING: no arg for fullsreen in lensflares\n");
|
|
continue;
|
|
}
|
|
fullscreen = R_FindShader(token, -1, qfalse, qfalse, qfalse, qfalse);
|
|
} else if (!Q_stricmp(token, "fullfade")) {
|
|
token = COM_ParseExt(&file, qfalse);
|
|
if (!token[0]) {
|
|
ri.Printf(PRINT_WARNING, "WARNING: no arg for fullfade in lensflares\n");
|
|
continue;
|
|
}
|
|
fullfade = atof(token);
|
|
} else if (!Q_stricmp(token, "end")) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!num_flares) {
|
|
ri.Printf(PRINT_WARNING, "WARNING: no lensflares defined!\n");
|
|
}
|
|
lasttime = backEnd.refdef.time - fullfade;
|
|
}
|
|
|
|
static void R_DrawSunFlare()
|
|
{
|
|
if (!s_sun.exists) {
|
|
return;
|
|
}
|
|
if (!sunFlare.initted) {
|
|
if (!s_sun.szFlareName[0]) {
|
|
return;
|
|
}
|
|
if (Q_stricmp(s_sun.szFlareName, "none")) {
|
|
sunFlare.Init(s_sun.szFlareName);
|
|
}
|
|
}
|
|
|
|
if (!sunFlare.initted) {
|
|
s_sun.szFlareName[0] = 0;
|
|
return;
|
|
}
|
|
|
|
if (!sunFlare.num_flares) {
|
|
return;
|
|
}
|
|
|
|
VectorMA(backEnd.viewParms.ori.origin, 16384, s_sun.flaredirection, sunFlare.trace_v);
|
|
VectorMA(backEnd.viewParms.ori.origin, 128, s_sun.flaredirection, sunFlare.v);
|
|
|
|
sunFlare.SunTry();
|
|
}
|
|
|
|
static void R_DrawSunFlareBlend()
|
|
{
|
|
if (!s_sun.exists) {
|
|
return;
|
|
}
|
|
if (!sunFlare.initted) {
|
|
return;
|
|
}
|
|
|
|
sunFlare.ScreenBlend();
|
|
}
|
|
|
|
void R_DrawLensFlares()
|
|
{
|
|
int i;
|
|
|
|
R_RotateForViewer();
|
|
|
|
qglPushMatrix();
|
|
qglLoadIdentity();
|
|
qglMatrixMode(GL_PROJECTION);
|
|
qglPushMatrix();
|
|
qglLoadIdentity();
|
|
qglOrtho(-1.0, 1.0, -1.0, 1.0, -99999.0, 99999.0);
|
|
|
|
tess.no_global_fog = true;
|
|
R_DrawSunFlare();
|
|
|
|
for (i = 0; i < backEnd.refdef.num_entities; i++) {
|
|
if ((backEnd.viewParms.isPortalSky && !(backEnd.refdef.entities[i].e.renderfx & RF_SKYENTITY))
|
|
|| (!backEnd.viewParms.isPortalSky && (backEnd.refdef.entities[i].e.renderfx & RF_SKYENTITY))) {
|
|
continue;
|
|
}
|
|
|
|
if (backEnd.refdef.entities[i].e.renderfx & RF_LENSFLARE) {
|
|
vec3_t rgb;
|
|
|
|
if (backEnd.refdef.entities[i].e.renderfx & RF_SKYENTITY) {
|
|
dlights.InPortalSky();
|
|
} else {
|
|
dlights.NotInPortalSky();
|
|
}
|
|
|
|
dlights.SetVect(backEnd.refdef.entities[i].e.origin);
|
|
|
|
//
|
|
// Set the dlight color from entity
|
|
//
|
|
|
|
rgb[0] = backEnd.refdef.entities[i].e.shaderRGBA[0] / 255.0;
|
|
rgb[1] = backEnd.refdef.entities[i].e.shaderRGBA[1] / 255.0;
|
|
rgb[2] = backEnd.refdef.entities[i].e.shaderRGBA[2] / 255.0;
|
|
dlights.SetColor(rgb);
|
|
|
|
dlights.Try();
|
|
}
|
|
|
|
if (backEnd.refdef.entities[i].e.renderfx & RF_VIEWLENSFLARE) {
|
|
vec3_t rgb;
|
|
|
|
if (backEnd.refdef.entities[i].e.renderfx & RF_SKYENTITY) {
|
|
torches.InPortalSky();
|
|
} else {
|
|
torches.NotInPortalSky();
|
|
}
|
|
|
|
torches.SetVect(backEnd.refdef.entities[i].e.origin);
|
|
|
|
rgb[0] = backEnd.refdef.entities[i].e.shaderRGBA[0] / 255.0;
|
|
rgb[1] = backEnd.refdef.entities[i].e.shaderRGBA[1] / 255.0;
|
|
rgb[2] = backEnd.refdef.entities[i].e.shaderRGBA[2] / 255.0;
|
|
torches.SetColor(rgb);
|
|
|
|
torches.Try();
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < backEnd.refdef.num_dlights; i++) {
|
|
if ((backEnd.refdef.dlights[i].type & dlighttype_t::lensflare)
|
|
|| (backEnd.refdef.dlights[i].type & dlighttype_t::additive)) {
|
|
dlights.NotInPortalSky();
|
|
dlights.SetVect(backEnd.refdef.dlights[i].origin);
|
|
dlights.SetColor(backEnd.refdef.dlights[i].color);
|
|
|
|
dlights.Try();
|
|
}
|
|
}
|
|
|
|
R_DrawSunFlareBlend();
|
|
tess.no_global_fog = qfalse;
|
|
|
|
qglPopMatrix();
|
|
qglMatrixMode(GL_MODELVIEW);
|
|
qglPopMatrix();
|
|
}
|
|
|
|
void R_InitLensFlare()
|
|
{
|
|
torches.Init("entity");
|
|
dlights.Init("dlight");
|
|
sunFlare.initted = false;
|
|
}
|
|
|
|
bool sun_flare_class::SunCheckRay()
|
|
{
|
|
mnode_t *pViewLeaf;
|
|
trace_t trace;
|
|
|
|
pViewLeaf = R_PointInLeaf(tr.refdef.vieworg);
|
|
|
|
if (pViewLeaf->area == -1 || !tr.world->vis || tr.sSunLight.leaf != (mnode_s *)-1
|
|
|| pViewLeaf->numlights && pViewLeaf->lights[0] == &tr.sSunLight) {
|
|
ri.CM_BoxTrace(
|
|
&trace, backEnd.viewParms.ori.origin, trace_v, vec3_origin, vec3_origin, 0, CONTENTS_SOLID, qfalse
|
|
);
|
|
|
|
if (trace.surfaceFlags & SURF_SKY) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void sun_flare_class::SunScreenCalc()
|
|
{
|
|
vec4_t eye;
|
|
vec4_t clip;
|
|
vec4_t point;
|
|
int i, j;
|
|
|
|
VectorCopy(v, point);
|
|
point[3] = 1.0;
|
|
|
|
VectorClear4(eye);
|
|
for (i = 0; i < 4; i++) {
|
|
for (j = 0; j < 4; j++) {
|
|
eye[i] += point[j] * tr.ori.modelMatrix[i + j * 4];
|
|
}
|
|
}
|
|
|
|
VectorClear4(clip);
|
|
for (i = 0; i < 4; i++) {
|
|
for (j = 0; j < 4; j++) {
|
|
clip[i] += eye[j] * tr.viewParms.projectionMatrix[i + j * 4];
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
screen[i] = clip[i] / clip[3];
|
|
}
|
|
}
|
|
|
|
void sun_flare_class::SunTry()
|
|
{
|
|
vec2_t diff;
|
|
vec2_t point;
|
|
float alpha;
|
|
int i;
|
|
qboolean bDrawingFade = qfalse;
|
|
|
|
if (!CheckRange()) {
|
|
return;
|
|
}
|
|
|
|
if (SunCheckRay()) {
|
|
alpha = (dot - dot_min) / (1.0 - dot_min);
|
|
} else {
|
|
int timediff;
|
|
|
|
if (!fullscreen) {
|
|
return;
|
|
}
|
|
if (!blend_active) {
|
|
return;
|
|
}
|
|
|
|
timediff = backEnd.refdef.time - lasttime;
|
|
alpha = (float)(fullfade - timediff) / fullfade * lastbright;
|
|
|
|
if (alpha <= 0.0001) {
|
|
return;
|
|
}
|
|
|
|
bDrawingFade = qtrue;
|
|
}
|
|
|
|
SunScreenCalc();
|
|
VectorScale2D(screen, -2.0, diff);
|
|
|
|
for (i = 0; i < num_flares; i++) {
|
|
flare_s *flare = &flares[i];
|
|
|
|
VectorMA2D(screen, flare->where, diff, point);
|
|
|
|
RB_Color4f(color[0], color[1], color[2], alpha * this->alpha * flare->alphascale);
|
|
RB_StreamBegin(flare->shader);
|
|
RB_Texcoord2f(0.0, 0.0);
|
|
|
|
RB_Vertex2f(point[0] - flare->size, point[1] + flare->size);
|
|
RB_Texcoord2f(1.0, 0.0);
|
|
|
|
RB_Vertex2f(point[0] + flare->size, point[1] + flare->size);
|
|
RB_Texcoord2f(0.0, 1.0);
|
|
|
|
RB_Vertex2f(point[0] - flare->size, point[1] - flare->size);
|
|
RB_Texcoord2f(1.0, 1.0);
|
|
|
|
RB_Vertex2f(point[0] + flare->size, point[1] - flare->size);
|
|
RB_StreamEnd();
|
|
}
|
|
|
|
if (!bDrawingFade) {
|
|
lasttime = backEnd.refdef.time;
|
|
blend_active = true;
|
|
lastbright = Square(alpha) * Square(alpha) * fullscale;
|
|
}
|
|
}
|