mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2024-11-23 04:12:42 +00:00
added r_mapGreyscale and r_mapGreyscaleCTF
This commit is contained in:
parent
178d91b000
commit
8c32b986f6
19 changed files with 458 additions and 91 deletions
|
@ -4,6 +4,15 @@ See the end of this file for known issues.
|
|||
|
||||
DD Mmm 20 - 1.53
|
||||
|
||||
add: r_mapGreyscale <0.0 to 1.0> (default: 0) controls the map's desaturation level
|
||||
r_mapGreyscale 0 = full color (nothing done)
|
||||
r_mapGreyscale 1 = completely monochrome
|
||||
|
||||
add: r_mapGreyscaleCTF <0.0 to 1.0> (default: 0) controls the CTF map surfaces' desaturation level
|
||||
r_mapGreyscaleCTF 0 = full color (nothing done)
|
||||
r_mapGreyscaleCTF 1 = completely monochrome
|
||||
it applies to the red/blue color-coded surfaces of popular CTF/NTF maps
|
||||
|
||||
add: net_proxy <ip> (default: "") is the proxy server to use when establishing client connections
|
||||
|
||||
add: /waitms <milliseconds> to delay command executions by the specified number of milliseconds
|
||||
|
|
|
@ -20,6 +20,8 @@ along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
|||
*/
|
||||
// dynamic light vertex and pixel shaders
|
||||
|
||||
#include "shared.hlsli"
|
||||
|
||||
cbuffer VertexShaderBuffer
|
||||
{
|
||||
matrix modelViewMatrix;
|
||||
|
@ -67,7 +69,8 @@ cbuffer PixelShaderBuffer
|
|||
float lightRadius;
|
||||
float opaque;
|
||||
float intensity;
|
||||
float dummy[2];
|
||||
float greyscale;
|
||||
float dummy;
|
||||
};
|
||||
|
||||
Texture2D texture0 : register(t0);
|
||||
|
@ -80,7 +83,7 @@ float BezierEase(float t)
|
|||
|
||||
float4 ps_main(VOut input) : SV_TARGET
|
||||
{
|
||||
float4 base = texture0.Sample(sampler0, input.texCoords);
|
||||
float4 base = MakeGreyscale(texture0.Sample(sampler0, input.texCoords), greyscale);
|
||||
float3 nL = normalize(input.osLightVec); // normalized object-space light vector
|
||||
float3 nV = normalize(input.osEyeVec); // normalized object-space view vector
|
||||
float3 nN = input.normal; // normalized object-space normal vector
|
||||
|
|
|
@ -20,6 +20,8 @@ along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
|||
*/
|
||||
// generic vertex and pixel shaders
|
||||
|
||||
#include "shared.hlsli"
|
||||
|
||||
cbuffer VertexShaderBuffer
|
||||
{
|
||||
matrix modelViewMatrix;
|
||||
|
@ -62,7 +64,8 @@ cbuffer PixelShaderBuffer
|
|||
{
|
||||
uint alphaTest;
|
||||
uint texEnv;
|
||||
float2 seed;
|
||||
float seed;
|
||||
float greyscale;
|
||||
float invGamma;
|
||||
float invBrightness;
|
||||
float noiseScale;
|
||||
|
@ -153,5 +156,5 @@ float4 ps_main(VOut input) : SV_Target0
|
|||
discard;
|
||||
#endif
|
||||
|
||||
return r;
|
||||
return MakeGreyscale(r, greyscale);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
|||
*/
|
||||
// post-processing vertex and pixel shaders
|
||||
|
||||
#include "shared.hlsli"
|
||||
|
||||
// X3571: pow(f, e) won't work if f is negative
|
||||
#pragma warning(disable : 3571)
|
||||
|
||||
|
@ -65,8 +67,6 @@ float4 ps_main(VOut input) : SV_TARGET
|
|||
{
|
||||
float3 base = texture0.Sample(sampler0, input.texCoords).rgb;
|
||||
float3 gc = pow(base, gamma) * brightness;
|
||||
float grey = 0.299 * gc.r + 0.587 * gc.g + 0.114 * gc.b;
|
||||
float3 result = lerp(gc, float3(grey, grey, grey), greyscale);
|
||||
|
||||
return float4(result.rgb, 1.0);
|
||||
return MakeGreyscale(float4(gc.rgb, 1.0), greyscale);
|
||||
}
|
||||
|
|
29
code/renderer/hlsl/shared.hlsli
Normal file
29
code/renderer/hlsl/shared.hlsli
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 2022 Gian 'myT' Schellenbaum
|
||||
|
||||
This file is part of Challenge Quake 3 (CNQ3).
|
||||
|
||||
Challenge Quake 3 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.
|
||||
|
||||
Challenge Quake 3 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 Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
||||
===========================================================================
|
||||
*/
|
||||
// shared functions
|
||||
|
||||
float4 MakeGreyscale(float4 input, float amount)
|
||||
{
|
||||
float grey = dot(input.rgb, float3(0.299, 0.587, 0.114));
|
||||
float4 result = lerp(input, float4(grey, grey, grey, input.a), amount);
|
||||
|
||||
return result;
|
||||
}
|
|
@ -20,6 +20,8 @@ along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
|
|||
*/
|
||||
// depth sprite vertex and pixel shaders
|
||||
|
||||
#include "shared.hlsli"
|
||||
|
||||
cbuffer VertexShaderBuffer
|
||||
{
|
||||
matrix modelViewMatrix;
|
||||
|
@ -64,7 +66,7 @@ cbuffer PixelShaderBuffer
|
|||
uint alphaTest;
|
||||
float distance;
|
||||
float offset;
|
||||
float dummy;
|
||||
float greyscale;
|
||||
float4 colorScale;
|
||||
float4 colorBias;
|
||||
};
|
||||
|
@ -115,5 +117,5 @@ float4 ps_main(VOut input, uint sampleIndex : SV_SampleIndex) : SV_TARGET
|
|||
float scale = Contrast((depthS - depthP) * distance, 2.0);
|
||||
float4 r2 = lerp(r * colorScale + colorBias, r, scale);
|
||||
|
||||
return r2;
|
||||
return MakeGreyscale(r2, greyscale);
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ static const void* RB_StretchPic( const void* data )
|
|||
}
|
||||
backEnd.currentEntity = &backEnd.entity2D;
|
||||
RB_BeginSurface( shader, 0 );
|
||||
tess.greyscale = 0.0f;
|
||||
}
|
||||
|
||||
RB_CHECKOVERFLOW( 4, 6 );
|
||||
|
@ -135,6 +136,7 @@ static const void* RB_Triangle( const void* data )
|
|||
}
|
||||
backEnd.currentEntity = &backEnd.entity2D;
|
||||
RB_BeginSurface( shader, 0 );
|
||||
tess.greyscale = 0.0f;
|
||||
}
|
||||
|
||||
RB_CHECKOVERFLOW( 3, 3 );
|
||||
|
@ -303,6 +305,7 @@ static void RB_RenderDrawSurfList( const drawSurf_t* drawSurfs, int numDrawSurfs
|
|||
RB_EndSurface();
|
||||
RB_BeginSurface( shader, fogNum );
|
||||
tess.depthFade = shader->dfType;
|
||||
tess.greyscale = drawSurf->greyscale;
|
||||
}
|
||||
|
||||
sort = drawSurf->sort;
|
||||
|
@ -419,6 +422,7 @@ static void RB_RenderLitSurfList( dlight_t* dl, qbool opaque )
|
|||
if (shaderPrev)
|
||||
RB_EndSurface();
|
||||
RB_BeginSurface( shader, fogNum );
|
||||
tess.greyscale = litSurf->greyscale;
|
||||
|
||||
// stage index is guaranteed valid by R_AddLitSurface
|
||||
const int stageIndex = shader->lightingStages[ST_DIFFUSE];
|
||||
|
|
|
@ -181,7 +181,8 @@ struct GenericPSData
|
|||
{
|
||||
uint32_t alphaTest; // AlphaTest enum
|
||||
uint32_t texEnv; // texEnv_t enum
|
||||
float seed[2];
|
||||
float seed;
|
||||
float greyscale;
|
||||
float invGamma;
|
||||
float invBrightness;
|
||||
float noiseScale;
|
||||
|
@ -200,7 +201,7 @@ struct DepthFadePSData
|
|||
uint32_t alphaTest; // AlphaTest enum
|
||||
float distance;
|
||||
float offset;
|
||||
float dummy;
|
||||
float greyscale;
|
||||
float scale[4];
|
||||
float bias[4];
|
||||
};
|
||||
|
@ -220,7 +221,8 @@ struct DynamicLightPSData
|
|||
float lightRadius;
|
||||
float opaque;
|
||||
float intensity;
|
||||
float dummy[2];
|
||||
float greyscale;
|
||||
float dummy;
|
||||
};
|
||||
|
||||
struct PostVSData
|
||||
|
@ -332,7 +334,7 @@ struct Direct3D
|
|||
float lightRadius;
|
||||
AlphaTest alphaTest;
|
||||
texEnv_t texEnv;
|
||||
float frameSeed[2];
|
||||
float frameSeed;
|
||||
|
||||
DXGI_FORMAT formatColorRT;
|
||||
DXGI_FORMAT formatDepth; // float: DXGI_FORMAT_R32_TYPELESS
|
||||
|
@ -740,8 +742,8 @@ static void UploadPendingShaderData()
|
|||
memcpy(vsData.clipPlane, d3d.clipPlane, sizeof(vsData.clipPlane));
|
||||
psData.alphaTest = d3d.alphaTest;
|
||||
psData.texEnv = d3d.texEnv;
|
||||
psData.seed[0] = d3d.frameSeed[0];
|
||||
psData.seed[1] = d3d.frameSeed[1];
|
||||
psData.seed = d3d.frameSeed;
|
||||
psData.greyscale = tess.greyscale;
|
||||
psData.invGamma = 1.0f / r_gamma->value;
|
||||
psData.invBrightness = 1.0f / r_brightness->value;
|
||||
psData.noiseScale = backEnd.projection2D ? 0.0f : r_ditherStrength->value;
|
||||
|
@ -761,6 +763,7 @@ static void UploadPendingShaderData()
|
|||
memcpy(psData.bias, r_depthFadeBias[tess.shader->dfType], sizeof(psData.bias));
|
||||
psData.distance = tess.shader->dfInvDist;
|
||||
psData.offset = tess.shader->dfBias;
|
||||
psData.greyscale = tess.greyscale;
|
||||
ResetShaderData(pipeline->vertexBuffer, &vsData, sizeof(vsData));
|
||||
ResetShaderData(pipeline->pixelBuffer, &psData, sizeof(psData));
|
||||
}
|
||||
|
@ -777,6 +780,7 @@ static void UploadPendingShaderData()
|
|||
psData.lightRadius = d3d.lightRadius;
|
||||
psData.opaque = backEnd.dlOpaque ? 1.0f : 0.0f;
|
||||
psData.intensity = backEnd.dlIntensity;
|
||||
psData.greyscale = tess.greyscale;
|
||||
ResetShaderData(pipeline->vertexBuffer, &vsData, sizeof(vsData));
|
||||
ResetShaderData(pipeline->pixelBuffer, &psData, sizeof(psData));
|
||||
}
|
||||
|
@ -2051,8 +2055,7 @@ static void GAL_BeginFrame()
|
|||
{
|
||||
BeginQueries();
|
||||
|
||||
d3d.frameSeed[0] = (float)rand() / (float)RAND_MAX;
|
||||
d3d.frameSeed[1] = (float)rand() / (float)RAND_MAX;
|
||||
d3d.frameSeed = (float)rand() / (float)RAND_MAX;
|
||||
|
||||
const FLOAT clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
const FLOAT clearColorDebug[4] = { 1.0f, 0.0f, 0.5f, 1.0f };
|
||||
|
|
|
@ -74,14 +74,62 @@ static void GL_Program( const GLSL_Program& prog )
|
|||
}
|
||||
}
|
||||
|
||||
static void GL_Program()
|
||||
{
|
||||
if ( progCurrent != 0 ) {
|
||||
glUseProgram(0);
|
||||
progCurrent = 0;
|
||||
backEnd.pc3D[ RB_SHADER_CHANGES ]++;
|
||||
}
|
||||
}
|
||||
|
||||
static GLSL_Program genericProg;
|
||||
|
||||
struct GLSL_GenericProgramAttribs {
|
||||
// pixel shader:
|
||||
GLint texture1; // 2D texture
|
||||
GLint texture2; // 2D texture
|
||||
GLint texEnv; // 1i
|
||||
GLint greyscale; // 1f
|
||||
};
|
||||
|
||||
static GLSL_GenericProgramAttribs genericProgAttribs;
|
||||
|
||||
static const char* sharedFS =
|
||||
"vec4 MakeGreyscale(vec4 color, float amount)\n"
|
||||
"{\n"
|
||||
" float grey = dot(color.rgb, vec3(0.299, 0.587, 0.114));\n"
|
||||
" vec4 result = mix(color, vec4(grey, grey, grey, color.a), amount);\n"
|
||||
" return result;\n"
|
||||
"}\n"
|
||||
"\n";
|
||||
|
||||
static const char* genericVS =
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = ftransform();\n"
|
||||
" gl_TexCoord[0] = gl_MultiTexCoord0;\n"
|
||||
" gl_TexCoord[1] = gl_MultiTexCoord1;\n"
|
||||
" gl_TexCoord[2] = gl_Color;\n"
|
||||
"}\n";
|
||||
|
||||
static const char* genericFS =
|
||||
"uniform sampler2D texture1;\n"
|
||||
"uniform sampler2D texture2;\n"
|
||||
"uniform int texEnv;\n"
|
||||
"uniform float greyscale;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec4 p = texture2D(texture1, gl_TexCoord[0].xy);\n"
|
||||
" vec4 s = texture2D(texture2, gl_TexCoord[1].xy);\n"
|
||||
" vec4 r;\n"
|
||||
" vec4 c = gl_TexCoord[2];"
|
||||
" if(texEnv == 1)\n"
|
||||
" r = c * s * p;\n"
|
||||
" else if(texEnv == 2)\n"
|
||||
" r = s; // use input.color or not?\n"
|
||||
" else if(texEnv == 3)\n"
|
||||
" r = c * vec4(p.rgb * (1.0 - s.a) + s.rgb * s.a, p.a);\n"
|
||||
" else if(texEnv == 4)\n"
|
||||
" r = c * vec4(p.rgb + s.rgb, p.a * s.a);\n"
|
||||
" else // texEnv == 0\n"
|
||||
" r = c * p;\n"
|
||||
"\n"
|
||||
" gl_FragColor = MakeGreyscale(r, greyscale);\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
static GLSL_Program dynLightProg;
|
||||
|
@ -95,6 +143,7 @@ struct GLSL_DynLightProgramAttribs {
|
|||
GLint texture; // 2D texture
|
||||
GLint lightColorRadius; // 4f, w = 1 / (r^2)
|
||||
GLint opaqueIntensity; // 2f
|
||||
GLint greyscale; // 1f
|
||||
};
|
||||
|
||||
static GLSL_DynLightProgramAttribs dynLightProgAttribs;
|
||||
|
@ -145,6 +194,8 @@ static void DrawDynamicLight()
|
|||
GL_SelectTexture( 0 );
|
||||
R_BindAnimatedImage( &pStage->bundle );
|
||||
|
||||
glUniform1f( dynLightProgAttribs.greyscale, tess.greyscale );
|
||||
|
||||
glDrawElements( GL_TRIANGLES, tess.dlNumIndexes, GL_INDEX_TYPE, tess.dlIndexes );
|
||||
backEnd.pc3D[ RB_DRAW_CALLS ]++;
|
||||
|
||||
|
@ -182,7 +233,11 @@ static qbool GL2_StageIterator_MultitextureStage( int stage )
|
|||
|
||||
static void DrawGeneric()
|
||||
{
|
||||
GL_Program();
|
||||
GL_Program( genericProg );
|
||||
|
||||
glUniform1i( genericProgAttribs.texture1, 0 );
|
||||
glUniform1i( genericProgAttribs.texture2, 1 );
|
||||
glUniform1f( genericProgAttribs.greyscale, tess.greyscale );
|
||||
|
||||
GL_Cull( tess.shader->cullType );
|
||||
|
||||
|
@ -212,12 +267,14 @@ static void DrawGeneric()
|
|||
if ( pStage->mtStages ) {
|
||||
// we can't really cope with massive collapses, so
|
||||
assert( pStage->mtStages == 1 );
|
||||
glUniform1i( genericProgAttribs.texEnv, tess.xstages[stage + 1]->mtEnv );
|
||||
if ( GL2_StageIterator_MultitextureStage( stage + 1 ) )
|
||||
break;
|
||||
stage += pStage->mtStages;
|
||||
continue;
|
||||
}
|
||||
|
||||
glUniform1i( genericProgAttribs.texEnv, TE_DISABLED );
|
||||
glDrawElements( GL_TRIANGLES, tess.numIndexes, GL_INDEX_TYPE, tess.indexes );
|
||||
backEnd.pc3D[ RB_DRAW_CALLS ]++;
|
||||
}
|
||||
|
@ -243,8 +300,14 @@ static void GAL_Draw( drawType_t type )
|
|||
|
||||
static qbool GL2_CreateShader( GLuint* shaderPtr, GLenum shaderType, const char* shaderSource )
|
||||
{
|
||||
const char* const sourceArray[] =
|
||||
{
|
||||
shaderType == GL_FRAGMENT_SHADER ? sharedFS : "",
|
||||
shaderSource
|
||||
};
|
||||
|
||||
GLuint shader = glCreateShader( shaderType );
|
||||
glShaderSource( shader, 1, &shaderSource, NULL );
|
||||
glShaderSource( shader, ARRAY_LEN(sourceArray), sourceArray, NULL );
|
||||
glCompileShader( shader );
|
||||
|
||||
GLint result = GL_FALSE;
|
||||
|
@ -278,7 +341,19 @@ static qbool GL2_CreateProgram( GLSL_Program& prog, const char* vs, const char*
|
|||
glAttachShader( prog.p, prog.fs );
|
||||
glLinkProgram( prog.p );
|
||||
|
||||
return qtrue;
|
||||
GLint result = GL_FALSE;
|
||||
glGetProgramiv( prog.p, GL_LINK_STATUS, &result );
|
||||
if ( result == GL_TRUE )
|
||||
return qtrue;
|
||||
|
||||
GLint logLength = 0;
|
||||
glGetProgramiv( prog.p, GL_INFO_LOG_LENGTH, &logLength );
|
||||
|
||||
static char log[4096]; // I've seen logs over 3 KB in size.
|
||||
glGetProgramInfoLog( prog.p, sizeof(log), NULL, log );
|
||||
ri.Printf( PRINT_ERROR, "Program link failed: %s\n", log );
|
||||
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
|
||||
|
@ -307,6 +382,7 @@ static const char* dynLightFS =
|
|||
"uniform sampler2D texture;\n"
|
||||
"uniform vec4 lightColorRadius;\n" // w = 1 / (r^2)
|
||||
"uniform vec2 opaqueIntensity;\n"
|
||||
"uniform float greyscale;\n"
|
||||
"varying vec4 L;\n" // object-space light vector
|
||||
"varying vec4 V;\n" // object-space view vector
|
||||
"varying vec3 nN;\n" // normalized object-space normal vector
|
||||
|
@ -318,7 +394,7 @@ static const char* dynLightFS =
|
|||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec4 base = texture2D(texture, gl_TexCoord[0].xy);\n"
|
||||
" vec4 base = MakeGreyscale(texture2D(texture, gl_TexCoord[0].xy), greyscale);\n"
|
||||
" vec3 nL = normalize(L.xyz);\n" // normalized light vector
|
||||
" vec3 nV = normalize(V.xyz);\n" // normalized view vector
|
||||
// light intensity
|
||||
|
@ -722,9 +798,8 @@ static const char* greyscaleFS =
|
|||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec3 base = texture2D(texture, gl_TexCoord[0].xy).rgb;\n"
|
||||
" vec3 grey = vec3(0.299 * base.r + 0.587 * base.g + 0.114 * base.b);\n"
|
||||
" gl_FragColor = vec4(mix(base, grey, greyscale), 1.0);\n"
|
||||
" vec4 final = MakeGreyscale(texture2D(texture, gl_TexCoord[0].xy), greyscale);\n"
|
||||
" gl_FragColor = vec4(final.rgb, 1.0);\n"
|
||||
"}\n"
|
||||
"";
|
||||
|
||||
|
@ -736,6 +811,15 @@ static qbool GL2_Init()
|
|||
return qfalse;
|
||||
}
|
||||
|
||||
if ( !GL2_CreateProgram( genericProg, genericVS, genericFS ) ) {
|
||||
ri.Error( PRINT_ERROR, "Failed to compile generic shaders\n" );
|
||||
return qfalse;
|
||||
}
|
||||
genericProgAttribs.texture1 = glGetUniformLocation( genericProg.p, "texture1" );
|
||||
genericProgAttribs.texture2 = glGetUniformLocation( genericProg.p, "texture2" );
|
||||
genericProgAttribs.texEnv = glGetUniformLocation( genericProg.p, "texEnv" );
|
||||
genericProgAttribs.greyscale = glGetUniformLocation( genericProg.p, "greyscale" );
|
||||
|
||||
if ( !GL2_CreateProgram( dynLightProg, dynLightVS, dynLightFS ) ) {
|
||||
ri.Printf( PRINT_ERROR, "Failed to compile dynamic light shaders\n" );
|
||||
return qfalse;
|
||||
|
@ -745,6 +829,7 @@ static qbool GL2_Init()
|
|||
dynLightProgAttribs.texture = glGetUniformLocation( dynLightProg.p, "texture" );
|
||||
dynLightProgAttribs.lightColorRadius = glGetUniformLocation( dynLightProg.p, "lightColorRadius" );
|
||||
dynLightProgAttribs.opaqueIntensity = glGetUniformLocation( dynLightProg.p, "opaqueIntensity" );
|
||||
dynLightProgAttribs.greyscale = glGetUniformLocation( dynLightProg.p, "greyscale" );
|
||||
|
||||
if ( !GL2_CreateProgram( gammaProg, gammaVS, gammaFS ) ) {
|
||||
ri.Printf( PRINT_ERROR, "Failed to compile gamma correction shaders\n" );
|
||||
|
@ -771,8 +856,6 @@ static void GL2_BeginFrame()
|
|||
GL2_FBO_Bind( frameBufferMain );
|
||||
else
|
||||
GL2_FBO_Bind();
|
||||
|
||||
GL_Program();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1270,8 +1353,8 @@ static GLenum GL_TextureFormat( textureFormat_t f )
|
|||
|
||||
static void GL_CheckErrors()
|
||||
{
|
||||
int err = glGetError();
|
||||
if ((err == GL_NO_ERROR) || r_ignoreGLErrors->integer)
|
||||
const int err = glGetError();
|
||||
if (err == GL_NO_ERROR || r_ignoreGLErrors->integer)
|
||||
return;
|
||||
|
||||
char s[64];
|
||||
|
@ -1470,12 +1553,6 @@ static void InitGLInfo()
|
|||
}
|
||||
|
||||
|
||||
static void InitExtensions()
|
||||
{
|
||||
GL2_Init();
|
||||
}
|
||||
|
||||
|
||||
static void GAL_ReadPixels( int x, int y, int w, int h, int alignment, colorSpace_t colorSpace, void* out )
|
||||
{
|
||||
const GLenum format = colorSpace == CS_BGR ? GL_BGR : GL_RGBA;
|
||||
|
@ -1543,7 +1620,7 @@ static qbool GAL_Init()
|
|||
ri.Error( ERR_FATAL, "Need at least OpenGL 3.0 or GL_ARB_framebuffer_object\n" );
|
||||
InitGLConfig();
|
||||
InitGLInfo();
|
||||
InitExtensions();
|
||||
GL2_Init();
|
||||
|
||||
// apply the current V-Sync option after the first rendered frame
|
||||
r_swapInterval->modified = qtrue;
|
||||
|
@ -1551,8 +1628,8 @@ static qbool GAL_Init()
|
|||
|
||||
GL_SetDefaultState();
|
||||
|
||||
int err = glGetError();
|
||||
if (err != GL_NO_ERROR)
|
||||
const int err = glGetError();
|
||||
if (err != GL_NO_ERROR && !r_ignoreGLErrors->integer)
|
||||
ri.Printf( PRINT_ALL, "glGetError() = 0x%x\n", err );
|
||||
|
||||
return qtrue;
|
||||
|
|
|
@ -151,6 +151,7 @@ enum GenericUniform
|
|||
GU_PROJECTION,
|
||||
GU_CLIP_PLANE,
|
||||
GU_ALPHA_TEX,
|
||||
GU_GREYSCALE,
|
||||
GU_GAMMA_BRIGHT_NOISE_SEED, // only defined when dithering is enabled
|
||||
GU_A2C_ALPHA_BOOST, // only defined when alpha to coverage is enabled
|
||||
GU_COUNT
|
||||
|
@ -166,6 +167,7 @@ enum DynamicLightUniform
|
|||
DU_LIGHT_COLOR_RADIUS,
|
||||
DU_OPAQUE,
|
||||
DU_INTENSITY,
|
||||
DU_GREYSCALE,
|
||||
DU_COUNT
|
||||
};
|
||||
|
||||
|
@ -178,6 +180,7 @@ enum SoftSpriteUniform
|
|||
SU_DIST_OFFSET,
|
||||
SU_COLOR_SCALE,
|
||||
SU_COLOR_BIAS,
|
||||
SU_GREYSCALE,
|
||||
SU_COUNT
|
||||
};
|
||||
|
||||
|
@ -244,6 +247,7 @@ struct OpenGL3
|
|||
float depthFadeBias[4];
|
||||
float depthFadeDist;
|
||||
float depthFadeOffset;
|
||||
float greyscale;
|
||||
|
||||
ArrayBuffer arrayBuffers[VB_COUNT];
|
||||
ArrayBuffer indexBuffer;
|
||||
|
@ -284,6 +288,15 @@ struct OpenGL3
|
|||
static OpenGL3 gl;
|
||||
|
||||
|
||||
static const char* shared_fs =
|
||||
"vec4 MakeGreyscale(vec4 color, float amount)\n"
|
||||
"{\n"
|
||||
" float grey = dot(color.rgb, vec3(0.299, 0.587, 0.114));\n"
|
||||
" vec4 result = mix(color, vec4(grey, grey, grey, color.a), amount);\n"
|
||||
" return result;\n"
|
||||
"}\n"
|
||||
"\n";
|
||||
|
||||
static const char* generic_vs =
|
||||
// a good way to test warning reports with r_verbose 1
|
||||
//"#extension DOESNTEXISTLOL:warn\n"
|
||||
|
@ -318,6 +331,7 @@ static const char* generic_fs =
|
|||
"uniform uvec2 alphaTex;\n"
|
||||
"#define alphaTest alphaTex.x\n"
|
||||
"#define texEnv alphaTex.y\n"
|
||||
"uniform float greyscale;\n"
|
||||
"#if CNQ3_DITHER\n"
|
||||
"uniform vec4 gammaBrightNoiseSeed;\n"
|
||||
"#define invGamma gammaBrightNoiseSeed.x\n"
|
||||
|
@ -406,7 +420,7 @@ static const char* generic_fs =
|
|||
" discard;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
" fragColor = r;\n"
|
||||
" fragColor = MakeGreyscale(r, greyscale);\n"
|
||||
"}\n";
|
||||
|
||||
static const char* dl_vs =
|
||||
|
@ -442,6 +456,7 @@ static const char* dl_fs =
|
|||
"uniform vec4 lightColorRadius;\n"
|
||||
"uniform float opaque;\n"
|
||||
"uniform float intensity;\n"
|
||||
"uniform float greyscale;\n"
|
||||
"\n"
|
||||
"in vec3 normalFS;\n"
|
||||
"in vec2 texCoords1FS;\n"
|
||||
|
@ -457,7 +472,7 @@ static const char* dl_fs =
|
|||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec4 base = texture2D(texture1, texCoords1FS);\n"
|
||||
" vec4 base = MakeGreyscale(texture2D(texture1, texCoords1FS), greyscale);\n"
|
||||
" vec3 nL = normalize(L);\n"
|
||||
" vec3 nV = normalize(V);\n"
|
||||
"\n"
|
||||
|
@ -474,7 +489,8 @@ static const char* dl_fs =
|
|||
" vec3 color = (base.rgb * vec3(diffuse) + vec3(spec)) * intens * intensity;\n"
|
||||
" float alpha = mix(opaque, 1.0, base.a);\n"
|
||||
"\n"
|
||||
" fragColor = vec4(color.rgb * alpha, alpha);\n"
|
||||
" vec4 r = vec4(color.rgb * alpha, alpha);\n"
|
||||
" fragColor = r;\n"
|
||||
"}\n";
|
||||
|
||||
static const char* sprite_vs =
|
||||
|
@ -514,6 +530,7 @@ static const char* sprite_fs =
|
|||
"uniform vec2 distOffset;\n"
|
||||
"uniform vec4 colorScale;\n"
|
||||
"uniform vec4 colorBias;\n"
|
||||
"uniform float greyscale;\n"
|
||||
"#define distance distOffset.x\n"
|
||||
"#define offset distOffset.y\n"
|
||||
"\n"
|
||||
|
@ -557,7 +574,7 @@ static const char* sprite_fs =
|
|||
" float depthP = depthVS - offset;\n"
|
||||
" float scale = Contrast((depthS - depthP) * distance, 2.0);\n"
|
||||
" vec4 r2 = mix(r * colorScale + colorBias, r, scale);\n"
|
||||
" fragColor = r2;\n"
|
||||
" fragColor = MakeGreyscale(r2, greyscale);\n"
|
||||
"}\n";
|
||||
|
||||
static const char* post_vs =
|
||||
|
@ -591,9 +608,7 @@ static const char* post_fs =
|
|||
"{\n"
|
||||
" vec3 base = texture(texture1, texCoords1FS).rgb;\n"
|
||||
" vec3 gc = pow(base, vec3(gamma)) * brightness;\n"
|
||||
" float grey = 0.299 * gc.r + 0.587 * gc.g + 0.114 * gc.b;\n"
|
||||
" vec3 result = mix(gc, vec3(grey, grey, grey), greyscale);\n"
|
||||
" fragColor = vec4(result.rgb, 1.0);\n"
|
||||
" fragColor = MakeGreyscale(vec4(gc.rgb, 1.0), greyscale);\n"
|
||||
"}\n";
|
||||
|
||||
static const char* gammaToLinear_cs =
|
||||
|
@ -796,6 +811,7 @@ static qbool CreateShader(GLuint* shaderPtr, PipelineId pipelineId, GLenum shade
|
|||
enableA2C ? "#define CNQ3_A2C 1\n" : "#define CNQ3_A2C 0\n",
|
||||
enableDithering ? "#define CNQ3_DITHER 1\n" : "#define CNQ3_DITHER 0\n",
|
||||
depthFadeWithMSAA ? "#define CNQ3_MSAA 1\n" : "#define CNQ3_MSAA 0\n",
|
||||
shaderType == GL_FRAGMENT_SHADER ? shared_fs : "",
|
||||
shaderSource
|
||||
};
|
||||
|
||||
|
@ -1935,6 +1951,7 @@ static void Init()
|
|||
gl.pipelines[PID_GENERIC].uniformNames[GU_PROJECTION] = "projection";
|
||||
gl.pipelines[PID_GENERIC].uniformNames[GU_CLIP_PLANE] = "clipPlane";
|
||||
gl.pipelines[PID_GENERIC].uniformNames[GU_ALPHA_TEX] = "alphaTex";
|
||||
gl.pipelines[PID_GENERIC].uniformNames[GU_GREYSCALE] = "greyscale";
|
||||
gl.pipelines[PID_GENERIC].uniformNames[GU_GAMMA_BRIGHT_NOISE_SEED] = "gammaBrightNoiseSeed";
|
||||
gl.pipelines[PID_GENERIC].uniformNames[GU_A2C_ALPHA_BOOST] = "alphaBoost";
|
||||
|
||||
|
@ -1952,6 +1969,7 @@ static void Init()
|
|||
gl.pipelines[PID_DYNAMIC_LIGHT].uniformNames[DU_LIGHT_COLOR_RADIUS] = "lightColorRadius";
|
||||
gl.pipelines[PID_DYNAMIC_LIGHT].uniformNames[DU_OPAQUE] = "opaque";
|
||||
gl.pipelines[PID_DYNAMIC_LIGHT].uniformNames[DU_INTENSITY] = "intensity";
|
||||
gl.pipelines[PID_DYNAMIC_LIGHT].uniformNames[DU_GREYSCALE] = "greyscale";
|
||||
|
||||
gl.pipelines[PID_SOFT_SPRITE].arrayBuffers[VB_POSITION].enabled = qtrue;
|
||||
gl.pipelines[PID_SOFT_SPRITE].arrayBuffers[VB_POSITION].attribName = "position";
|
||||
|
@ -1966,6 +1984,7 @@ static void Init()
|
|||
gl.pipelines[PID_SOFT_SPRITE].uniformNames[SU_DIST_OFFSET] = "distOffset";
|
||||
gl.pipelines[PID_SOFT_SPRITE].uniformNames[SU_COLOR_SCALE] = "colorScale";
|
||||
gl.pipelines[PID_SOFT_SPRITE].uniformNames[SU_COLOR_BIAS] = "colorBias";
|
||||
gl.pipelines[PID_SOFT_SPRITE].uniformNames[SU_GREYSCALE] = "greyscale";
|
||||
|
||||
gl.pipelines[PID_POST_PROCESS].uniformNames[PU_BRIGHT_GAMMA_GREY] = "brightGammaGrey";
|
||||
|
||||
|
@ -2208,6 +2227,13 @@ static void DrawGeneric()
|
|||
glUniform1f(pipeline->uniformLocations[GU_A2C_ALPHA_BOOST], r_alphaToCoverageMipBoost->value);
|
||||
pipeline->uniformsDirty[GU_A2C_ALPHA_BOOST] = qfalse;
|
||||
}
|
||||
if(pipeline->uniformsDirty[GU_GREYSCALE] ||
|
||||
tess.greyscale != gl.greyscale)
|
||||
{
|
||||
glUniform1f(pipeline->uniformLocations[GU_GREYSCALE], tess.greyscale);
|
||||
gl.greyscale = tess.greyscale;
|
||||
pipeline->uniformsDirty[GU_GREYSCALE] = qfalse;
|
||||
}
|
||||
|
||||
UploadVertexArray(VB_POSITION, tess.xyz);
|
||||
UploadIndices(tess.indexes, tess.numIndexes);
|
||||
|
@ -2295,6 +2321,12 @@ static void DrawDynamicLight()
|
|||
pipeline->uniformsDirty[DU_INTENSITY] = qtrue;
|
||||
}
|
||||
|
||||
if(tess.greyscale != gl.greyscale)
|
||||
{
|
||||
gl.greyscale = tess.greyscale;
|
||||
pipeline->uniformsDirty[DU_GREYSCALE] = qtrue;
|
||||
}
|
||||
|
||||
if(pipeline->uniformsDirty[DU_MODELVIEW])
|
||||
{
|
||||
glUniformMatrix4fv(pipeline->uniformLocations[DU_MODELVIEW], 1, GL_FALSE, gl.modelViewMatrix);
|
||||
|
@ -2315,6 +2347,10 @@ static void DrawDynamicLight()
|
|||
{
|
||||
glUniform1f(pipeline->uniformLocations[DU_INTENSITY], gl.dlIntensity);
|
||||
}
|
||||
if(pipeline->uniformsDirty[DU_GREYSCALE])
|
||||
{
|
||||
glUniform1f(pipeline->uniformLocations[DU_GREYSCALE], tess.greyscale);
|
||||
}
|
||||
|
||||
memset(pipeline->uniformsDirty, 0, sizeof(pipeline->uniformsDirty));
|
||||
|
||||
|
@ -2363,6 +2399,13 @@ static void DrawDepthFade()
|
|||
gl.depthFadeOffset = tess.shader->dfBias;
|
||||
pipeline->uniformsDirty[SU_DIST_OFFSET] = qfalse;
|
||||
}
|
||||
if(pipeline->uniformsDirty[SU_GREYSCALE] ||
|
||||
tess.greyscale != gl.greyscale)
|
||||
{
|
||||
glUniform1f(pipeline->uniformLocations[SU_GREYSCALE], tess.greyscale);
|
||||
gl.greyscale = tess.greyscale;
|
||||
pipeline->uniformsDirty[SU_GREYSCALE] = qfalse;
|
||||
}
|
||||
|
||||
UploadVertexArray(VB_POSITION, tess.xyz);
|
||||
|
||||
|
|
|
@ -180,3 +180,7 @@ S_COLOR_VAL " 2 " S_COLOR_HELP "= R16G16B16A16"
|
|||
#define help_r_colorMipLevels \
|
||||
"colorizes textures based on their mip level\n" \
|
||||
"This disables MSAA on back-ends that use centroid sampling."
|
||||
|
||||
#define help_r_mapGreyscaleCTF \
|
||||
"how desaturated CTF map surfaces look\n" \
|
||||
"It applies to the red/blue color-coded surfaces of popular CTF/NTF maps."
|
||||
|
|
|
@ -61,6 +61,8 @@ cvar_t *r_speeds;
|
|||
cvar_t *r_fullbright;
|
||||
cvar_t *r_lightmap;
|
||||
cvar_t *r_lightmapGreyscale;
|
||||
cvar_t *r_mapGreyscale;
|
||||
cvar_t *r_mapGreyscaleCTF;
|
||||
cvar_t *r_novis;
|
||||
cvar_t *r_nocull;
|
||||
cvar_t *r_nocurves;
|
||||
|
@ -383,7 +385,7 @@ static const cvarTableItem_t r_cvars[] =
|
|||
{ &r_subdivisions, "r_subdivisions", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_FLOAT, "1", "64", help_r_subdivisions },
|
||||
{ &r_fullbright, "r_fullbright", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_fullbright },
|
||||
{ &r_lightmap, "r_lightmap", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_lightmap },
|
||||
{ &r_lightmapGreyscale, "r_lightmapGreyscale", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_FLOAT, "0", "1", "how monochrome the lightmap looks" },
|
||||
{ &r_lightmapGreyscale, "r_lightmapGreyscale", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_FLOAT, "0", "1", "how desaturated the lightmap looks" },
|
||||
{ &r_depthFade, "r_depthFade", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_depthFade },
|
||||
{ &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 },
|
||||
|
@ -409,11 +411,13 @@ static const cvarTableItem_t r_cvars[] =
|
|||
// r_textureMode's default value can't be an empty string because otherwise, a user-created default can stick (see Cvar_Get)
|
||||
{ &r_textureMode, "r_textureMode", "best", CVAR_ARCHIVE | CVAR_LATCH, CVART_STRING, NULL, NULL, help_r_textureMode },
|
||||
{ &r_gamma, "r_gamma", "1.2", CVAR_ARCHIVE, CVART_FLOAT, "0.5", "3", help_r_gamma },
|
||||
{ &r_greyscale, "r_greyscale", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "1", "controls how monochrome the final image looks" },
|
||||
{ &r_greyscale, "r_greyscale", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "1", "how desaturated the final image looks" },
|
||||
{ &r_ditherStrength, "r_ditherStrength", "1.0", CVAR_ARCHIVE, CVART_FLOAT, "0.125", "8.0", help_r_ditherStrength },
|
||||
{ &r_transpSort, "r_transpSort", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_r_transpSort },
|
||||
{ &r_lodCurveError, "r_lodCurveError", "2000", CVAR_ARCHIVE, CVART_FLOAT, "250", "10000", "curved surfaces LOD scale" },
|
||||
{ &r_alphaToCoverageMipBoost, "r_alphaToCoverageMipBoost", "0.125", CVAR_ARCHIVE, CVART_FLOAT, "0", "0.5", "increases the alpha value of higher mip levels" },
|
||||
{ &r_mapGreyscale, "r_mapGreyscale", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "1", "how desaturated the map looks" },
|
||||
{ &r_mapGreyscaleCTF, "r_mapGreyscaleCTF", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "1", help_r_mapGreyscaleCTF },
|
||||
|
||||
//
|
||||
// temporary variables that can change at any time
|
||||
|
@ -455,6 +459,7 @@ static void R_InitGAL()
|
|||
{
|
||||
struct gal_t {
|
||||
getGALInterface_t grabInterface;
|
||||
galId_t id;
|
||||
const char* cvarValue;
|
||||
const char* fullName;
|
||||
};
|
||||
|
@ -462,10 +467,10 @@ static void R_InitGAL()
|
|||
// preferred option goes first
|
||||
const gal_t galArray[] = {
|
||||
#if defined( _WIN32 )
|
||||
{ &GAL_GetD3D11, "D3D11", "Direct3D 11" },
|
||||
{ &GAL_GetD3D11, GAL_D3D11, "D3D11", "Direct3D 11" },
|
||||
#endif
|
||||
{ &GAL_GetGL3, "GL3", "OpenGL 3" },
|
||||
{ &GAL_GetGL2, "GL2", "OpenGL 2" }
|
||||
{ &GAL_GetGL3, GAL_GL3, "GL3", "OpenGL 3" },
|
||||
{ &GAL_GetGL2, GAL_GL2, "GL2", "OpenGL 2" }
|
||||
};
|
||||
|
||||
int galIndex = -1;
|
||||
|
@ -495,6 +500,7 @@ static void R_InitGAL()
|
|||
if ( !gal.Init() )
|
||||
ri.Error( ERR_FATAL, "Failed to initialize the %s back-end\n", galArray[galIndex].fullName );
|
||||
|
||||
gal.id = galArray[galIndex].id;
|
||||
GfxInfo_f();
|
||||
}
|
||||
|
||||
|
|
|
@ -423,6 +423,8 @@ struct shader_t {
|
|||
float dfInvDist;
|
||||
float dfBias;
|
||||
|
||||
qbool greyscaleCTF;
|
||||
|
||||
shader_t* next;
|
||||
};
|
||||
|
||||
|
@ -509,6 +511,7 @@ struct drawSurf_t {
|
|||
int index; // transparent surface's registration order
|
||||
float shaderSort; // transparent surface's shader sort
|
||||
int shaderNum; // unsorted shader index, for when we need to do fix-ups
|
||||
float greyscale; // how monochrome to draw all the stages
|
||||
};
|
||||
|
||||
extern void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( const void* );
|
||||
|
@ -519,6 +522,7 @@ struct litSurf_t {
|
|||
int shaderNum; // unsorted shader index, for when we need to do fix-ups
|
||||
const surfaceType_t* surface; // any of surface*_t
|
||||
litSurf_t* next;
|
||||
float greyscale;
|
||||
};
|
||||
|
||||
struct dlight_t {
|
||||
|
@ -932,6 +936,8 @@ typedef struct {
|
|||
float fogTable[FOG_TABLE_SIZE];
|
||||
|
||||
float mipFilter[4]; // only used by the GPU generators
|
||||
|
||||
qbool worldSurface; // is the currently added draw surface a world surface?
|
||||
} trGlobals_t;
|
||||
|
||||
extern backEndState_t backEnd;
|
||||
|
@ -1011,6 +1017,8 @@ extern cvar_t *r_ditherStrength; // the strength of the dithering noise
|
|||
extern cvar_t *r_transpSort; // transparency sorting mode
|
||||
extern cvar_t *r_lightmap; // render lightmaps only
|
||||
extern cvar_t *r_lightmapGreyscale; // how monochrome the lightmap looks
|
||||
extern cvar_t *r_mapGreyscale; // how monochrome the map looks
|
||||
extern cvar_t *r_mapGreyscaleCTF; // how monochrome CTF map surfaces look
|
||||
extern cvar_t *r_fullbright; // avoid lightmap pass
|
||||
extern cvar_t *r_depthFade; // fades marked shaders based on depth
|
||||
extern cvar_t *r_gpuMipGen; // uses GPU-side mip-map generation
|
||||
|
@ -1275,6 +1283,9 @@ struct shaderCommands_t
|
|||
|
||||
// use this state vector when drawing the fog pass
|
||||
unsigned int fogStateBits;
|
||||
|
||||
// how to process the colors of the current batch
|
||||
float greyscale;
|
||||
};
|
||||
|
||||
extern shaderCommands_t tess;
|
||||
|
@ -1529,6 +1540,8 @@ typedef enum {
|
|||
} drawType_t;
|
||||
|
||||
typedef struct {
|
||||
galId_t id;
|
||||
|
||||
qbool (*Init)();
|
||||
void (*ShutDown)( qbool fullShutDown );
|
||||
|
||||
|
|
|
@ -1065,6 +1065,15 @@ static void R_SortLitsurfs( dlight_t* dl )
|
|||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
static float SurfGreyscaleAmount( const shader_t* shader )
|
||||
{
|
||||
if (!tr.worldSurface)
|
||||
return 0.0f;
|
||||
|
||||
return shader->greyscaleCTF ? r_mapGreyscaleCTF->value : r_mapGreyscale->value;
|
||||
}
|
||||
|
||||
|
||||
void R_AddDrawSurf( const surfaceType_t* surface, const shader_t* shader, int fogIndex )
|
||||
{
|
||||
if (tr.refdef.numDrawSurfs >= MAX_DRAWSURFS)
|
||||
|
@ -1075,6 +1084,7 @@ void R_AddDrawSurf( const surfaceType_t* surface, const shader_t* shader, int fo
|
|||
drawSurf->surface = surface;
|
||||
drawSurf->model = tr.currentModel != NULL ? tr.currentModel->index : 0;
|
||||
drawSurf->shaderNum = shader->index;
|
||||
drawSurf->greyscale = SurfGreyscaleAmount( shader );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1089,6 +1099,7 @@ void R_AddLitSurf( const surfaceType_t* surface, const shader_t* shader, int fog
|
|||
litSurf->sort = R_ComposeSort( tr.currentEntityNum, shader, fogIndex );
|
||||
litSurf->surface = surface;
|
||||
litSurf->shaderNum = shader->index;
|
||||
litSurf->greyscale = SurfGreyscaleAmount( shader );
|
||||
|
||||
if (!tr.light->head)
|
||||
tr.light->head = litSurf;
|
||||
|
@ -1370,7 +1381,10 @@ static void R_AddEntitySurfaces()
|
|||
R_AddMD3Surfaces( ent );
|
||||
break;
|
||||
case MOD_BRUSH:
|
||||
// we want doors and lifts to be considered world surfaces too
|
||||
tr.worldSurface = qtrue;
|
||||
R_AddBrushModelSurfaces( ent );
|
||||
tr.worldSurface = qfalse;
|
||||
break;
|
||||
case MOD_BAD: // null model axis
|
||||
if ( (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal)
|
||||
|
@ -1392,7 +1406,9 @@ static void R_AddEntitySurfaces()
|
|||
|
||||
static void R_GenerateDrawSurfs()
|
||||
{
|
||||
tr.worldSurface = qtrue;
|
||||
R_AddWorldSurfaces();
|
||||
tr.worldSurface = qfalse;
|
||||
|
||||
R_AddPolygonSurfaces();
|
||||
|
||||
|
|
|
@ -963,53 +963,54 @@ void RB_CalcSpecularAlpha( unsigned char *alphas, int firstVertex, int numVertex
|
|||
|
||||
static void RB_CalcDiffuseColor( unsigned char *colors, int firstVertex, int numVertexes )
|
||||
{
|
||||
int i, j;
|
||||
float *v, *normal;
|
||||
float incoming;
|
||||
trRefEntity_t *ent;
|
||||
int ambientLightInt;
|
||||
vec3_t ambientLight;
|
||||
vec3_t lightDir;
|
||||
vec3_t directedLight;
|
||||
|
||||
ent = backEnd.currentEntity;
|
||||
trRefEntity_t* const ent = backEnd.currentEntity;
|
||||
if (!ent || !numVertexes)
|
||||
return;
|
||||
|
||||
ambientLightInt = ent->ambientLightInt;
|
||||
int ambientLightInt = ent->ambientLightInt;
|
||||
vec3_t ambientLight, lightDir, directedLight;
|
||||
VectorCopy( ent->ambientLight, ambientLight );
|
||||
VectorCopy( ent->directedLight, directedLight );
|
||||
VectorCopy( ent->lightDir, lightDir );
|
||||
|
||||
v = tess.xyz[firstVertex];
|
||||
normal = tess.normal[firstVertex];
|
||||
float* v = tess.xyz[firstVertex];
|
||||
float* normal = tess.normal[firstVertex];
|
||||
colors += firstVertex * 4;
|
||||
|
||||
for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) {
|
||||
incoming = DotProduct (normal, lightDir);
|
||||
const float t = r_mapGreyscale->value;
|
||||
const float ti = 1.0f - t;
|
||||
|
||||
// fix up ambientLightInt for the case where the dot product is 0 or negative
|
||||
vec3_t ambientLightMixed;
|
||||
const float ambientGrey = 0.299f * ambientLight[0] + 0.587f * ambientLight[1] + 0.114f * ambientLight[2];
|
||||
const float ambientGrey_t = ambientGrey * t;
|
||||
ambientLightMixed[0] = ambientLight[0] * ti + ambientGrey_t;
|
||||
ambientLightMixed[1] = ambientLight[1] * ti + ambientGrey_t;
|
||||
ambientLightMixed[2] = ambientLight[2] * ti + ambientGrey_t;
|
||||
((byte*)&ambientLightInt)[0] = ambientLightMixed[0];
|
||||
((byte*)&ambientLightInt)[1] = ambientLightMixed[1];
|
||||
((byte*)&ambientLightInt)[2] = ambientLightMixed[2];
|
||||
((byte*)&ambientLightInt)[3] = 0xFF;
|
||||
|
||||
for (int i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) {
|
||||
const float incoming = DotProduct( normal, lightDir );
|
||||
if ( incoming <= 0 ) {
|
||||
*(int *)&colors[i*4] = ambientLightInt;
|
||||
*(int*)&colors[i * 4] = ambientLightInt;
|
||||
continue;
|
||||
}
|
||||
j = myftol( ambientLight[0] + incoming * directedLight[0] );
|
||||
if ( j > 255 ) {
|
||||
j = 255;
|
||||
}
|
||||
colors[i*4+0] = j;
|
||||
|
||||
j = myftol( ambientLight[1] + incoming * directedLight[1] );
|
||||
if ( j > 255 ) {
|
||||
j = 255;
|
||||
}
|
||||
colors[i*4+1] = j;
|
||||
|
||||
j = myftol( ambientLight[2] + incoming * directedLight[2] );
|
||||
if ( j > 255 ) {
|
||||
j = 255;
|
||||
}
|
||||
colors[i*4+2] = j;
|
||||
|
||||
colors[i*4+3] = 255;
|
||||
const float inR = ambientLight[0] + incoming * directedLight[0];
|
||||
const float inG = ambientLight[1] + incoming * directedLight[1];
|
||||
const float inB = ambientLight[2] + incoming * directedLight[2];
|
||||
const float grey = 0.299f * inR + 0.587f * inG + 0.114f * inB;
|
||||
const float grey_t = grey * t;
|
||||
const float outR = inR * ti + grey_t;
|
||||
const float outG = inG * ti + grey_t;
|
||||
const float outB = inB * ti + grey_t;
|
||||
colors[i * 4 + 0] = (byte)min( outR, 255.0f );
|
||||
colors[i * 4 + 1] = (byte)min( outG, 255.0f );
|
||||
colors[i * 4 + 2] = (byte)min( outB, 255.0f );
|
||||
colors[i * 4 + 3] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2124,6 +2124,153 @@ static void ProcessDepthFade()
|
|||
}
|
||||
|
||||
|
||||
static void ProcessGreyscale()
|
||||
{
|
||||
// maps: q3wcp1/5/9/14/22 ct3ctf1/2 cpmctf1/2 q3w5
|
||||
// I'll thank DEZ here for compiling most of this list
|
||||
const char* names[] =
|
||||
{
|
||||
"textures/ctf_unified/banner01_red",
|
||||
"textures/ctf_unified/bounce_red",
|
||||
"textures/ssctf5/s_xian_dm3padwall_red",
|
||||
"textures/ssctf5/s_red_xian_dm3padwall",
|
||||
"textures/base_light/light1red_2000",
|
||||
"textures/ctf_unified/plaque_shiny_red",
|
||||
"textures/ctf_unified/pointer_right_red",
|
||||
"textures/ssctf5/s_redbase",
|
||||
"textures/ctf_unified/pointer_left_red",
|
||||
"textures/ssctf5/s_bluebase",
|
||||
"textures/ctf_unified/bounce_blue",
|
||||
"textures/base_light/light1blue_5000",
|
||||
"textures/ctf_unified/weapfloor_blue",
|
||||
"textures/ctf_unified/banner01_blue",
|
||||
"textures/ctf_unified/pointer_left_blue",
|
||||
"textures/ctf_unified/pointer_right_blue",
|
||||
"textures/ctf_unified/weapfloor_red",
|
||||
"textures/base_light/light1blue_2000",
|
||||
"textures/ctf_unified/plaque_notshiny_blue",
|
||||
"textures/ctf_unified/direction_blue",
|
||||
"textures/ctf_unified/direction_red",
|
||||
//"textures/ssctf5/s_xian_dm3padwall",
|
||||
"textures/ctf_unified/monologo_noflash_red",
|
||||
"textures/ctf_unified/wall_decal_red",
|
||||
"textures/ssctf3/s_beam_red",
|
||||
"textures/ctf_unified/banner02_red",
|
||||
"textures/ctf_unified/floor_decal_red",
|
||||
"textures/base_light/ceil1_22a_8k",
|
||||
"textures/ssctf3/s_beam_blue",
|
||||
"textures/ctf_unified/monologo_noflash_blue",
|
||||
"textures/ctf_unified/wall_decal_blue",
|
||||
"textures/ctf_unified/banner02_blue",
|
||||
"textures/ctf_unified/floor_decal_blue",
|
||||
"textures/base_light/ceil1_30_8k",
|
||||
"textures/ct3ctf1/jumppad_01_blue",
|
||||
"textures/base_light/ceil1_34",
|
||||
"textures/base_light/ceil1_22a",
|
||||
"textures/ct3ctf1/jumppad_01_red",
|
||||
"textures/base_light/light1red_5000",
|
||||
"textures/ninemil-ctf2/promode_logo_red",
|
||||
"textures/ninemil-ctf2/promode_logo_blue",
|
||||
"textures/ninemil-ctf2/bounce_red",
|
||||
"textures/ninemil-ctf2/bounce_blue",
|
||||
"textures/ninemil-ctf2/promode_logo_blue_large",
|
||||
"textures/ninemil-ctf2/test_blue",
|
||||
"textures/gothic_light/ironcrossltblue_5000",
|
||||
"textures/ninemil-ctf2/ctf_blueflag",
|
||||
"textures/ninemil-ctf2/test_red",
|
||||
"textures/gothic_light/ironcrossltred_5000",
|
||||
"textures/ninemil-ctf2/ctf_redflag",
|
||||
"textures/ninemil-ctf2/promode_logo_red_large",
|
||||
"textures/ninemil-ctf2/weapfloor_red",
|
||||
"textures/ninemil-ctf2/weapfloor_blue",
|
||||
"textures/japanc_q3w/Katana_r",
|
||||
"textures/japanc_q3w/trim_shadow_r",
|
||||
"textures/japanc_q3w/killblock_i2_small_r",
|
||||
"textures/japanc_q3w/pic1_r",
|
||||
"textures/japanc_q3w/drag_r",
|
||||
"textures/ctf_unified/pointer_red",
|
||||
"textures/ctf_unified/pointer_blue",
|
||||
"textures/japanc_q3w/drag_b",
|
||||
"textures/japanc_q3w/killblock_i2_small_b",
|
||||
"textures/japanc_q3w/Katana_b",
|
||||
"textures/japanc_q3w/trim_shadow_b",
|
||||
"textures/japanc_q3w/samurai_b",
|
||||
"textures/japanc_q3w/pic1_b",
|
||||
"textures/japanc_q3w/samurai_r",
|
||||
"textures/cpmctf1/banner2_b2",
|
||||
"textures/cpmctf1/banner2_r2",
|
||||
"textures/cpmctf1/metal_r",
|
||||
"textures/cpmctf1/metal_b",
|
||||
"textures/cpmctf1/trim_b",
|
||||
"textures/cpmctf1/banner1_b2",
|
||||
"textures/ctf/blocks18c_b",
|
||||
"textures/cpmctf1/trim_r",
|
||||
"textures/ctf/blocks18c_r",
|
||||
"textures/cpmctf1/banner1_r2",
|
||||
"textures/medieval/flr_marble1_c3trn_jp",
|
||||
"textures/medieval/flr_marble5_c3trn_jp",
|
||||
"textures/medieval/flr_marble1_c2trn",
|
||||
"textures/medieval/flr_marble5_c2trn",
|
||||
"textures/ssctf4/s_flameanim_blue",
|
||||
"textures/ssctf4/s_flameanim_red",
|
||||
"textures/ctf/ctf_tower_redfin_shiny",
|
||||
"textures/ctf/ctf_tower_bluefin_shiny",
|
||||
"textures/ctf/supportborder_blue",
|
||||
"textures/gothic_trim/supportborder",
|
||||
"textures/ssctf4/s_strucco_arch3",
|
||||
"textures/ctf_unified/banner03_blue",
|
||||
"textures/ssctf4/s_strucco_arch4",
|
||||
"textures/ssctf4/ssctf4_fogblue",
|
||||
"textures/ssctf4/ssctf4_fog",
|
||||
"textures/gothic_trim/baseboard08_ered",
|
||||
"textures/gothic_trim/baseboard08_dblue",
|
||||
"textures/gothic_trim/baseboard09_blue",
|
||||
"textures/gothic_trim/baseboard09_red",
|
||||
"textures/ninemil-ctf2/killblock_i2_r",
|
||||
"textures/ninemil-ctf2/killblock_i2_b",
|
||||
"textures/gothic_trim/baseboard08_ered",
|
||||
"textures/gothic_trim/baseboard08_dblue",
|
||||
"textures/gothic_trim/baseboard09_blue",
|
||||
"textures/gothic_trim/baseboard09_red",
|
||||
"textures/ninemil-ctf2/killblock_i2_r",
|
||||
"textures/ninemil-ctf2/killblock_i2_b",
|
||||
"textures/ctf_unified/plaque_shiny_blue",
|
||||
"textures/japanc_q3w/red_laq1",
|
||||
"textures/japanc_q3w/blue_laq1",
|
||||
"textures/sfx/xmetalfloor_wall_5b",
|
||||
"textures/sfx/xmetalfloor_wall_9b",
|
||||
"textures/sfx/xian_dm3padwall",
|
||||
"textures/crew/redwall",
|
||||
"textures/crew/bluewall",
|
||||
"textures/ctf_unified/monologo_flash_red",
|
||||
"textures/ctf_unified/monologo_flash_blue",
|
||||
"textures/crew/border11cx_r",
|
||||
"textures/crew/border11cx_b",
|
||||
"textures/ct_ct3ctf2/red_arrows_2",
|
||||
"textures/ct_ct3ctf2/blue_arrows_2",
|
||||
"textures/ct_ct3ctf2/jp_01_red",
|
||||
"textures/ct_ct3ctf2/jp_01",
|
||||
"textures/ct_ct3ctf2/red_pipe_liquid",
|
||||
"textures/ct_ct3ctf2/blue_pipe_liquid",
|
||||
"textures/ct_ct3ctf2/light_trim_red",
|
||||
"textures/ct_ct3ctf2/light_trim_blue",
|
||||
"textures/ct_ct3ctf2/red_jumppad_wall",
|
||||
"textures/ct_ct3ctf2/blue_jumppad_wall"
|
||||
};
|
||||
|
||||
// This takes less than 80 us when loading cpm32_b1 on my old 2600K.
|
||||
// So no, we don't need a hash map.
|
||||
for (int i = 0; i < ARRAY_LEN(names); ++i) {
|
||||
if (!Q_stricmp(shader.name, names[i])) {
|
||||
shader.greyscaleCTF = qtrue;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
shader.greyscaleCTF = qfalse;
|
||||
}
|
||||
|
||||
|
||||
static qbool UsesInternalLightmap( const shaderStage_t* stage )
|
||||
{
|
||||
return
|
||||
|
@ -2390,6 +2537,8 @@ static shader_t* FinishShader()
|
|||
|
||||
ProcessDepthFade();
|
||||
|
||||
ProcessGreyscale();
|
||||
|
||||
return GeneratePermanentShader();
|
||||
}
|
||||
|
||||
|
|
|
@ -749,6 +749,7 @@ solution "cnq3"
|
|||
end
|
||||
if os.is("windows") then
|
||||
files { string.format("%s/renderer/hlsl/*.hlsl", path_src) }
|
||||
files { string.format("%s/renderer/hlsl/*.hlsli", path_src) }
|
||||
end
|
||||
ApplyLibProjectSettings()
|
||||
filter "action:gmake"
|
||||
|
|
|
@ -255,6 +255,7 @@
|
|||
<None Include="..\..\code\renderer\hlsl\mip_pass.hlsl" />
|
||||
<None Include="..\..\code\renderer\hlsl\mip_start.hlsl" />
|
||||
<None Include="..\..\code\renderer\hlsl\post.hlsl" />
|
||||
<None Include="..\..\code\renderer\hlsl\shared.hlsli" />
|
||||
<None Include="..\..\code\renderer\hlsl\sprite.hlsl" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
|
|
@ -58,6 +58,9 @@
|
|||
<None Include="..\..\code\renderer\hlsl\post.hlsl">
|
||||
<Filter>hlsl</Filter>
|
||||
</None>
|
||||
<None Include="..\..\code\renderer\hlsl\shared.hlsli">
|
||||
<Filter>hlsl</Filter>
|
||||
</None>
|
||||
<None Include="..\..\code\renderer\hlsl\sprite.hlsl">
|
||||
<Filter>hlsl</Filter>
|
||||
</None>
|
||||
|
|
Loading…
Reference in a new issue