mirror of
https://github.com/ReactionQuake3/reaction.git
synced 2025-01-23 10:00:41 +00:00
Overbright bits hack. FP16 FBO's with r_ext_framebuffer_object 2. Occlusion query for god rays.
This commit is contained in:
parent
3a6ad64407
commit
5df45cf52b
7 changed files with 211 additions and 46 deletions
|
@ -24,7 +24,11 @@
|
||||||
HANDLE_EXT_FUNC( PFNGLGETQUERYOBJECTIVARBPROC, glGetQueryObjectivARB) \
|
HANDLE_EXT_FUNC( PFNGLGETQUERYOBJECTIVARBPROC, glGetQueryObjectivARB) \
|
||||||
HANDLE_EXT_FUNC( PFNGLGETQUERYOBJECTUIVARBPROC, glGetQueryObjectuivARB) \
|
HANDLE_EXT_FUNC( PFNGLGETQUERYOBJECTUIVARBPROC, glGetQueryObjectuivARB) \
|
||||||
|
|
||||||
|
#define GL_MISSING_FUNCTIONS \
|
||||||
|
HANDLE_EXT_FUNC( PFNGLBLENDEQUATIONPROC, glBlendEquation) \
|
||||||
|
|
||||||
|
#define GL_ARB_color_buffer_float_functions \
|
||||||
|
HANDLE_EXT_FUNC( PFNGLCLAMPCOLORARBPROC, glClampColorARB) \
|
||||||
|
|
||||||
#ifndef GL_EXT_framebuffer_multisample
|
#ifndef GL_EXT_framebuffer_multisample
|
||||||
#define GL_EXT_framebuffer_multisample 1
|
#define GL_EXT_framebuffer_multisample 1
|
||||||
|
@ -57,6 +61,7 @@
|
||||||
GL_EXT_framebuffer_multisample_functions \
|
GL_EXT_framebuffer_multisample_functions \
|
||||||
GL_EXT_framebuffer_blit_functions \
|
GL_EXT_framebuffer_blit_functions \
|
||||||
GL_ARB_occlusion_query_functions \
|
GL_ARB_occlusion_query_functions \
|
||||||
|
GL_ARB_color_buffer_float_functions \
|
||||||
|
GL_MISSING_FUNCTIONS \
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -601,6 +601,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
|
||||||
float originalTime;
|
float originalTime;
|
||||||
float depth[2];
|
float depth[2];
|
||||||
fbo_t* fbo = NULL;
|
fbo_t* fbo = NULL;
|
||||||
|
qboolean inQuery = qfalse;
|
||||||
|
|
||||||
// save original time for entity shader offsets
|
// save original time for entity shader offsets
|
||||||
originalTime = backEnd.refdef.floatTime;
|
originalTime = backEnd.refdef.floatTime;
|
||||||
|
@ -665,6 +666,10 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
|
||||||
{
|
{
|
||||||
R_FBO_Bind(fbo);
|
R_FBO_Bind(fbo);
|
||||||
qglDepthRange(depth[0], depth[1]);
|
qglDepthRange(depth[0], depth[1]);
|
||||||
|
if (inQuery) {
|
||||||
|
inQuery = qfalse;
|
||||||
|
qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( entityNum != ENTITYNUM_WORLD ) {
|
if ( entityNum != ENTITYNUM_WORLD ) {
|
||||||
|
@ -687,11 +692,16 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
|
||||||
// if we're rendering to a fbo
|
// if we're rendering to a fbo
|
||||||
if (fbo) {
|
if (fbo) {
|
||||||
VectorCopy(backEnd.currentEntity->e.origin, backEnd.sunFlarePos);
|
VectorCopy(backEnd.currentEntity->e.origin, backEnd.sunFlarePos);
|
||||||
backEnd.hasSunFlare = qtrue;
|
|
||||||
sunflare = qtrue;
|
|
||||||
// switch FBO
|
// switch FBO
|
||||||
R_FBO_Bind(tr.fbo.fbos[1]);
|
R_FBO_Bind(tr.fbo.fbos[1]);
|
||||||
qglDepthRange(1.f, 1.f);
|
qglDepthRange(1.f, 1.f);
|
||||||
|
if (glRefConfig.occlusionQuery && !inQuery && !backEnd.hasSunFlare) {
|
||||||
|
inQuery = qtrue;
|
||||||
|
tr.sunFlareQueryActive[tr.sunFlareQueryIndex] = qtrue;
|
||||||
|
qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, tr.sunFlareQuery[tr.sunFlareQueryIndex]);
|
||||||
|
}
|
||||||
|
backEnd.hasSunFlare = qtrue;
|
||||||
|
sunflare = qtrue;
|
||||||
} else {
|
} else {
|
||||||
depthRange = qtrue;
|
depthRange = qtrue;
|
||||||
}
|
}
|
||||||
|
@ -785,6 +795,10 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
R_FBO_Bind(fbo);
|
R_FBO_Bind(fbo);
|
||||||
|
if (inQuery) {
|
||||||
|
inQuery = qfalse;
|
||||||
|
qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
|
||||||
|
}
|
||||||
|
|
||||||
// go back to the world modelview matrix
|
// go back to the world modelview matrix
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
|
||||||
#ifndef ARRAY_SIZE
|
|
||||||
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MAX_FBO_COLOR_BUFFERS 8
|
#define MAX_FBO_COLOR_BUFFERS 8
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -426,6 +422,18 @@ static void R_FBO_CreateDefaultBuffers(void)
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
tr.fbo.tiny[0] = R_FBO_CreateSimple(
|
||||||
|
"tiny0",
|
||||||
|
R_FBO_CreateColorBuffer("*tinyBuffer0", glConfig.vidWidth/4, glConfig.vidHeight/4, qfalse, qfalse, GL_CLAMP_TO_EDGE),
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
tr.fbo.tiny[1] = R_FBO_CreateSimple(
|
||||||
|
"tiny1",
|
||||||
|
R_FBO_CreateColorBuffer("*tinyBuffer1", glConfig.vidWidth/4, glConfig.vidHeight/4, qfalse, qfalse, GL_CLAMP_TO_EDGE),
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
ri.Printf(PRINT_DEVELOPER, "...created %d FBOs\n", tr.fbo.numFBOs);
|
ri.Printf(PRINT_DEVELOPER, "...created %d FBOs\n", tr.fbo.numFBOs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -501,11 +501,19 @@ static void Upload32( unsigned *data,
|
||||||
GLenum internalFormat = GL_RGB;
|
GLenum internalFormat = GL_RGB;
|
||||||
float rMax = 0, gMax = 0, bMax = 0;
|
float rMax = 0, gMax = 0, bMax = 0;
|
||||||
|
|
||||||
// Makro - render target
|
// Makro - no data, this must be a render target
|
||||||
if (!data)
|
if (!data)
|
||||||
|
{
|
||||||
|
if (r_ext_framebuffer_object->integer >= 2 && glRefConfig.textureFloat)
|
||||||
|
{
|
||||||
|
internalFormat = GL_RGBA16F_ARB;
|
||||||
|
qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
internalFormat = GL_RGBA8;
|
internalFormat = GL_RGBA8;
|
||||||
qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
}
|
||||||
GL_CheckErrors();
|
GL_CheckErrors();
|
||||||
*format = internalFormat;
|
*format = internalFormat;
|
||||||
*pUploadWidth = width;
|
*pUploadWidth = width;
|
||||||
|
@ -777,19 +785,45 @@ done:
|
||||||
ri.Hunk_FreeTempMemory( resampledBuffer );
|
ri.Hunk_FreeTempMemory( resampledBuffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static image_t *R_AllocImage(const char* name, int width, int height, qboolean mipmap, qboolean allowPicmip, int glWrapClampMode)
|
||||||
|
{
|
||||||
|
image_t *image;
|
||||||
|
long hash;
|
||||||
|
|
||||||
|
image = tr.images[tr.numImages++] = ri.Hunk_Alloc( sizeof( image_t ), h_low );
|
||||||
|
Com_Memset(image, 0, sizeof(*image));
|
||||||
|
|
||||||
|
image->texnum = 1024 + tr.numImages;
|
||||||
|
image->mipmap = mipmap;
|
||||||
|
image->allowPicmip = allowPicmip;
|
||||||
|
|
||||||
|
strcpy (image->imgName, name);
|
||||||
|
|
||||||
|
image->width = width;
|
||||||
|
image->height = height;
|
||||||
|
image->wrapClampMode = glWrapClampMode;
|
||||||
|
|
||||||
|
hash = generateHashValue(name);
|
||||||
|
image->next = hashTable[hash];
|
||||||
|
hashTable[hash] = image;
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
R_CreateImage
|
R_CreateImage
|
||||||
|
|
||||||
This is the only way any image_t are created
|
This is the only way any image_t are created
|
||||||
|
|
||||||
|
Makro - except maybe for render targets
|
||||||
|
at some point in the near future...
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
image_t *R_CreateImage( const char *name, const byte *pic, int width, int height,
|
image_t *R_CreateImage( const char *name, const byte *pic, int width, int height,
|
||||||
qboolean mipmap, qboolean allowPicmip, int glWrapClampMode ) {
|
qboolean mipmap, qboolean allowPicmip, int glWrapClampMode ) {
|
||||||
image_t *image;
|
image_t *image;
|
||||||
qboolean isLightmap = qfalse;
|
qboolean isLightmap = qfalse;
|
||||||
long hash;
|
|
||||||
|
|
||||||
if (strlen(name) >= MAX_QPATH ) {
|
if (strlen(name) >= MAX_QPATH ) {
|
||||||
ri.Error (ERR_DROP, "R_CreateImage: \"%s\" is too long\n", name);
|
ri.Error (ERR_DROP, "R_CreateImage: \"%s\" is too long\n", name);
|
||||||
|
@ -802,18 +836,7 @@ image_t *R_CreateImage( const char *name, const byte *pic, int width, int height
|
||||||
ri.Error( ERR_DROP, "R_CreateImage: MAX_DRAWIMAGES hit\n");
|
ri.Error( ERR_DROP, "R_CreateImage: MAX_DRAWIMAGES hit\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
image = tr.images[tr.numImages] = ri.Hunk_Alloc( sizeof( image_t ), h_low );
|
image = R_AllocImage(name, width, height, mipmap, allowPicmip, glWrapClampMode);
|
||||||
image->texnum = 1024 + tr.numImages;
|
|
||||||
tr.numImages++;
|
|
||||||
|
|
||||||
image->mipmap = mipmap;
|
|
||||||
image->allowPicmip = allowPicmip;
|
|
||||||
|
|
||||||
strcpy (image->imgName, name);
|
|
||||||
|
|
||||||
image->width = width;
|
|
||||||
image->height = height;
|
|
||||||
image->wrapClampMode = glWrapClampMode;
|
|
||||||
|
|
||||||
// lightmaps are always allocated on TMU 1
|
// lightmaps are always allocated on TMU 1
|
||||||
if ( qglActiveTextureARB && isLightmap ) {
|
if ( qglActiveTextureARB && isLightmap ) {
|
||||||
|
@ -845,10 +868,6 @@ image_t *R_CreateImage( const char *name, const byte *pic, int width, int height
|
||||||
GL_SelectTexture( 0 );
|
GL_SelectTexture( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
hash = generateHashValue(name);
|
|
||||||
image->next = hashTable[hash];
|
|
||||||
hashTable[hash] = image;
|
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1226,12 +1245,12 @@ void R_SetColorMappings( void ) {
|
||||||
|
|
||||||
// setup the overbright lighting
|
// setup the overbright lighting
|
||||||
tr.overbrightBits = r_overBrightBits->integer;
|
tr.overbrightBits = r_overBrightBits->integer;
|
||||||
if ( !glConfig.deviceSupportsGamma ) {
|
if ( !glConfig.deviceSupportsGamma && !glRefConfig.glslOverbright ) {
|
||||||
tr.overbrightBits = 0; // need hardware gamma for overbright
|
tr.overbrightBits = 0; // need hardware gamma for overbright
|
||||||
}
|
}
|
||||||
|
|
||||||
// never overbright in windowed mode
|
// never overbright in windowed mode
|
||||||
if ( !glConfig.isFullscreen )
|
if ( !glConfig.isFullscreen && !glRefConfig.glslOverbright )
|
||||||
{
|
{
|
||||||
tr.overbrightBits = 0;
|
tr.overbrightBits = 0;
|
||||||
}
|
}
|
||||||
|
@ -1268,6 +1287,9 @@ void R_SetColorMappings( void ) {
|
||||||
|
|
||||||
shift = tr.overbrightBits;
|
shift = tr.overbrightBits;
|
||||||
|
|
||||||
|
if (glRefConfig.glslOverbright)
|
||||||
|
shift = 0;
|
||||||
|
|
||||||
for ( i = 0; i < 256; i++ ) {
|
for ( i = 0; i < 256; i++ ) {
|
||||||
if ( g == 1 ) {
|
if ( g == 1 ) {
|
||||||
inf = i;
|
inf = i;
|
||||||
|
|
|
@ -410,7 +410,7 @@ void RB_TakeScreenshotJPEG( int x, int y, int width, int height, char *fileName
|
||||||
|
|
||||||
buffer = ri.Hunk_AllocateTempMemory(glConfig.vidWidth*glConfig.vidHeight*4);
|
buffer = ri.Hunk_AllocateTempMemory(glConfig.vidWidth*glConfig.vidHeight*4);
|
||||||
|
|
||||||
qglReadPixels( x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer );
|
qglReadPixels( x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer );
|
||||||
|
|
||||||
// gamma correct
|
// gamma correct
|
||||||
if ( glConfig.deviceSupportsGamma ) {
|
if ( glConfig.deviceSupportsGamma ) {
|
||||||
|
@ -430,6 +430,7 @@ RB_TakeScreenshotCmd
|
||||||
*/
|
*/
|
||||||
const void *RB_TakeScreenshotCmd( const void *data ) {
|
const void *RB_TakeScreenshotCmd( const void *data ) {
|
||||||
const screenshotCommand_t *cmd;
|
const screenshotCommand_t *cmd;
|
||||||
|
fbo_t *fbo = R_FBO_Bind(NULL);
|
||||||
|
|
||||||
cmd = (const screenshotCommand_t *)data;
|
cmd = (const screenshotCommand_t *)data;
|
||||||
|
|
||||||
|
@ -438,6 +439,8 @@ const void *RB_TakeScreenshotCmd( const void *data ) {
|
||||||
else
|
else
|
||||||
RB_TakeScreenshot( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
|
RB_TakeScreenshot( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
|
||||||
|
|
||||||
|
R_FBO_Bind(fbo);
|
||||||
|
|
||||||
return (const void *)(cmd + 1);
|
return (const void *)(cmd + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,12 +713,17 @@ const void *RB_TakeVideoFrameCmd( const void *data )
|
||||||
const videoFrameCommand_t *cmd;
|
const videoFrameCommand_t *cmd;
|
||||||
int frameSize;
|
int frameSize;
|
||||||
int i;
|
int i;
|
||||||
|
fbo_t *fbo;
|
||||||
|
|
||||||
cmd = (const videoFrameCommand_t *)data;
|
cmd = (const videoFrameCommand_t *)data;
|
||||||
|
|
||||||
|
fbo = R_FBO_Bind(NULL);
|
||||||
|
|
||||||
qglReadPixels( 0, 0, cmd->width, cmd->height, GL_RGBA,
|
qglReadPixels( 0, 0, cmd->width, cmd->height, GL_RGBA,
|
||||||
GL_UNSIGNED_BYTE, cmd->captureBuffer );
|
GL_UNSIGNED_BYTE, cmd->captureBuffer );
|
||||||
|
|
||||||
|
R_FBO_Bind(fbo);
|
||||||
|
|
||||||
// gamma correct
|
// gamma correct
|
||||||
if( glConfig.deviceSupportsGamma )
|
if( glConfig.deviceSupportsGamma )
|
||||||
R_GammaCorrect( cmd->captureBuffer, cmd->width * cmd->height * 4 );
|
R_GammaCorrect( cmd->captureBuffer, cmd->width * cmd->height * 4 );
|
||||||
|
@ -1070,12 +1078,16 @@ void R_InitQueries(void)
|
||||||
{
|
{
|
||||||
if (!glRefConfig.occlusionQuery)
|
if (!glRefConfig.occlusionQuery)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
qglGenQueriesARB(ARRAY_SIZE(tr.sunFlareQuery), tr.sunFlareQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
void R_ShutDownQueries(void)
|
void R_ShutDownQueries(void)
|
||||||
{
|
{
|
||||||
if (!glRefConfig.occlusionQuery)
|
if (!glRefConfig.occlusionQuery)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
qglDeleteQueriesARB(ARRAY_SIZE(tr.sunFlareQuery), tr.sunFlareQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -43,6 +43,10 @@ long myftol( float f );
|
||||||
|
|
||||||
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
||||||
|
|
||||||
|
#ifndef ARRAY_SIZE
|
||||||
|
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||||
|
#endif
|
||||||
|
|
||||||
// everything that is needed by the backend needs
|
// everything that is needed by the backend needs
|
||||||
// to be double buffered to allow it to run in
|
// to be double buffered to allow it to run in
|
||||||
// parallel on a dual cpu machine
|
// parallel on a dual cpu machine
|
||||||
|
@ -2166,6 +2170,11 @@ typedef struct {
|
||||||
qboolean framebufferBlit;
|
qboolean framebufferBlit;
|
||||||
qboolean framebufferMultisample;
|
qboolean framebufferMultisample;
|
||||||
|
|
||||||
|
qboolean glslOverbright;
|
||||||
|
|
||||||
|
qboolean textureFloat;
|
||||||
|
qboolean colorBufferFloat;
|
||||||
|
|
||||||
qboolean occlusionQuery;
|
qboolean occlusionQuery;
|
||||||
|
|
||||||
// These next three are all required for one chunk of code, so glsl is
|
// These next three are all required for one chunk of code, so glsl is
|
||||||
|
@ -2229,6 +2238,7 @@ typedef struct {
|
||||||
|
|
||||||
fbo_t *full[2]; // full resolution, shared zbuffer
|
fbo_t *full[2]; // full resolution, shared zbuffer
|
||||||
fbo_t *quarter[2]; // quarter resolution, no zbuffer
|
fbo_t *quarter[2]; // quarter resolution, no zbuffer
|
||||||
|
fbo_t *tiny[2]; // 1/16 resolution, no zbuffer
|
||||||
|
|
||||||
int numFBOs;
|
int numFBOs;
|
||||||
fbo_t *fbos[1024];
|
fbo_t *fbos[1024];
|
||||||
|
@ -2352,6 +2362,10 @@ typedef struct {
|
||||||
int numSkins;
|
int numSkins;
|
||||||
skin_t *skins[MAX_SKINS];
|
skin_t *skins[MAX_SKINS];
|
||||||
|
|
||||||
|
GLuint sunFlareQuery[2];
|
||||||
|
int sunFlareQueryIndex;
|
||||||
|
qboolean sunFlareQueryActive[2];
|
||||||
|
|
||||||
float sinTable[FUNCTABLE_SIZE];
|
float sinTable[FUNCTABLE_SIZE];
|
||||||
float squareTable[FUNCTABLE_SIZE];
|
float squareTable[FUNCTABLE_SIZE];
|
||||||
float triangleTable[FUNCTABLE_SIZE];
|
float triangleTable[FUNCTABLE_SIZE];
|
||||||
|
|
|
@ -158,6 +158,35 @@ static void RB_RadialBlur(int passes, float stretch, float x, float y, float w,
|
||||||
RB_Color4f(1.f, 1.f, 1.f, 1.f);
|
RB_Color4f(1.f, 1.f, 1.f, 1.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static qboolean RB_UpdateSunFlareVis(void)
|
||||||
|
{
|
||||||
|
GLuint sampleCount = 0;
|
||||||
|
if (!glRefConfig.occlusionQuery)
|
||||||
|
return qtrue;
|
||||||
|
|
||||||
|
tr.sunFlareQueryIndex ^= 1;
|
||||||
|
if (!tr.sunFlareQueryActive[tr.sunFlareQueryIndex])
|
||||||
|
return qtrue;
|
||||||
|
|
||||||
|
/* debug code */
|
||||||
|
if (0)
|
||||||
|
{
|
||||||
|
int iter;
|
||||||
|
for (iter=0 ; ; ++iter)
|
||||||
|
{
|
||||||
|
GLint available = 0;
|
||||||
|
qglGetQueryObjectivARB(tr.sunFlareQuery[tr.sunFlareQueryIndex], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
|
||||||
|
if (available)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ri.Printf(PRINT_DEVELOPER, "Waited %d iterations\n", iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
qglGetQueryObjectuivARB(tr.sunFlareQuery[tr.sunFlareQueryIndex], GL_QUERY_RESULT_ARB, &sampleCount);
|
||||||
|
return sampleCount > 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
RB_GodRays
|
RB_GodRays
|
||||||
|
@ -186,6 +215,9 @@ static void RB_GodRays(void)
|
||||||
if (dot < cutoff)
|
if (dot < cutoff)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!RB_UpdateSunFlareVis())
|
||||||
|
return;
|
||||||
|
|
||||||
VectorCopy(backEnd.sunFlarePos, pos);
|
VectorCopy(backEnd.sunFlarePos, pos);
|
||||||
pos[3] = 1.f;
|
pos[3] = 1.f;
|
||||||
|
|
||||||
|
@ -202,8 +234,8 @@ static void RB_GodRays(void)
|
||||||
// viewport dimensions
|
// viewport dimensions
|
||||||
w = glConfig.vidWidth;
|
w = glConfig.vidWidth;
|
||||||
h = glConfig.vidHeight;
|
h = glConfig.vidHeight;
|
||||||
w2 = w * 0.5f;
|
w2 = glConfig.vidWidth / 2;
|
||||||
h2 = h * 0.5f;
|
h2 = glConfig.vidHeight / 2;
|
||||||
|
|
||||||
// initialize quarter buffers
|
// initialize quarter buffers
|
||||||
{
|
{
|
||||||
|
@ -212,7 +244,7 @@ static void RB_GodRays(void)
|
||||||
RB_SetGL2D_Level(1);
|
RB_SetGL2D_Level(1);
|
||||||
|
|
||||||
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
|
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
|
||||||
RB_Color4f(1.f, 1.f, 1.f, 1.f);
|
RB_Color4f(mul, mul, mul, 1.f);
|
||||||
|
|
||||||
// first, downsample the main framebuffers
|
// first, downsample the main framebuffers
|
||||||
R_FBO_Bind(tr.fbo.quarter[0]);
|
R_FBO_Bind(tr.fbo.quarter[0]);
|
||||||
|
@ -245,15 +277,67 @@ static void RB_GodRays(void)
|
||||||
|
|
||||||
// add result back on top of the main buffer
|
// add result back on top of the main buffer
|
||||||
{
|
{
|
||||||
|
float mul = 1.f;
|
||||||
R_FBO_BindColorBuffer(R_FBO_Bind(tr.fbo.full[0]), 0);
|
R_FBO_BindColorBuffer(R_FBO_Bind(tr.fbo.full[0]), 0);
|
||||||
RB_SetGL2D_Level(0);
|
RB_SetGL2D_Level(0);
|
||||||
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
|
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
|
||||||
|
|
||||||
RB_Color4f(1.f, 1.f, 1.f, 1.f);
|
RB_Color4f(mul, mul, mul, 1.f);
|
||||||
RB_DrawQuad(0.f, 0.f, w, h, 0.f, 0.f, 1.f, 1.f);
|
RB_DrawQuad(0.f, 0.f, w, h, 0.f, 0.f, 1.f, 1.f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void RB_BlurAxis(float w, float h, qboolean horizontal)
|
||||||
|
{
|
||||||
|
float dx, dy;
|
||||||
|
float xmul, ymul;
|
||||||
|
float weights[3] = {
|
||||||
|
0.316216216f,
|
||||||
|
0.227027027f,
|
||||||
|
0.070270270f,
|
||||||
|
};
|
||||||
|
float offsets[3] = {
|
||||||
|
0.f,
|
||||||
|
1.3846153846f,
|
||||||
|
3.2307692308f,
|
||||||
|
};
|
||||||
|
|
||||||
|
xmul = horizontal;
|
||||||
|
ymul = 1.f - xmul;
|
||||||
|
|
||||||
|
xmul /= w;
|
||||||
|
ymul /= h;
|
||||||
|
|
||||||
|
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
|
||||||
|
|
||||||
|
RB_Color4f(weights[0], weights[0], weights[0], 1.f);
|
||||||
|
RB_DrawQuad(0.f, 0.f, w, h, 0.f, 0.f, 1.f, 1.f);
|
||||||
|
|
||||||
|
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
|
||||||
|
|
||||||
|
RB_Color4f(weights[1], weights[1], weights[1], 1.f);
|
||||||
|
dx = offsets[1] * xmul;
|
||||||
|
dy = offsets[1] * ymul;
|
||||||
|
RB_DrawQuad(0.f, 0.f, w, h, dx, dy, 1.f+dx, 1.f+dy);
|
||||||
|
RB_DrawQuad(0.f, 0.f, w, h, -dx, -dy, 1.f-dx, 1.f-dy);
|
||||||
|
|
||||||
|
RB_Color4f(weights[2], weights[2], weights[2], 1.f);
|
||||||
|
dx = offsets[2] * xmul;
|
||||||
|
dy = offsets[2] * ymul;
|
||||||
|
RB_DrawQuad(0.f, 0.f, w, h, dx, dy, 1.f+dx, 1.f+dy);
|
||||||
|
RB_DrawQuad(0.f, 0.f, w, h, -dx, -dy, 1.f-dx, 1.f-dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RB_HBlur(float w, float h)
|
||||||
|
{
|
||||||
|
RB_BlurAxis(w, h, qtrue);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RB_VBlur(float w, float h)
|
||||||
|
{
|
||||||
|
RB_BlurAxis(w, h, qfalse);
|
||||||
|
}
|
||||||
|
|
||||||
void RB_FBO_Set2D(void)
|
void RB_FBO_Set2D(void)
|
||||||
{
|
{
|
||||||
RB_DrawQuad = NULL;
|
RB_DrawQuad = NULL;
|
||||||
|
@ -321,6 +405,12 @@ void RB_FBO_Blit(void)
|
||||||
R_FBO_BindColorBuffer(fbo, 0);
|
R_FBO_BindColorBuffer(fbo, 0);
|
||||||
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
|
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
|
||||||
|
|
||||||
|
if (glRefConfig.glslOverbright)
|
||||||
|
{
|
||||||
|
float mul = 1.f / tr.identityLight;
|
||||||
|
RB_Color4f(mul, mul, mul, 1.f);
|
||||||
|
}
|
||||||
|
|
||||||
RB_DrawQuad(0.f, 0.f, glConfig.vidWidth, glConfig.vidHeight, 0.f, 0.f, 1.f, 1.f);
|
RB_DrawQuad(0.f, 0.f, glConfig.vidWidth, glConfig.vidHeight, 0.f, 0.f, 1.f, 1.f);
|
||||||
|
|
||||||
R_FBO_Bind(fbo);
|
R_FBO_Bind(fbo);
|
||||||
|
@ -334,7 +424,7 @@ RB_PostProcess
|
||||||
|
|
||||||
void RB_PostProcess(void)
|
void RB_PostProcess(void)
|
||||||
{
|
{
|
||||||
if (!glState.currentFBO)
|
if (!glState.currentFBO || backEnd.refdef.rdflags & RDF_NOWORLDMODEL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RB_FBO_Set2D();
|
RB_FBO_Set2D();
|
||||||
|
|
Loading…
Reference in a new issue