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
@ -402,6 +442,15 @@ they mean:
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: