OpenGL2: Add normalScale and parallaxDepth stage keywords and helper cvars.

This commit is contained in:
SmileTheory 2014-03-03 21:02:39 -08:00
parent ea2810c085
commit ee67d0a981
7 changed files with 224 additions and 45 deletions

View File

@ -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);

View File

@ -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 },

View File

@ -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 );

View File

@ -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;

View File

@ -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);

View File

@ -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 <value>
@ -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 <value>
@ -978,7 +981,103 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
continue;
}
stage->materialInfo[1] = atof( token );
stage->specularScale[3] = atof( token );
}
//
// parallaxDepth <value>
//
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 <xy>
// or normalScale <x> <y>
// or normalScale <x> <y> <height>
//
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 <rgb> <gloss>
// or specularScale <r> <g> <b>
// or specularScale <r> <g> <b> <gloss>
//
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;
}
//

View File

@ -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 <x> <y>
- 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 <value>
- 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: