Skip to content

Commit a80b19e

Browse files
committed
Implement MSAA
Add `r_msaa`. When set to > 0, an MSAA FBO will be created with that many samples. This FBO will be used for rendering, other than when it requires sampling from current render/depth image. When such rendering is required the MSAA FBO will be blit into the main FBO and vice versa, to resolve the MSAA texture.
1 parent 8dd80ed commit a80b19e

File tree

9 files changed

+301
-146
lines changed

9 files changed

+301
-146
lines changed

src/engine/renderer/Material.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,8 @@ void BindShaderHeatHaze( Material* material ) {
945945
gl_heatHazeShaderMaterial->SetUniform_DeformEnable( true );
946946

947947
// draw to background image
948+
TransitionMSAAToMain();
949+
948950
R_BindFBO( tr.mainFBO[1 - backEnd.currentMainFBO] );
949951
}
950952

@@ -2090,6 +2092,9 @@ void MaterialSystem::RenderMaterial( Material& material, const uint32_t viewID )
20902092

20912093
if( material.shaderBinder == BindShaderHeatHaze ) {
20922094
// Hack: Use a global uniform for heatHaze with material system to avoid duplicating all of the shader stage data
2095+
const int mainFBO = r_msaa.Get() ? backEnd.currentMainFBO : 1 - backEnd.currentMainFBO;
2096+
const int heatHazeFBO = r_msaa.Get() ? 1 - backEnd.currentMainFBO : backEnd.currentMainFBO;
2097+
20932098
gl_heatHazeShaderMaterial->SetUniform_CurrentMapBindless(
20942099
GL_BindToTMU( 1, tr.currentRenderImage[1 - backEnd.currentMainFBO] )
20952100
);
@@ -2100,6 +2105,8 @@ void MaterialSystem::RenderMaterial( Material& material, const uint32_t viewID )
21002105
R_BindFBO( tr.mainFBO[backEnd.currentMainFBO] );
21012106

21022107
RenderIndirect( material, viewID );
2108+
2109+
TransitionMainToMSAA();
21032110
}
21042111

21052112
if ( r_showTris->integer

src/engine/renderer/tr_backend.cpp

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,53 @@ GLuint64 GL_BindToTMU( int unit, image_t *image )
199199
return 0;
200200
}
201201

202+
void GL_BlitFBOToMSAA( FBO_t* fbo ) {
203+
glState.currentFBO = nullptr;
204+
205+
R_BindFBO( GL_READ_FRAMEBUFFER, fbo );
206+
R_BindFBO( GL_DRAW_FRAMEBUFFER, tr.msaaFBO );
207+
glBlitFramebuffer( 0, 0, fbo->width, fbo->height, 0, 0, tr.msaaFBO->width, tr.msaaFBO->height,
208+
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST );
209+
210+
glState.currentFBO = nullptr;
211+
R_BindFBO( GL_DRAW_FRAMEBUFFER, fbo );
212+
glState.currentFBO = fbo;
213+
}
214+
215+
void GL_BlitMSAAToFBO( FBO_t* fbo ) {
216+
glState.currentFBO = nullptr;
217+
218+
R_BindFBO( GL_READ_FRAMEBUFFER, tr.msaaFBO );
219+
R_BindFBO( GL_DRAW_FRAMEBUFFER, fbo );
220+
glBlitFramebuffer( 0, 0, tr.msaaFBO->width, tr.msaaFBO->height, 0, 0, fbo->width, fbo->height,
221+
GL_COLOR_BUFFER_BIT /* | GL_DEPTH_BUFFER_BIT */, GL_NEAREST );
222+
223+
glState.currentFBO = nullptr;
224+
R_BindFBO( GL_READ_FRAMEBUFFER, fbo );
225+
glState.currentFBO = fbo;
226+
}
227+
228+
void TransitionMainToMSAA() {
229+
if ( r_msaa.Get() ) {
230+
GL_BlitFBOToMSAA( tr.mainFBO[backEnd.currentMainFBO] );
231+
R_BindFBO( tr.msaaFBO );
232+
}
233+
}
234+
235+
void TransitionMSAAToMain() {
236+
if ( r_msaa.Get() ) {
237+
GL_BlitMSAAToFBO( tr.mainFBO[backEnd.currentMainFBO] );
238+
}
239+
}
240+
241+
void BindMSAAOrMainFBO() {
242+
if ( r_msaa.Get() ) {
243+
R_BindFBO( tr.msaaFBO );
244+
} else {
245+
R_BindFBO( tr.mainFBO[backEnd.currentMainFBO] );
246+
}
247+
}
248+
202249
void GL_BlendFunc( GLenum sfactor, GLenum dfactor )
203250
{
204251
if ( glState.blendSrc != ( signed ) sfactor || glState.blendDst != ( signed ) dfactor )
@@ -797,7 +844,13 @@ void GL_TexImage2D( GLenum target, GLint level, GLint internalFormat, GLsizei wi
797844
GLint finalFormat = GL_ToSRGB( internalFormat, isSRGB );
798845

799846
glTexImage2D( target, level, finalFormat, width, height, border, format, type, data );
847+
}
848+
849+
void GL_TexImage2DMultisample( GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, bool fixedSampleLocations, bool isSRGB )
850+
{
851+
GLint finalFormat = GL_ToSRGB( internalFormat, isSRGB );
800852

853+
glTexImage2DMultisample( target, samples, finalFormat, width, height, fixedSampleLocations );
801854
}
802855

803856
void GL_TexImage3D( GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *data, bool isSRGB )
@@ -1335,7 +1388,8 @@ void RB_RenderPostDepthLightTile()
13351388
Tess_Clear();
13361389

13371390
// back to main image
1338-
R_BindFBO( tr.mainFBO[ backEnd.currentMainFBO ] );
1391+
BindMSAAOrMainFBO();
1392+
13391393
GL_Viewport( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
13401394
backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight );
13411395
GL_Scissor( backEnd.viewParms.scissorX, backEnd.viewParms.scissorY,
@@ -1431,6 +1485,8 @@ void RB_RenderBloom()
14311485
GL_BindToTMU( 0, tr.currentRenderImage[backEnd.currentMainFBO] )
14321486
);
14331487

1488+
TransitionMSAAToMain();
1489+
14341490
R_BindFBO( tr.contrastRenderFBO );
14351491
GL_ClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
14361492
glClear( GL_COLOR_BUFFER_BIT );
@@ -1495,6 +1551,8 @@ void RB_RenderBloom()
14951551
GL_PopMatrix();
14961552
}
14971553

1554+
TransitionMainToMSAA();
1555+
14981556
GL_CheckErrors();
14991557
}
15001558

@@ -1513,6 +1571,8 @@ void RB_RenderMotionBlur()
15131571

15141572
gl_motionblurShader->BindProgram( 0 );
15151573

1574+
TransitionMSAAToMain();
1575+
15161576
// Swap main FBOs
15171577
gl_motionblurShader->SetUniform_ColorMapBindless(
15181578
GL_BindToTMU( 0, tr.currentRenderImage[backEnd.currentMainFBO] )
@@ -1528,6 +1588,8 @@ void RB_RenderMotionBlur()
15281588

15291589
Tess_InstantScreenSpaceQuad();
15301590

1591+
TransitionMainToMSAA();
1592+
15311593
GL_CheckErrors();
15321594
}
15331595

@@ -2648,7 +2710,7 @@ static void RB_RenderView( bool depthPass )
26482710
backEnd.pc.c_surfaces += backEnd.viewParms.numDrawSurfs;
26492711

26502712
// disable offscreen rendering
2651-
R_BindFBO( tr.mainFBO[ backEnd.currentMainFBO ] );
2713+
BindMSAAOrMainFBO();
26522714

26532715
// we will need to change the projection matrix before drawing
26542716
// 2D images again
@@ -2768,6 +2830,8 @@ static void RB_RenderPostProcess()
27682830
materialSystem.EndFrame();
27692831
}
27702832

2833+
TransitionMSAAToMain();
2834+
27712835
RB_FXAA();
27722836

27732837
// render chromatic aberration
@@ -3402,7 +3466,7 @@ const RenderCommand *ClearBufferCommand::ExecuteSelf( ) const
34023466
}
34033467

34043468
// disable offscreen rendering
3405-
R_BindFBO( tr.mainFBO[ backEnd.currentMainFBO ] );
3469+
R_BindFBO( tr.mainFBO[backEnd.currentMainFBO] );
34063470

34073471
// we will need to change the projection matrix before drawing
34083472
// 2D images again
@@ -3423,6 +3487,11 @@ const RenderCommand *ClearBufferCommand::ExecuteSelf( ) const
34233487

34243488
glClear( clearBits );
34253489

3490+
if ( r_msaa.Get() ) {
3491+
R_BindFBO( tr.msaaFBO );
3492+
glClear( clearBits );
3493+
}
3494+
34263495
return this + 1;
34273496
}
34283497

src/engine/renderer/tr_fbo.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,8 @@ R_AttachFBOTexture2D
304304
*/
305305
void R_AttachFBOTexture2D( int target, int texId, int index )
306306
{
307-
if ( target != GL_TEXTURE_2D && ( target < GL_TEXTURE_CUBE_MAP_POSITIVE_X || target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ) )
307+
if ( target != GL_TEXTURE_2D && target != GL_TEXTURE_2D_MULTISAMPLE
308+
&& ( target < GL_TEXTURE_CUBE_MAP_POSITIVE_X || target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ) )
308309
{
309310
Log::Warn("R_AttachFBOTexture2D: invalid target %i", target );
310311
return;
@@ -356,24 +357,31 @@ void R_AttachFBOTexturePackedDepthStencil( int texId )
356357
GL_fboShim.glFramebufferTexture2D( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texId, 0 );
357358
}
358359

360+
void R_AttachFBOTexturePackedDepthStencilMSAA( int texId ) {
361+
GL_fboShim.glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, texId, 0 );
362+
GL_fboShim.glFramebufferTexture2D( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, texId, 0 );
363+
}
364+
359365
/*
360366
============
361367
R_BindFBO
362368
============
363369
*/
364370
void R_BindFBO( FBO_t *fbo )
365371
{
366-
if ( !fbo )
367-
{
372+
R_BindFBO( GL_FRAMEBUFFER, fbo );
373+
}
374+
375+
void R_BindFBO( const GLenum target, FBO_t* fbo ) {
376+
if ( !fbo ) {
368377
R_BindNullFBO();
369378
return;
370379
}
371380

372381
GLIMP_LOGCOMMENT( "--- R_BindFBO( %s ) ---", fbo->name );
373382

374-
if ( glState.currentFBO != fbo )
375-
{
376-
GL_fboShim.glBindFramebuffer( GL_FRAMEBUFFER, fbo->frameBuffer );
383+
if ( glState.currentFBO != fbo ) {
384+
GL_fboShim.glBindFramebuffer( target, fbo->frameBuffer );
377385

378386
glState.currentFBO = fbo;
379387
}
@@ -430,6 +438,17 @@ void R_InitFBOs()
430438
R_AttachFBOTexturePackedDepthStencil( tr.currentDepthImage->texnum );
431439
R_CheckFBO( tr.mainFBO[1] );
432440

441+
if( r_msaa.Get() ) {
442+
tr.msaaFBO = R_CreateFBO( "msaa", width, height );
443+
R_BindFBO( tr.msaaFBO );
444+
GL_CheckErrors();
445+
R_AttachFBOTexture2D( GL_TEXTURE_2D_MULTISAMPLE, tr.currentRenderImageMSAA->texnum, 0 );
446+
GL_CheckErrors();
447+
R_AttachFBOTexturePackedDepthStencilMSAA( tr.currentDepthImageMSAA->texnum );
448+
GL_CheckErrors();
449+
R_CheckFBO( tr.msaaFBO );
450+
}
451+
433452
if ( glConfig.realtimeLighting )
434453
{
435454
/* It's only required to create frame buffers only used by the

0 commit comments

Comments
 (0)