From ee67d0a981e4133fba4b72ed91e6c5486d36a11c Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Mon, 3 Mar 2014 21:02:39 -0800 Subject: [PATCH] OpenGL2: Add normalScale and parallaxDepth stage keywords and helper cvars. --- code/renderergl2/glsl/lightall_fp.glsl | 17 +-- code/renderergl2/tr_glsl.c | 7 +- code/renderergl2/tr_init.c | 6 + code/renderergl2/tr_local.h | 11 +- code/renderergl2/tr_shade.c | 31 +++++- code/renderergl2/tr_shader.c | 146 ++++++++++++++++++++----- opengl2-readme.txt | 51 ++++++++- 7 files changed, 224 insertions(+), 45 deletions(-) diff --git a/code/renderergl2/glsl/lightall_fp.glsl b/code/renderergl2/glsl/lightall_fp.glsl index 871c527e34..c74d6844f5 100644 --- a/code/renderergl2/glsl/lightall_fp.glsl +++ b/code/renderergl2/glsl/lightall_fp.glsl @@ -25,7 +25,8 @@ uniform samplerCube u_CubeMap; #endif #if defined(USE_NORMALMAP) || defined(USE_DELUXEMAP) || defined(USE_SPECULARMAP) || defined(USE_CUBEMAP) -uniform vec4 u_EnableTextures; // x = normal, y = deluxe, z = specular, w = cube +// y = deluxe, w = cube +uniform vec4 u_EnableTextures; #endif #if defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT) @@ -39,7 +40,8 @@ uniform vec3 u_PrimaryLightAmbient; #endif #if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT) -uniform vec2 u_MaterialInfo; +uniform vec4 u_NormalScale; +uniform vec4 u_SpecularScale; #endif varying vec4 var_TexCoords; @@ -360,7 +362,7 @@ void main() #if defined(USE_PARALLAXMAP) vec3 offsetDir = normalize(E * tangentToWorld); - offsetDir.xy *= -0.05 / offsetDir.z; + offsetDir.xy *= -u_NormalScale.a / offsetDir.z; texCoords += offsetDir.xy * RayIntersectDisplaceMap(texCoords, offsetDir.xy, u_NormalMap); #endif @@ -378,7 +380,7 @@ void main() #else N.xy = texture2D(u_NormalMap, texCoords).rg - vec2(0.5); #endif - N.xy *= u_EnableTextures.x; + N.xy *= u_NormalScale.xy; N.z = sqrt(clamp((0.25 - N.x * N.x) - N.y * N.y, 0.0, 1.0)); N = tangentToWorld * N; #else @@ -425,15 +427,16 @@ void main() NL = clamp(dot(N, L), 0.0, 1.0); NE = clamp(dot(N, E), 0.0, 1.0); - vec4 specular = vec4(1.0); #if defined(USE_SPECULARMAP) - specular += texture2D(u_SpecularMap, texCoords) * u_EnableTextures.z - u_EnableTextures.zzzz; + vec4 specular = texture2D(u_SpecularMap, texCoords); #if defined(USE_GAMMA2_TEXTURES) specular.rgb *= specular.rgb; #endif + #else + vec4 specular = vec4(1.0); #endif - specular *= u_MaterialInfo.xxxy; + specular *= u_SpecularScale; float gloss = specular.a; float shininess = exp2(gloss * 13.0); diff --git a/code/renderergl2/tr_glsl.c b/code/renderergl2/tr_glsl.c index 4919254f04..c4a30b6035 100644 --- a/code/renderergl2/tr_glsl.c +++ b/code/renderergl2/tr_glsl.c @@ -123,9 +123,10 @@ static uniformInfo_t uniformsInfo[] = { "u_ModelMatrix", GLSL_MAT16 }, { "u_ModelViewProjectionMatrix", GLSL_MAT16 }, - { "u_Time", GLSL_FLOAT }, - { "u_VertexLerp" , GLSL_FLOAT }, - { "u_MaterialInfo", GLSL_VEC2 }, + { "u_Time", GLSL_FLOAT }, + { "u_VertexLerp" , GLSL_FLOAT }, + { "u_NormalScale", GLSL_VEC4 }, + { "u_SpecularScale", GLSL_VEC4 }, { "u_ViewInfo", GLSL_VEC4 }, { "u_ViewOrigin", GLSL_VEC3 }, diff --git a/code/renderergl2/tr_init.c b/code/renderergl2/tr_init.c index 4fb1d99ef8..6c9d248f45 100644 --- a/code/renderergl2/tr_init.c +++ b/code/renderergl2/tr_init.c @@ -135,6 +135,9 @@ cvar_t *r_parallaxMapping; cvar_t *r_cubeMapping; cvar_t *r_deluxeSpecular; cvar_t *r_specularIsMetallic; +cvar_t *r_baseNormalX; +cvar_t *r_baseNormalY; +cvar_t *r_baseParallax; cvar_t *r_baseSpecular; cvar_t *r_baseGloss; cvar_t *r_recalcMD3Normals; @@ -1188,6 +1191,9 @@ void R_Register( void ) r_cubeMapping = ri.Cvar_Get( "r_cubeMapping", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_deluxeSpecular = ri.Cvar_Get( "r_deluxeSpecular", "0.3", CVAR_ARCHIVE | CVAR_LATCH ); r_specularIsMetallic = ri.Cvar_Get( "r_specularIsMetallic", "0", CVAR_ARCHIVE | CVAR_LATCH ); + r_baseNormalX = ri.Cvar_Get( "r_baseNormalX", "1.0", CVAR_ARCHIVE | CVAR_LATCH ); + r_baseNormalY = ri.Cvar_Get( "r_baseNormalY", "1.0", CVAR_ARCHIVE | CVAR_LATCH ); + r_baseParallax = ri.Cvar_Get( "r_baseParallax", "0.05", CVAR_ARCHIVE | CVAR_LATCH ); r_baseSpecular = ri.Cvar_Get( "r_baseSpecular", "0.04", CVAR_ARCHIVE | CVAR_LATCH ); r_baseGloss = ri.Cvar_Get( "r_baseGloss", "0.3", CVAR_ARCHIVE | CVAR_LATCH ); r_dlightMode = ri.Cvar_Get( "r_dlightMode", "0", CVAR_ARCHIVE | CVAR_LATCH ); diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index d04485074c..1f7c6fd636 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -400,7 +400,10 @@ typedef struct { stageType_t type; struct shaderProgram_s *glslShaderGroup; int glslShaderIndex; - vec2_t materialInfo; + + vec4_t normalScale; + vec4_t specularScale; + } shaderStage_t; struct shaderCommands_s; @@ -676,7 +679,8 @@ typedef enum UNIFORM_TIME, UNIFORM_VERTEXLERP, - UNIFORM_MATERIALINFO, + UNIFORM_NORMALSCALE, + UNIFORM_SPECULARSCALE, UNIFORM_VIEWINFO, // znear, zfar, width/2, height/2 UNIFORM_VIEWORIGIN, @@ -1794,6 +1798,9 @@ extern cvar_t *r_parallaxMapping; extern cvar_t *r_cubeMapping; extern cvar_t *r_deluxeSpecular; extern cvar_t *r_specularIsMetallic; +extern cvar_t *r_baseNormalX; +extern cvar_t *r_baseNormalY; +extern cvar_t *r_baseParallax; extern cvar_t *r_baseSpecular; extern cvar_t *r_baseGloss; extern cvar_t *r_dlightMode; diff --git a/code/renderergl2/tr_shade.c b/code/renderergl2/tr_shade.c index 115a2c30e2..349f7e2e87 100644 --- a/code/renderergl2/tr_shade.c +++ b/code/renderergl2/tr_shade.c @@ -811,7 +811,8 @@ static void ForwardDlight( void ) { GLSL_SetUniformFloat(sp, UNIFORM_LIGHTRADIUS, radius); - GLSL_SetUniformVec2(sp, UNIFORM_MATERIALINFO, pStage->materialInfo); + GLSL_SetUniformVec4(sp, UNIFORM_NORMALSCALE, pStage->normalScale); + GLSL_SetUniformVec4(sp, UNIFORM_SPECULARSCALE, pStage->specularScale); // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light // where they aren't rendered @@ -822,11 +823,36 @@ static void ForwardDlight( void ) { if (pStage->bundle[TB_DIFFUSEMAP].image[0]) R_BindAnimatedImageToTMU( &pStage->bundle[TB_DIFFUSEMAP], TB_DIFFUSEMAP); + // bind textures that are sampled and used in the glsl shader, and + // bind whiteImage to textures that are sampled but zeroed in the glsl shader + // + // alternatives: + // - use the last bound texture + // -> costs more to sample a higher res texture then throw out the result + // - disable texture sampling in glsl shader with #ifdefs, as before + // -> increases the number of shaders that must be compiled + // + if (pStage->bundle[TB_NORMALMAP].image[0]) + { R_BindAnimatedImageToTMU( &pStage->bundle[TB_NORMALMAP], TB_NORMALMAP); + } + else if (r_normalMapping->integer) + GL_BindToTMU( tr.whiteImage, TB_NORMALMAP ); if (pStage->bundle[TB_SPECULARMAP].image[0]) + { R_BindAnimatedImageToTMU( &pStage->bundle[TB_SPECULARMAP], TB_SPECULARMAP); + } + else if (r_specularMapping->integer) + GL_BindToTMU( tr.whiteImage, TB_SPECULARMAP ); + + { + vec4_t enableTextures; + + VectorSet4(enableTextures, 0.0f, 0.0f, 0.0f, 0.0f); + GLSL_SetUniformVec4(sp, UNIFORM_ENABLETEXTURES, enableTextures); + } if (r_dlightMode->integer >= 2) { @@ -1222,7 +1248,8 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) GLSL_SetUniformMat4(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix); - GLSL_SetUniformVec2(sp, UNIFORM_MATERIALINFO, pStage->materialInfo); + GLSL_SetUniformVec4(sp, UNIFORM_NORMALSCALE, pStage->normalScale); + GLSL_SetUniformVec4(sp, UNIFORM_SPECULARSCALE, pStage->specularScale); //GLSL_SetUniformFloat(sp, UNIFORM_MAPLIGHTSCALE, backEnd.refdef.mapLightScale); diff --git a/code/renderergl2/tr_shader.c b/code/renderergl2/tr_shader.c index 6dbac55a36..d6e0727a4f 100644 --- a/code/renderergl2/tr_shader.c +++ b/code/renderergl2/tr_shader.c @@ -911,6 +911,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) else if(!Q_stricmp(token, "normalMap") || !Q_stricmp(token, "bumpMap")) { stage->type = ST_NORMALMAP; + VectorSet4(stage->normalScale, r_baseNormalX->value, r_baseNormalY->value, 1.0f, r_baseParallax->value); } else if(!Q_stricmp(token, "normalParallaxMap") || !Q_stricmp(token, "bumpParallaxMap")) { @@ -918,12 +919,12 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) stage->type = ST_NORMALPARALLAXMAP; else stage->type = ST_NORMALMAP; + VectorSet4(stage->normalScale, r_baseNormalX->value, r_baseNormalY->value, 1.0f, r_baseParallax->value); } else if(!Q_stricmp(token, "specularMap")) { stage->type = ST_SPECULARMAP; - stage->materialInfo[0] = 1.0f; - stage->materialInfo[1] = 1.0f; + VectorSet4(stage->specularScale, 1.0f, 1.0f, 1.0f, 1.0f); } else { @@ -942,7 +943,9 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) ri.Printf( PRINT_WARNING, "WARNING: missing parameter for specular reflectance in shader '%s'\n", shader.name ); continue; } - stage->materialInfo[0] = atof( token ); + stage->specularScale[0] = + stage->specularScale[1] = + stage->specularScale[2] = atof( token ); } // // specularExponent @@ -964,7 +967,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) // FIXME: assumes max exponent of 8192 and min of 1, must change here if altered in lightall_fp.glsl exponent = CLAMP(exponent, 1.0, 8192.0); - stage->materialInfo[1] = log(exponent) / log(8192.0); + stage->specularScale[3] = log(exponent) / log(8192.0); } // // gloss @@ -978,7 +981,103 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) continue; } - stage->materialInfo[1] = atof( token ); + stage->specularScale[3] = atof( token ); + } + // + // parallaxDepth + // + else if (!Q_stricmp(token, "parallaxdepth")) + { + token = COM_ParseExt(text, qfalse); + if ( token[0] == 0 ) + { + ri.Printf( PRINT_WARNING, "WARNING: missing parameter for parallaxDepth in shader '%s'\n", shader.name ); + continue; + } + + stage->normalScale[3] = atof( token ); + } + // + // normalScale + // or normalScale + // or normalScale + // + else if (!Q_stricmp(token, "normalscale")) + { + token = COM_ParseExt(text, qfalse); + if ( token[0] == 0 ) + { + ri.Printf( PRINT_WARNING, "WARNING: missing parameter for normalScale in shader '%s'\n", shader.name ); + continue; + } + + stage->normalScale[0] = atof( token ); + + token = COM_ParseExt(text, qfalse); + if ( token[0] == 0 ) + { + // one value, applies to X/Y + stage->normalScale[1] = stage->normalScale[0]; + continue; + } + + stage->normalScale[1] = atof( token ); + + token = COM_ParseExt(text, qfalse); + if ( token[0] == 0 ) + { + // two values, no height + continue; + } + + stage->normalScale[3] = atof( token ); + } + // + // specularScale + // or specularScale + // or specularScale + // + else if (!Q_stricmp(token, "specularscale")) + { + token = COM_ParseExt(text, qfalse); + if ( token[0] == 0 ) + { + ri.Printf( PRINT_WARNING, "WARNING: missing parameter for specularScale in shader '%s'\n", shader.name ); + continue; + } + + stage->specularScale[0] = atof( token ); + + token = COM_ParseExt(text, qfalse); + if ( token[0] == 0 ) + { + ri.Printf( PRINT_WARNING, "WARNING: missing parameter for specularScale in shader '%s'\n", shader.name ); + continue; + } + + stage->specularScale[1] = atof( token ); + + token = COM_ParseExt(text, qfalse); + if ( token[0] == 0 ) + { + // two values, rgb then gloss + stage->specularScale[3] = stage->specularScale[1]; + stage->specularScale[1] = + stage->specularScale[2] = stage->specularScale[0]; + continue; + } + + stage->specularScale[2] = atof( token ); + + token = COM_ParseExt(text, qfalse); + if ( token[0] == 0 ) + { + // three values, rgb + continue; + } + + stage->specularScale[2] = atof( token ); + } // // rgbGen @@ -2231,6 +2330,8 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse, diffuse->bundle[TB_NORMALMAP] = normal->bundle[0]; if (parallax && r_parallaxMapping->integer) defs |= LIGHTDEF_USE_PARALLAXMAP; + + VectorCopy4(normal->normalScale, diffuse->normalScale); } else if ((lightmap || useLightVector || useLightVertex) && (diffuseImg = diffuse->bundle[TB_DIFFUSEMAP].image[0])) { @@ -2251,6 +2352,8 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse, if (parallax && r_parallaxMapping->integer) defs |= LIGHTDEF_USE_PARALLAXMAP; + + VectorSet4(diffuse->normalScale, r_baseNormalX->value, r_baseNormalY->value, 1.0f, r_baseParallax->value); } } } @@ -2261,8 +2364,7 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse, { //ri.Printf(PRINT_ALL, ", specularmap %s", specular->bundle[0].image[0]->imgName); diffuse->bundle[TB_SPECULARMAP] = specular->bundle[0]; - diffuse->materialInfo[0] = specular->materialInfo[0]; - diffuse->materialInfo[1] = specular->materialInfo[1]; + VectorCopy4(specular->specularScale, diffuse->specularScale); } } @@ -2568,29 +2670,6 @@ static qboolean CollapseStagesToGLSL(void) } } - // insert default material info if needed - for (i = 0; i < MAX_SHADER_STAGES; i++) - { - shaderStage_t *pStage = &stages[i]; - - if (!pStage->active) - continue; - - if (pStage->glslShaderGroup != tr.lightallShader) - continue; - - if ((pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) == 0) - continue; - - if (!pStage->bundle[TB_SPECULARMAP].image[0] && r_specularMapping->integer) - { - if (!pStage->materialInfo[0]) - pStage->materialInfo[0] = r_baseSpecular->value; - if (!pStage->materialInfo[1]) - pStage->materialInfo[1] = r_baseGloss->value; - } - } - return numStages; } @@ -3216,6 +3295,13 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImag shader.lightmapIndex = lightmapIndex; for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) { stages[i].bundle[0].texMods = texMods[i]; + + // default normal/specular + VectorSet4(stages[i].normalScale, 0.0f, 0.0f, 0.0f, 0.0f); + stages[i].specularScale[0] = + stages[i].specularScale[1] = + stages[i].specularScale[2] = r_baseSpecular->value; + stages[i].specularScale[3] = r_baseGloss->value; } // diff --git a/opengl2-readme.txt b/opengl2-readme.txt index 999fd38522..3df7958e26 100644 --- a/opengl2-readme.txt +++ b/opengl2-readme.txt @@ -203,6 +203,44 @@ Cvars for advanced material usage: 0 - No. (default) 1 - Yes. + r_baseSpecular - Set the specular reflectance of materials + which don't include a specular map or + use the specularReflectance keyword. + 0 - No. + 0.04 - Realistic. (default) + 1.0 - Ack. + + r_baseGloss - Set the glossiness of materials which don't + include a specular map or use the + specularExponent keyword. + 0 - Rough. + 0.3 - Default. + 1.0 - Shiny. + + r_baseNormalX - Set the scale of the X values from normal + maps when the normalScale keyword is not + used. + -1 - Flip X. + 0 - Ignore X. + 1 - Normal X. (default) + 2 - Double X. + + r_baseNormalY - Set the scale of the Y values from normal + maps when the normalScale keyword is not + used. + -1 - Flip Y. + 0 - Ignore Y. + 1 - Normal Y. (default) + 2 - Double Y. + + r_baseParallax - Sets the scale of the parallax effect for + materials when the parallaxDepth keyword + is not used. + 0 - No depth. + 0.01 - Pretty smooth. + 0.05 - Standard depth. (default) + 0.1 - Looks broken. + Cvars for image interpolation and generation: r_imageUpsample - Use interpolation to artifically increase the resolution of all textures. Looks good @@ -362,6 +400,8 @@ Here's an example of a material stored in one, showing off some new features: { stage normalparallaxmap map textures/abandon/grass3_1024_n.png + normalScale 1 1 + parallaxDepth 0.05 } { stage specularmap @@ -401,7 +441,16 @@ they mean: alpha channel of the specular map, so if it were set to 16, and the alpha channel of the specular map was set to 0.5, then the shininess would be set to 8. Default 256. - + + normalScale + - State the X and Y scales of the normal map. This is useful for increasing + or decreasing the "strength" of the normal map, or entering negative values + to flip the X and/or Y values. Default 1 1. + + parallaxDepth + - State the maximum depth of the parallax map. This is a fairly sensitive + value, and I recommend the default or lower. Default 0.05. + An important note is that normal and specular maps influence the diffuse map declared before them, so materials like this are possible: