From a9dbcb1f7b612543e960d0401f54a0eb03d20713 Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 8 Oct 2020 23:01:13 +0100 Subject: [PATCH] HUD and PDA now working some minor bugs with videos not playing on the PDA but it is pretty much working how it was now. --- Projects/Android/AndroidManifest.xml | 4 +- .../d3es-multithread-master/neo/game/Item.cpp | 2 + .../neo/game/PlayerView.cpp | 8 +- .../neo/mobile/Android.mk | 1 + .../neo/renderer/RenderSystem.cpp | 15 + .../neo/renderer/RenderSystem.h | 3 + .../neo/renderer/RenderSystem_init.cpp | 2 + .../neo/renderer/framebuffer.cpp | 357 ++---------------- .../neo/renderer/tr_backend.cpp | 6 + .../neo/renderer/tr_local.h | 11 +- .../neo/renderer/tr_subview.cpp | 12 + 11 files changed, 100 insertions(+), 321 deletions(-) diff --git a/Projects/Android/AndroidManifest.xml b/Projects/Android/AndroidManifest.xml index 484542f..3afb82e 100644 --- a/Projects/Android/AndroidManifest.xml +++ b/Projects/Android/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="13" + android:versionName="0.1.0" android:installLocation="auto" > diff --git a/Projects/Android/jni/d3es-multithread-master/neo/game/Item.cpp b/Projects/Android/jni/d3es-multithread-master/neo/game/Item.cpp index 97ae952..7778f07 100644 --- a/Projects/Android/jni/d3es-multithread-master/neo/game/Item.cpp +++ b/Projects/Android/jni/d3es-multithread-master/neo/game/Item.cpp @@ -713,10 +713,12 @@ void idObjective::Event_CamShot( ) { fullView.width = SCREEN_WIDTH; fullView.height = SCREEN_HEIGHT; // draw a view to a texture + renderSystem->DirectFrameBufferStart(); renderSystem->CropRenderSize( 256, 256, true ); gameRenderWorld->RenderScene( &fullView ); renderSystem->CaptureRenderToFile( shotName ); renderSystem->UnCrop(); + renderSystem->DirectFrameBufferEnd(); } } } diff --git a/Projects/Android/jni/d3es-multithread-master/neo/game/PlayerView.cpp b/Projects/Android/jni/d3es-multithread-master/neo/game/PlayerView.cpp index b202398..bae40d9 100644 --- a/Projects/Android/jni/d3es-multithread-master/neo/game/PlayerView.cpp +++ b/Projects/Android/jni/d3es-multithread-master/neo/game/PlayerView.cpp @@ -455,6 +455,7 @@ idAngles idPlayerView::AngleOffset() const { idPlayerView::SingleView ================== */ + void idPlayerView::SingleView( idUserInterface *hud, const renderView_t *view ) { // normal rendering @@ -462,13 +463,18 @@ void idPlayerView::SingleView( idUserInterface *hud, const renderView_t *view ) return; } + renderSystem->DirectFrameBufferStart(); + if ( player->objectiveSystemOpen ) { player->objectiveSystem->Redraw( gameLocal.time ); } else { player->DrawHUD(hud); } - //renderSystem->CaptureRenderToImage( "_hudImage" ); + renderSystem->CaptureRenderToImage( "_hudImage" ); + + renderSystem->DirectFrameBufferEnd(); + // place the sound origin for the player gameSoundWorld->PlaceListener( view->vieworg, view->viewaxis, player->entityNumber + 1, gameLocal.time, hud ? hud->State().GetString( "location" ) : "Undefined" ); diff --git a/Projects/Android/jni/d3es-multithread-master/neo/mobile/Android.mk b/Projects/Android/jni/d3es-multithread-master/neo/mobile/Android.mk index 2780d20..4e23852 100644 --- a/Projects/Android/jni/d3es-multithread-master/neo/mobile/Android.mk +++ b/Projects/Android/jni/d3es-multithread-master/neo/mobile/Android.mk @@ -88,6 +88,7 @@ src_renderer = \ renderer/tr_trisurf.cpp \ renderer/tr_turboshadow.cpp \ renderer/etc_android.cpp \ + renderer/framebuffer.cpp src_framework = \ framework/CVarSystem.cpp \ diff --git a/Projects/Android/jni/d3es-multithread-master/neo/renderer/RenderSystem.cpp b/Projects/Android/jni/d3es-multithread-master/neo/renderer/RenderSystem.cpp index 0c4809a..24fee33 100644 --- a/Projects/Android/jni/d3es-multithread-master/neo/renderer/RenderSystem.cpp +++ b/Projects/Android/jni/d3es-multithread-master/neo/renderer/RenderSystem.cpp @@ -1181,3 +1181,18 @@ bool idRenderSystemLocal::UploadImage( const char *imageName, const byte *data, image->SetImageFilterAndRepeat(); return true; } + +void idRenderSystemLocal::DirectFrameBufferStart() +{ + emptyCommand_t *cmd; + cmd = (emptyCommand_t *)R_GetCommandBuffer( sizeof( *cmd ) ); + cmd->commandId = RC_DIRECT_BUFFER_START; +} + +void idRenderSystemLocal::DirectFrameBufferEnd() +{ + emptyCommand_t *cmd; + cmd = (emptyCommand_t *)R_GetCommandBuffer( sizeof( *cmd ) ); + cmd->commandId = RC_DIRECT_BUFFER_END; +} + diff --git a/Projects/Android/jni/d3es-multithread-master/neo/renderer/RenderSystem.h b/Projects/Android/jni/d3es-multithread-master/neo/renderer/RenderSystem.h index f264d3c..12e0cac 100644 --- a/Projects/Android/jni/d3es-multithread-master/neo/renderer/RenderSystem.h +++ b/Projects/Android/jni/d3es-multithread-master/neo/renderer/RenderSystem.h @@ -229,6 +229,9 @@ public: // texture filter / mipmapping / repeat won't be modified by the upload // returns false if the image wasn't found virtual bool UploadImage( const char *imageName, const byte *data, int width, int height ) = 0; + + virtual void DirectFrameBufferStart() = 0; + virtual void DirectFrameBufferEnd() = 0; }; extern idRenderSystem * renderSystem; diff --git a/Projects/Android/jni/d3es-multithread-master/neo/renderer/RenderSystem_init.cpp b/Projects/Android/jni/d3es-multithread-master/neo/renderer/RenderSystem_init.cpp index 5c86785..8cca096 100644 --- a/Projects/Android/jni/d3es-multithread-master/neo/renderer/RenderSystem_init.cpp +++ b/Projects/Android/jni/d3es-multithread-master/neo/renderer/RenderSystem_init.cpp @@ -1738,6 +1738,8 @@ void idRenderSystemLocal::InitOpenGL( void ) { common->Printf( "glGetError() = 0x%x\n", err ); } } + + R_InitFrameBuffer(); } /* diff --git a/Projects/Android/jni/d3es-multithread-master/neo/renderer/framebuffer.cpp b/Projects/Android/jni/d3es-multithread-master/neo/renderer/framebuffer.cpp index c48787b..c189e3d 100644 --- a/Projects/Android/jni/d3es-multithread-master/neo/renderer/framebuffer.cpp +++ b/Projects/Android/jni/d3es-multithread-master/neo/renderer/framebuffer.cpp @@ -5,356 +5,79 @@ GPL3 #include "renderer/tr_local.h" #include "renderer/VertexCache.h" - -idCVar r_framebufferFilter( "r_framebufferFilter", "0", CVAR_RENDERER | CVAR_BOOL, "Image filter when using the framebuffer. 0 = Nearest, 1 = Linear" ); - -static GLuint m_framebuffer = -1; -static GLuint m_depthbuffer; -static GLuint m_stencilbuffer; +static GLuint m_framebuffer[3]; +static GLuint m_depthbuffer[3]; static int m_framebuffer_width, m_framebuffer_height; -static GLuint m_framebuffer_texture; +static GLuint m_framebuffer_texture[3]; -static GLuint m_positionLoc; -static GLuint m_texCoordLoc; -static GLuint m_samplerLoc; - -static GLuint r_program; - -static int fixNpot(int v) -{ - int ret = 1; - while(ret < v) - ret <<= 1; - return ret; -} - -#define ALOGE(...) __android_log_print( ANDROID_LOG_ERROR, "FRAMEBUFFER", __VA_ARGS__ ) - -static const char * GlErrorString( GLenum error ) -{ - switch ( error ) - { - case GL_NO_ERROR: return "GL_NO_ERROR"; - case GL_INVALID_ENUM: return "GL_INVALID_ENUM"; - case GL_INVALID_VALUE: return "GL_INVALID_VALUE"; - case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION"; - case GL_INVALID_FRAMEBUFFER_OPERATION: return "GL_INVALID_FRAMEBUFFER_OPERATION"; - case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY"; - default: return "unknown"; - } -} - -static void GLCheckErrors( int line ) -{ - for ( int i = 0; i < 10; i++ ) - { - const GLenum error = glGetError(); - if ( error == GL_NO_ERROR ) - { - break; - } - ALOGE( "GL error on line %d: %s", line, GlErrorString( error ) ); - } -} - -#define LOG common->Printf -int loadShader(int shaderType, const char * source) -{ - int shader = qglCreateShader(shaderType); - - if(shader != 0) - { - qglShaderSource(shader, 1, &source, NULL); - qglCompileShader(shader); - - GLint length; - - qglGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); - - if(length) - { - char* buffer = new char [ length ]; - qglGetShaderInfoLog(shader, length, NULL, buffer); - LOG("shader = %s\n", buffer); - delete [] buffer; - - GLint success; - qglGetShaderiv(shader, GL_COMPILE_STATUS, &success); - - if(success != GL_TRUE) - { - LOG("ERROR compiling shader\n"); - } - } - } - else - { - LOG("FAILED to create shader"); - } - - return shader; -} - -int createProgram(const char * vertexSource, const char * fragmentSource) -{ - int vertexShader = loadShader(GL_VERTEX_SHADER, vertexSource); - int pixelShader = loadShader(GL_FRAGMENT_SHADER, fragmentSource); - - int program = glCreateProgram(); - - if(program != 0) - { - glAttachShader(program, vertexShader); - // checkGlError("glAttachShader"); - glAttachShader(program, pixelShader); - // checkGlError("glAttachShader"); - glLinkProgram(program); -#define GL_LINK_STATUS 0x8B82 - int linkStatus[1]; - glGetProgramiv(program, GL_LINK_STATUS, linkStatus); - - if(linkStatus[0] != GL_TRUE) - { - LOG("Could not link program: "); - char log[256]; - GLsizei size; - glGetProgramInfoLog(program, 256, &size, log); - LOG("Log: %s", log); - //glDeleteProgram(program); - program = 0; - } - - } - else - { - LOG("FAILED to create program"); - } - - LOG("Program linked OK %d", program); - return program; -} - -static void createShaders (void) -{ - const GLchar *vertSource = \ - "attribute vec2 a_texCoord; \n \ - attribute vec4 a_position; \n \ - varying vec2 v_texCoord; \n \ - void main() \n \ - { \n \ - gl_Position = a_position; \n \ - v_texCoord = a_texCoord; \n \ - } \n \ - "; - - const GLchar *fragSource = \ - "precision mediump float; \n \ - varying vec2 v_texCoord; \n \ - uniform sampler2D s_texture; \n \ - void main() \n \ - { \n \ - gl_FragColor = texture2D( s_texture, v_texCoord ); \n \ - //gl_FragColor = vec4( 0.8, 0.5, 0.9, 1.0 ); \n \ - } \n \ - "; - - - r_program = createProgram(vertSource, fragSource); - - glUseProgram(r_program); - - // get attrib locations - m_positionLoc = glGetAttribLocation(r_program, "a_position"); - m_texCoordLoc = glGetAttribLocation(r_program, "a_texCoord"); - m_samplerLoc = glGetUniformLocation(r_program, "s_texture"); - - if(m_positionLoc == -1) - LOG("Failed to get m_positionLoc"); - - if(m_texCoordLoc == -1) - LOG("Failed to get m_texCoordLoc"); - - if(m_samplerLoc == -1) - LOG("Failed to get m_samplerLoc"); - - glUniform1i(m_samplerLoc, 0); -} +static GLint drawFboId = 0; +static int calldepth = 0; void R_InitFrameBuffer() { - //LOG("R_InitFrameBuffer Real[%d, %d] -> Framebuffer[%d,%d]", glConfig.vidWidthReal, glConfig.vidHeightReal, glConfig.vidWidth, glConfig.vidHeight); - -/* if(glConfig.vidWidthReal == glConfig.vidWidth && glConfig.vidHeightReal == glConfig.vidHeight) - { - LOGI("Not using framebuffer"); - return; - }*/ - - //glConfig.npotAvailable = false; - m_framebuffer_width = glConfig.vidWidth; m_framebuffer_height = glConfig.vidHeight; - if (!glConfig.npotAvailable) - { - m_framebuffer_width = fixNpot(m_framebuffer_width); - m_framebuffer_height = fixNpot(m_framebuffer_height); - } + for (int i = 0; i < 3; ++i) { + // Create texture + glGenTextures(1, &m_framebuffer_texture[i]); + glBindTexture(GL_TEXTURE_2D, m_framebuffer_texture[i]); - LOGI("Framebuffer buffer size = [%d, %d]", m_framebuffer_width, m_framebuffer_height); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_framebuffer_width, m_framebuffer_height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - // Create texture - glGenTextures(1, &m_framebuffer_texture); - glBindTexture(GL_TEXTURE_2D, m_framebuffer_texture); + // Create framebuffer + glGenFramebuffers(1, &m_framebuffer[i]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_framebuffer_width, m_framebuffer_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - if(r_framebufferFilter.GetInteger() == 0) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - else - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - - // Create framebuffer - glGenFramebuffers(1, &m_framebuffer); - - // Create renderbuffer - glGenRenderbuffers(1, &m_depthbuffer); - glBindRenderbuffer(GL_RENDERBUFFER, m_depthbuffer); - - if(glConfig.depthStencilAvailable) - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, m_framebuffer_width, m_framebuffer_height); - else - { - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, m_framebuffer_width, m_framebuffer_height); - - // Need separate Stencil buffer - glGenRenderbuffers(1, &m_stencilbuffer); - glBindRenderbuffer(GL_RENDERBUFFER, m_stencilbuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, m_framebuffer_width, m_framebuffer_height); - } - - createShaders(); + // Create renderbuffer + glGenRenderbuffers(1, &m_depthbuffer[i]); + glBindRenderbuffer(GL_RENDERBUFFER, m_depthbuffer[i]); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, m_framebuffer_width, + m_framebuffer_height); + } } void R_FrameBufferStart() { - if(m_framebuffer == -1) - return; + if (calldepth == 0) { + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &drawFboId); + } // Render to framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); - GLCheckErrors(__LINE__); + glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer[calldepth]); glBindRenderbuffer(GL_RENDERBUFFER, 0); - GLCheckErrors(__LINE__); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_framebuffer_texture, 0); - GLCheckErrors(__LINE__); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_framebuffer_texture[calldepth], 0); // Attach combined depth+stencil - if(glConfig.depthStencilAvailable) - { - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthbuffer); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthbuffer); - } - else - { - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthbuffer); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilbuffer); - } + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthbuffer[calldepth]); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthbuffer[calldepth]); GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER); if(result != GL_FRAMEBUFFER_COMPLETE) { - common->Error( "Error binding Framebuffer: %d\n", result ); + common->Error( "Error binding Framebuffer: %i\n", result ); } + + glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); + qglClear( GL_COLOR_BUFFER_BIT ); + + calldepth++; } void R_FrameBufferEnd() { - if(m_framebuffer == -1) - return; + calldepth--; - //glBindFramebuffer(GL_FRAMEBUFFER, 0); - //glBindRenderbuffer(GL_RENDERBUFFER, 0); - - // Bind the texture - glBindTexture(GL_TEXTURE_2D, m_framebuffer_texture); - GLCheckErrors(__LINE__); - - // Unbind any VBOs - vertexCache.UnbindIndex(); - vertexCache.UnbindVertex(); - - glUseProgram(r_program); - GLCheckErrors(__LINE__); - - GLfloat vert[] = - { - -1.f, -1.f, 0.0f, // 0. left-bottom - -1.f, 1.f, 0.0f, // 1. left-top - 1.f, 1.f, 0.0f, // 2. right-top - 1.f, -1.f, 0.0f, // 3. right-bottom - }; - - GLfloat smax = 1; - GLfloat tmax = 1; - - if (!glConfig.npotAvailable) - { - smax = (float)glConfig.vidWidth / (float)m_framebuffer_width; - tmax = (float)glConfig.vidHeight / (float)m_framebuffer_height; - } - - GLfloat texVert[] = - { - 0.0f, 0.0f, // TexCoord 0 - 0.0f, tmax, // TexCoord 1 - smax, tmax, // TexCoord 2 - smax, 0.0f // TexCoord 3 - }; - - GLCheckErrors(__LINE__); - glVertexAttribPointer(m_positionLoc, 3, GL_FLOAT, - false, - 3 * 4, - vert); - GLCheckErrors(__LINE__); - - glVertexAttribPointer(m_texCoordLoc, 2, GL_FLOAT, - false, - 2 * 4, - texVert); - GLCheckErrors(__LINE__); - - glEnableVertexAttribArray(m_positionLoc); - GLCheckErrors(__LINE__); - glEnableVertexAttribArray(m_texCoordLoc); - GLCheckErrors(__LINE__); - - - // Set the sampler texture unit to 0 - glUniform1i(m_samplerLoc, 0); - GLCheckErrors(__LINE__); - - glViewport (0, 0, glConfig.vidWidth, glConfig.vidHeight ); - //glViewport (0, 0, glConfig.vidWidthReal, glConfig.vidHeightReal ); - GLCheckErrors(__LINE__); - - glDisable(GL_BLEND); - GLCheckErrors(__LINE__); - glDisable(GL_SCISSOR_TEST); - GLCheckErrors(__LINE__); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - GLCheckErrors(__LINE__); + if (calldepth == 0) { + glBindFramebuffer(GL_FRAMEBUFFER, drawFboId); + } else { + glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer[calldepth-1]); + } } diff --git a/Projects/Android/jni/d3es-multithread-master/neo/renderer/tr_backend.cpp b/Projects/Android/jni/d3es-multithread-master/neo/renderer/tr_backend.cpp index c162f31..e938bca 100644 --- a/Projects/Android/jni/d3es-multithread-master/neo/renderer/tr_backend.cpp +++ b/Projects/Android/jni/d3es-multithread-master/neo/renderer/tr_backend.cpp @@ -418,6 +418,12 @@ void RB_ExecuteBackEndCommands( const emptyCommand_t *cmds ) { RB_CopyRender(cmd); c_copyRenders++; break; + case RC_DIRECT_BUFFER_START: + R_FrameBufferStart(); + break; + case RC_DIRECT_BUFFER_END: + R_FrameBufferEnd(); + break; default: common->Error("RB_ExecuteBackEndCommands: bad commandId"); break; diff --git a/Projects/Android/jni/d3es-multithread-master/neo/renderer/tr_local.h b/Projects/Android/jni/d3es-multithread-master/neo/renderer/tr_local.h index cad39cd..f102dd8 100644 --- a/Projects/Android/jni/d3es-multithread-master/neo/renderer/tr_local.h +++ b/Projects/Android/jni/d3es-multithread-master/neo/renderer/tr_local.h @@ -491,7 +491,9 @@ typedef enum { RC_DRAW_VIEW, RC_SET_BUFFER, RC_COPY_RENDER, - RC_SWAP_BUFFERS // can't just assume swap at end of list because + RC_SWAP_BUFFERS, // can't just assume swap at end of list because + RC_DIRECT_BUFFER_START, + RC_DIRECT_BUFFER_END // of forced list submission before syncs } renderCommand_t; @@ -715,6 +717,8 @@ public: virtual void UnCrop(); virtual bool UploadImage( const char *imageName, const byte *data, int width, int height ); + virtual void DirectFrameBufferStart(); + virtual void DirectFrameBufferEnd(); public: // internal functions idRenderSystemLocal( void ); @@ -1209,6 +1213,11 @@ void R_FreeEntityDefFadedDecals( idRenderEntityLocal *def, int time ); void R_CreateLightDefFogPortals( idRenderLightLocal *ldef ); +// Framebuffer stuff +void R_InitFrameBuffer(); +void R_FrameBufferStart(); +void R_FrameBufferEnd(); + /* ============================================================ diff --git a/Projects/Android/jni/d3es-multithread-master/neo/renderer/tr_subview.cpp b/Projects/Android/jni/d3es-multithread-master/neo/renderer/tr_subview.cpp index 91f5fb5..a7f16a3 100644 --- a/Projects/Android/jni/d3es-multithread-master/neo/renderer/tr_subview.cpp +++ b/Projects/Android/jni/d3es-multithread-master/neo/renderer/tr_subview.cpp @@ -324,6 +324,8 @@ static void R_RemoteRender( drawSurf_t *surf, textureStage_t *stage ) { parms->superView = tr.viewDef; parms->subviewSurface = surf; + R_FrameBufferStart(); + // generate render commands for it R_RenderView(parms); @@ -335,6 +337,8 @@ static void R_RemoteRender( drawSurf_t *surf, textureStage_t *stage ) { tr.CaptureRenderToImage( stage->image->imgName ); tr.UnCrop(); + + R_FrameBufferEnd(); } /* @@ -376,6 +380,8 @@ void R_MirrorRender( drawSurf_t *surf, textureStage_t *stage, idScreenRect sciss // triangle culling order changes with mirroring parms->isMirror = ( ( (int)parms->isMirror ^ (int)tr.viewDef->isMirror ) != 0 ); + R_FrameBufferStart(); + // generate render commands for it R_RenderView( parms ); @@ -385,6 +391,8 @@ void R_MirrorRender( drawSurf_t *surf, textureStage_t *stage, idScreenRect sciss tr.CaptureRenderToImage( stage->image->imgName ); tr.UnCrop(); + + R_FrameBufferEnd(); } /* @@ -426,6 +434,8 @@ void R_XrayRender( drawSurf_t *surf, textureStage_t *stage, idScreenRect scissor // triangle culling order changes with mirroring parms->isMirror = ( ( (int)parms->isMirror ^ (int)tr.viewDef->isMirror ) != 0 ); + R_FrameBufferStart(); + // generate render commands for it R_RenderView( parms ); @@ -435,6 +445,8 @@ void R_XrayRender( drawSurf_t *surf, textureStage_t *stage, idScreenRect scissor tr.CaptureRenderToImage( stage->image->imgName ); tr.UnCrop(); + + R_FrameBufferEnd(); } /*