Adding Specular Maps in Source

Working on a model and finished the textures, and so I’m testing them out in-game to see how they turn out.

I made a diffuse, normal and specular map for this puppy, but the specular map is the one thing I don’t know how to add.

Does anyone know the code to add a custom spec-map to a model in Source? I’m certain you can do it; there’s no way the Source-Engine can have looked as decent as it does while using flat shaders across an entire model.

Speculars should go into the diffuse alpha map, not as a separate texture. The bumpmap doesn’t work with envmaps.

How does that work, exactly? You mean you save the original TGA with the specular as the alpha channel?

'Kay, so what does that look like when coded?

Also, on a side-note, that limitation sounds rather restricting…not to mention somewhat confusing as opposed to just designing specific slots for specific textures…

[editline]21st January 2011[/editline]

Eh hehehe…

Well, I think the normal map is working, but something is screwy with the spec.

Well, I put the spec in the alpha of the diffuse vtf, and Silverlan advised me to just use the $envmap env_cubemap
code. I think something additional is required…

This is my code, just so you know:

    "$baseTexture" "models/graboid"
    "$bumpmap" "models/graboid_normal"
    "$surfaceprop" "zombieflesh"
    "$envmap" "env_cubemap"


I’m not exactly sure if a spec map on a model is similar to a phong mask in Source. For shininess and reflectiveness on my models, I put the black and white phong mask (could be a black and white version of the diffuse, but with edited brightness/contrast levels) in the normal map’s alpha channel. Then I play around with the $phong perimeters in the VMT.

Of course if I’m totally wrong and I’m rambling on about random things, then completely ignore this post. :v:


Well, specular maps certainly SOUND an awful lot like these phong masks. It does indeed determine the specular (shiny) value of different sections of the texture, with white being very shiny, and black having no shine at all.

This is the one that applies to this model.

Try this:


	"$baseTexture" "models/graboid"
        "$bumpmap" "models/graboid_normal"

	"$halflambert" "1"

	"$phong" 1
	"$phongboost" 0.04
	"$phongexponent" 30
	"$phongtint" "[1 .85 .85]"
	"$phongfresnelranges" "[.5 .85 30]"


and put the specular map into the alpha map of the diffuse, and save it as 32 bit. The last bit is important, anything else than 32 bits doesn’t save the alpha map.

$normalmapalphaenvmapmask 1 :slight_smile:

Works just as fine. On top of that it works relatively decent as you can have phong in the same alpha channel

The’re some differences between phong and specularity. Basically phong reflects light and you can control the tightness of it. The amount of reflected light is based by the alpha of the normal map the whiter the more light is reflected. The tightness is then controlled by a phongexponent. Either globally for the whole texture or via a phongexponenttexture.

Specularity works a bit different - it essentially puts a cubemap reflection on the top of the texture with the amount of the reflection happening in the envmask - which can be a seperate texture or if the model uses a normal map it can be either in the alpha of the selfillum, normal map or diffuse. But it CANNOT be it’s own texture. I’m not fully certain how light works in those, but I think somewhat as well.

Eitherway - the calls are either $basealphaenvmapmask, $normalmapalphaenvmapmask or $selfillum_envmapmask_alpha.
Keep in mind that if the model uses translucency and you have the envmask in the base alpha, it works inverted.
you want more or less a similar settup from memory

//generic declerations
	"$halflambert" "1"
	"$basetexture" "models\kit\g22\NPK_G22_Body_D"
	"$bumpmap" "models\kit\g22\NPK_G22_Body_n"
	"$phongexponenttexture" ""models\kit\g22\NPK_G22_Body_S"	
	"$phong" "1" 
	"$phongboost" ".5"	
	"$phongfresnelranges"	"[.3 .8 9]"
	"$rimlight" "1"
	"$rimlightexponent" "15"
	"$rimlightboost" "1.8"
	"$normalmapalphaenvmapmask" "1"
	"$envmap" "env_cubemap"
//envcubemap uses the nearest cubemap in the map, you can also specify a custom cubemap as well 

Well, I have a feeling I’m still not fully getting it.

Just tried your code there, but I have no idea what I’m supposed to place as “$phongexponenttexture” . What does that do exactly? What map do I use?

My overblown reflection is certainly fixed, but in it’s place I don’t seem to have any at all.

[editline]21st January 2011[/editline]


Okay, I screwed up with the path. I put the spec map in that slot, and it worked! Varied shininess!

Of course, I need to alter the spec-map, because the areas MEANT to be shiny (the beak and mouth) are overblown. Still, this is FAR improved compared to before. I need to head to work, but I think I’ll be able to ship something together when I get back. Also, probably going to simplify the tongues (different material) to a something broader. THEY don’t need spec-maps, really…

Alright, now that I’ve figured that out, I decided to see if I could add an ambient occlusion map as well. I made one and tried adding this to the material code…

"$AmbientOcclTexture" "graboid_ao"
"$AmbientOcclColor"       "[.33 .33 .33]"
"$ambientocclusion" "1"

But I’m not seeing anything change in model viewer.

Really, I wouldn’t bug people here, but the Source documentation doesn’t seem to cover the abstract rules that govern half of this stuff, and I can never find it anywhere…

It’s best to use the Valve dev wiki for most of this stuff. As to $AO - It’s best to put it into the diffuse more than anything.
Apparently Alyx’s face VMT does have AO calls but I’m not sure what exactly they do. Might be something that’s present in newer engine versions and not the OB branch.