diff --git a/changelog.txt b/changelog.txt index a34b8dd..6ff26ae 100644 --- a/changelog.txt +++ b/changelog.txt @@ -71,6 +71,11 @@ add: r_khr_debug <0|1|2> (default: 2) decides whether to create an OpenGL debug r_khr_debug 0 = forced OFF r_khr_debug 1 = forced ON r_khr_debug 2 = only in debug builds + +add: r_rtColorFormat <0|1|2> (default: 0) selects the color format for render targets + r_rtColorFormat 0 = R8G8B8A8 + r_rtColorFormat 1 = R10G10B10A2 + r_rtColorFormat 2 = R16G16B16A16 add: r_mapBrightness now works on q3map2's external lightmap atlas images diff --git a/code/renderer/tr_backend_d3d11.cpp b/code/renderer/tr_backend_d3d11.cpp index 2f119d4..138ad21 100644 --- a/code/renderer/tr_backend_d3d11.cpp +++ b/code/renderer/tr_backend_d3d11.cpp @@ -278,6 +278,11 @@ struct Direct3D texEnv_t texEnv; float frameSeed[2]; + DXGI_FORMAT formatColorRT; + DXGI_FORMAT formatDepth; // float: DXGI_FORMAT_R32_TYPELESS + DXGI_FORMAT formatDepthRTV; // float: DXGI_FORMAT_R32_FLOAT + DXGI_FORMAT formatDepthView; // float: DXGI_FORMAT_D32_FLOAT + Texture textures[MAX_DRAWIMAGES]; int textureCount; @@ -540,6 +545,17 @@ static D3D11_BLEND GetDestinationBlend(unsigned int stateBits) } } +static DXGI_FORMAT GetRenderTargetColorFormat(int format) +{ + switch(format) + { + case RTCF_R8G8B8A8: return DXGI_FORMAT_R8G8B8A8_UNORM; + case RTCF_R10G10B10A2: return DXGI_FORMAT_R10G10B10A2_UNORM; + case RTCF_R16G16B16A16: return DXGI_FORMAT_R16G16B16A16_UNORM; + default: return DXGI_FORMAT_R8G8B8A8_UNORM; + } +} + static void ResetShaderData(ID3D11Resource* buffer, const void* data, size_t bytes) { D3D11_MAPPED_SUBRESOURCE ms; @@ -979,7 +995,9 @@ static void FindBestAvailableAA(DXGI_SAMPLE_DESC* sampleDesc) while(sampleDesc->Count > 0) { UINT levelCount = 0; - if(SUCCEEDED(d3d.device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, sampleDesc->Count, &levelCount)) && + if(SUCCEEDED(d3d.device->CheckMultisampleQualityLevels(d3d.formatColorRT, sampleDesc->Count, &levelCount)) && + levelCount > 0 && + SUCCEEDED(d3d.device->CheckMultisampleQualityLevels(d3d.formatDepth, sampleDesc->Count, &levelCount)) && levelCount > 0) break; @@ -1045,6 +1063,11 @@ create_device: } Check(hr, "D3D11CreateDeviceAndSwapChain"); + d3d.formatColorRT = GetRenderTargetColorFormat(r_rtColorFormat->integer); + d3d.formatDepth = DXGI_FORMAT_R24G8_TYPELESS; + d3d.formatDepthRTV = DXGI_FORMAT_R24_UNORM_X8_TYPELESS; + d3d.formatDepthView = DXGI_FORMAT_D24_UNORM_S8_UINT; + D3D11_TEXTURE2D_DESC readbackTexDesc; ZeroMemory(&readbackTexDesc, sizeof(readbackTexDesc)); readbackTexDesc.Width = glConfig.vidWidth; @@ -1083,7 +1106,7 @@ create_device: renderTargetTexDesc.Height = glConfig.vidHeight; renderTargetTexDesc.MipLevels = 1; renderTargetTexDesc.ArraySize = 1; - renderTargetTexDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + renderTargetTexDesc.Format = d3d.formatColorRT; renderTargetTexDesc.SampleDesc.Count = sampleDesc.Count; renderTargetTexDesc.SampleDesc.Quality = sampleDesc.Quality; renderTargetTexDesc.Usage = D3D11_USAGE_DEFAULT; @@ -1103,7 +1126,7 @@ create_device: renderTargetTexDesc.Height = glConfig.vidHeight; renderTargetTexDesc.MipLevels = 1; renderTargetTexDesc.ArraySize = 1; - renderTargetTexDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + renderTargetTexDesc.Format = d3d.formatColorRT; renderTargetTexDesc.SampleDesc.Count = 1; renderTargetTexDesc.SampleDesc.Quality = 0; renderTargetTexDesc.Usage = D3D11_USAGE_DEFAULT; @@ -1126,8 +1149,7 @@ create_device: depthStencilTexDesc.Height = glConfig.vidHeight; depthStencilTexDesc.MipLevels = 1; depthStencilTexDesc.ArraySize = 1; - //depthStencilTexDesc.Format = DXGI_FORMAT_R32_TYPELESS; // DXGI_FORMAT_R24G8_TYPELESS - depthStencilTexDesc.Format = DXGI_FORMAT_R24G8_TYPELESS; + depthStencilTexDesc.Format = d3d.formatDepth; depthStencilTexDesc.SampleDesc.Count = sampleDesc.Count; depthStencilTexDesc.SampleDesc.Quality = sampleDesc.Quality; depthStencilTexDesc.Usage = D3D11_USAGE_DEFAULT; @@ -1138,16 +1160,14 @@ create_device: D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc)); - //depthStencilViewDesc.Format = DXGI_FORMAT_D32_FLOAT; // DXGI_FORMAT_D24_UNORM_S8_UINT - depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + depthStencilViewDesc.Format = d3d.formatDepthView; depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; depthStencilViewDesc.Texture2D.MipSlice = 0; hr = d3d.device->CreateDepthStencilView(d3d.depthStencilTexture, &depthStencilViewDesc, &d3d.depthStencilView); CheckAndName(hr, "CreateDepthStencilView", d3d.depthStencilView, "depth stencil view"); ZeroMemory(&srvDesc, sizeof(srvDesc)); - //srvDesc.Format = DXGI_FORMAT_R32_FLOAT; // DXGI_FORMAT_R24_UNORM_X8_TYPELESS - srvDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS; + srvDesc.Format = d3d.formatDepthRTV; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS; D3D11_CreateShaderResourceView(d3d.depthStencilTexture, &srvDesc, &d3d.depthStencilShaderView, "depth stencil shader resource view"); @@ -1776,7 +1796,7 @@ static void GAL_EndFrame() } } - d3d.context->ResolveSubresource(d3d.resolveTexture, 0, d3d.renderTargetTextureMS, 0, DXGI_FORMAT_R8G8B8A8_UNORM); + d3d.context->ResolveSubresource(d3d.resolveTexture, 0, d3d.renderTargetTextureMS, 0, d3d.formatColorRT); d3d.postPSData.gamma = 1.0f / r_gamma->value; d3d.postPSData.brightness = r_brightness->value; d3d.postPSData.greyscale = r_greyscale->value; diff --git a/code/renderer/tr_backend_gl2.cpp b/code/renderer/tr_backend_gl2.cpp index c283e24..5c33b0d 100644 --- a/code/renderer/tr_backend_gl2.cpp +++ b/code/renderer/tr_backend_gl2.cpp @@ -398,6 +398,32 @@ static const char* GL2_GetFBOStatusString( GLenum status ) #undef CASE +void GL_GetRenderTargetFormat( GLenum* internalFormat, GLenum* format, GLenum* type, int cnq3Format ) +{ + switch( cnq3Format ) + { + case RTCF_R10G10B10A2: + *internalFormat = GL_RGB10_A2; + *format = GL_BGRA; + *type = GL_UNSIGNED_INT_2_10_10_10_REV; + break; + + case RTCF_R16G16B16A16: + *internalFormat = GL_RGBA16; + *format = GL_BGRA; + *type = GL_UNSIGNED_SHORT; + break; + + case RTCF_R8G8B8A8: + default: + *internalFormat = GL_RGBA8; + *format = GL_BGRA; + *type = GL_UNSIGNED_BYTE; + break; + } +} + + static qbool GL2_FBO_CreateSS( FrameBuffer& fb, qbool depthStencil ) { while ( glGetError() != GL_NO_ERROR ) {} // clear the error queue @@ -411,11 +437,13 @@ static qbool GL2_FBO_CreateSS( FrameBuffer& fb, qbool depthStencil ) GL(glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, glConfig.vidWidth, glConfig.vidHeight, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL )); } + GLenum internalFormat, format, type; + GL_GetRenderTargetFormat( &internalFormat, &format, &type, r_rtColorFormat->integer ); GL(glGenTextures( 1, &fb.color )); GL(glBindTexture( GL_TEXTURE_2D, fb.color )); GL(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR )); GL(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR )); - GL(glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, glConfig.vidWidth, glConfig.vidHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL )); + GL(glTexImage2D( GL_TEXTURE_2D, 0, internalFormat, glConfig.vidWidth, glConfig.vidHeight, 0, format, type, NULL )); GL(glGenFramebuffers( 1, &fb.fbo )); GL(glBindFramebuffer( GL_FRAMEBUFFER, fb.fbo )); @@ -446,9 +474,11 @@ static qbool GL2_FBO_CreateMS( FrameBuffer& fb ) GL(glGenFramebuffers( 1, &fb.fbo )); GL(glBindFramebuffer( GL_FRAMEBUFFER, fb.fbo )); + GLenum internalFormat, format, type; + GL_GetRenderTargetFormat( &internalFormat, &format, &type, r_rtColorFormat->integer ); GL(glGenRenderbuffers( 1, &fb.color )); GL(glBindRenderbuffer( GL_RENDERBUFFER, fb.color )); - GL(glRenderbufferStorageMultisample( GL_RENDERBUFFER, r_msaa->integer, GL_RGBA8, glConfig.vidWidth, glConfig.vidHeight )); + GL(glRenderbufferStorageMultisample( GL_RENDERBUFFER, r_msaa->integer, internalFormat, glConfig.vidWidth, glConfig.vidHeight )); GL(glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fb.color )); GL(glGenRenderbuffers( 1, &fb.depthStencil )); diff --git a/code/renderer/tr_backend_gl3.cpp b/code/renderer/tr_backend_gl3.cpp index 2cbe137..5e6979f 100644 --- a/code/renderer/tr_backend_gl3.cpp +++ b/code/renderer/tr_backend_gl3.cpp @@ -823,6 +823,8 @@ static qbool CreateComputeProgram(Program* prog, const char* cs, const char* deb return qfalse; } +extern void GL_GetRenderTargetFormat(GLenum* internalFormat, GLenum* format, GLenum* type, int cnq3Format); + static void FBO_CreateSS(FrameBuffer* fb, qbool color, qbool depthStencil, const char* name) { if(depthStencil) @@ -837,11 +839,13 @@ static void FBO_CreateSS(FrameBuffer* fb, qbool color, qbool depthStencil, const if(color) { + GLenum internalFormat, format, type; + GL_GetRenderTargetFormat(&internalFormat, &format, &type, r_rtColorFormat->integer); glGenTextures(1, &fb->color); glBindTexture(GL_TEXTURE_2D, fb->color); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, glConfig.vidWidth, glConfig.vidHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, glConfig.vidWidth, glConfig.vidHeight, 0, format, type, NULL); SetDebugName(GL_TEXTURE, fb->color, va("%s color attachment 0", name)); } @@ -875,9 +879,11 @@ static void FBO_CreateMS(FrameBuffer* fb, const char* name) glGenFramebuffers(1, &fb->fbo); glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo); + GLenum internalFormat, format, type; + GL_GetRenderTargetFormat(&internalFormat, &format, &type, r_rtColorFormat->integer); glGenRenderbuffers(1, &fb->color); glBindRenderbuffer(GL_RENDERBUFFER, fb->color); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, r_msaa->integer, GL_RGBA8, glConfig.vidWidth, glConfig.vidHeight); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, r_msaa->integer, internalFormat, glConfig.vidWidth, glConfig.vidHeight); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fb->color); SetDebugName(GL_RENDERBUFFER, fb->color, va("%s color attachment 0", name)); diff --git a/code/renderer/tr_help.h b/code/renderer/tr_help.h index 78bdcc6..210e892 100644 --- a/code/renderer/tr_help.h +++ b/code/renderer/tr_help.h @@ -151,3 +151,8 @@ S_COLOR_VAL " T2 " S_COLOR_HELP "= Tent 2 (1/3 2/3, same as the CPU version) "dithering noise strength\n" \ "The dithering on/off switch is " S_COLOR_CVAR "r_dither" S_COLOR_HELP "." +#define help_r_rtColorFormat \ +"render target color format\n" \ +S_COLOR_VAL " 0 " S_COLOR_HELP "= R8G8B8A8\n" \ +S_COLOR_VAL " 1 " S_COLOR_HELP "= R10G10B10A2\n" \ +S_COLOR_VAL " 2 " S_COLOR_HELP "= R16G16B16A16" diff --git a/code/renderer/tr_init.cpp b/code/renderer/tr_init.cpp index 9dcb585..6666e73 100644 --- a/code/renderer/tr_init.cpp +++ b/code/renderer/tr_init.cpp @@ -67,6 +67,7 @@ cvar_t *r_softSprites; cvar_t *r_gpuMipGen; cvar_t *r_alphaToCoverage; cvar_t *r_dither; +cvar_t *r_rtColorFormat; cvar_t *r_mipGenFilter; cvar_t *r_mipGenGamma; @@ -391,6 +392,7 @@ static const cvarTableItem_t r_cvars[] = { &r_gpuMipGen, "r_gpuMipGen", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_gpuMipGen }, { &r_alphaToCoverage, "r_alphaToCoverage", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_alphaToCoverage }, { &r_dither, "r_dither", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_dither }, + { &r_rtColorFormat, "r_rtColorFormat", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", XSTRING(RTCF_MAX), help_r_rtColorFormat }, // // latched variables that can only change over a restart diff --git a/code/renderer/tr_local.h b/code/renderer/tr_local.h index 0b581d9..142af98 100644 --- a/code/renderer/tr_local.h +++ b/code/renderer/tr_local.h @@ -930,6 +930,12 @@ extern trGlobals_t tr; #define BLITMODE_STRETCHED 2 // dumb stretch, takes the full screen #define BLITMODE_MAX 2 +// r_rtColorFormat +#define RTCF_R8G8B8A8 0 +#define RTCF_R10G10B10A2 1 +#define RTCF_R16G16B16A16 2 +#define RTCF_MAX 2 + // r_gl3_geoStream #define GL3MAP_AUTO 0 #define GL3MAP_SUBDATA 1 @@ -979,6 +985,7 @@ extern cvar_t *r_softSprites; // draws certain surfaces as depth particles extern cvar_t *r_gpuMipGen; // uses GPU-side mip-map generation extern cvar_t *r_alphaToCoverage; // enables A2C on alpha-tested surfaces extern cvar_t *r_dither; // enables dithering +extern cvar_t *r_rtColorFormat; // see RTCF_* extern cvar_t *r_mipGenFilter; // if the string is invalid, Lanczos 4 is used extern cvar_t *r_mipGenGamma; // what gamma-space do we consider the textures to be in