User:SirYodaJedi/Porting IdTech 3 maps to Source/Shader2VMT
Some miscellanea for the User:SirYodaJedi/Porting IdTech 3 maps to Source#Converting materials section that would bloat the page if put there.
Per material
SurfaceParm commands
These are all defined via surfaceParm <parmname>; each parameter gets its own surfaceParm declaration. If multiple combined parameters are equivalent to a single command in Source, this is indicated here with plus signs.
Quake III
Most games have all of these, except where specified.
- alphashadow
This uses the alpha channel of q3map_lightImage to cast texture shadows. VRAD doesn't quite have as much control over texture shadows, so some creativity might be needed.
- For brushes, the most practical option will usually end up being to convert the applicable brushwork into an MDL. A custom VRAD could be used, but this opens a separate can of worms.
- One method I've used for texture shadows from brushes on vanilla Source 2013 compilers is to create MDL versions of the brushwork, with the faces inset a tenth of a unit, make the prop_static nonsolid, disable per-vertex lighting, and set its maxdxlevel to 60 (could probs even set it lower). In L4D and newer, you'd probably be safe setting mingpulevel to something absurdly high, like 20.
$no_draw technically would also work, but that method still loads the model and its geometry when the map is running, which is wasteful when we don't want to render it at all. - Definitely don't use blocklight brushes; you'd reach the brushside limit very quickly.
- One method I've used for texture shadows from brushes on vanilla Source 2013 compilers is to create MDL versions of the brushwork, with the faces inset a tenth of a unit, make the prop_static nonsolid, disable per-vertex lighting, and set its maxdxlevel to 60 (could probs even set it lower). In L4D and newer, you'd probably be safe setting mingpulevel to something absurdly high, like 20.
- For models, use $casttextureshadows.
- If the q3map_lightImage is significantly different from the actual transparent diffuse texture, you may want to set up a separate version of the texture that isn't part of the game files, and load it via an -insert_search_path in VRAD.
- detail
- flesh
This was supposed to be equivalent to $surfaceprop flesh, but doesn't work.
- lava
%CompileWater, along with a trigger_hurt brush
- metalsteps
Use a metallic $surfaceprop
- nolightmap
Lightmaps are not generated for this material. This does not necessarily mean the surface is unlit; it still per-vertex lighting calculated for it unless q3map_noVertexLight is used (but whether they are actually used depends upon if rgbGen vertex is used, afaik)
- nonsolid
If playerclip is not present:
- For brushes, use %CompileNonSolid.
- For models, use $contents notsolid.
- For displacements, set the "no physics collision", "no hull collision", and "no ray collision" flags for each applicable displacement in the map editor.
- nonsolid + playerclip (+ botclip)
- For brushes, use %CompilePassBullets.
- For models, use $contents grate.
- For displacements, set the "no physics collision" and "no hull collision" flags for each applicable displacement in the map editor.
- nomarks
- nosteps
Use the default_silent $surfaceprop
- pointlight
Same as nolightmap
- sky
The material is a sky. Replace with toolsskybox, but check skyParms to see how to set up the sky.
- slime
%CompileSlime, along with a trigger_hurt brush. Slime brushes in Source don't actually do any damage, unlike IdTech (and GoldSrc).
- trans
If neither alphashadow nor lightfilter are present:
- For brushes and displacements, set $alphatest only while compiling VBSP. If using a custom VRAD that supports texture shadows from brushes/disps, it may be necessary to add a noshadow entry for the material in the RAD file.
- For models, add a noshadow entry for the material in the RAD file
- water
Quake Live
Quake Live has all surfaceParms from Quake III.
- snowsteps
Use $surfaceprop snow
- woodsteps
Use a wooden $surfaceprop
Return to Castle Wolfenstein
RtCW has all surfaceParms from Quake III except botclip, flesh, and dust.
- metal
Same as metalsteps
- glass
$surfaceprop glass
- ceramic
There is no vanilla "ceramic" $surfaceprop, but tile will suffice.
- woodsteps
Any wooden $surfaceprop
- grasssteps
$surfaceprop grass
- gravelsteps
$surfaceprop gravel
- rubble
???
- carpetsteps
$surfaceprop carpet
- snowsteps
$surfaceprop snow
- roofsteps
???
- ai_nosight
- ai_nopass
- ai_nopass_large
Use an NPCClip brush.
- slag
Like slime, but solid. Put a trigger_hurt covering the 8 or so units above the slag.
Wolfenstein: Enemy Territory
WolfET has all surfaceParms from RTCW except ceramic.
- splash
$surfaceprop wade
- landmine
Landmines can be placed here; how to handle this will be dependent upon how the target game handles this sort of gameplay.
Solider of Fortune II, Jedi Outcast, Jedi Academy
Q3Map_* commands
- q3map_alphaGen const <norm>
$alpha <norm>
- q3map_bounce
- q3map_bounceScale
Scales reflectivity of the material when calculating bounced lighting. What you can probably do is:
- Create a VTF of the diffuse texture using VTFEdit's default luminance weights ([ 0.299 0.587 0.114 ]).
- Multiply the each of the calculated values by the scale, and put the resulting set of three values in $reflectivity.
- q3map_colorGen const ( <red> <green> <blue> )
Constant vertex color. Use $color or $color2, depending upon the shader.
- q3map_foliage <modelpath> <scale> <density> <odds> <invertalpha> (only in WolfET)
Like q3map_surfaceModel, but renders at runtime instead of being baked as misc_models.
- q3map_forceMeta
If used on a misc_model, the model is converted into "metasurfaces", which is required for lightmapped models. If a model has a material with this command, it's probably a good idea to spend extra effort in making sure the ported version gets light as nicely as possible.
- q3map_lightImage <texturepath>
This is used for texlight color, bounced light reflectivity, and texture shadows (both opaque and color-tinted).
If the lightImage texture is a JPG, then <texturename>_alpha.jpg
should be treated as the alpha channel, if present.
If absent, qer_editorImage is used instead. If that is also absent, then the first non-$lightmap texture map is used.
- q3map_lightRGB <red> <green> <blue>
Texlight color, used instead of the average color of the texture. The values are normalized to 0-1 and will need to be converted to the 0-255 range. This is as simple as multiplying each value by 255 and rounding to the nearest whole integer.
- q3map_material <surfaceprop>
Same as using surfaceParm "*_mat_<surfaceparm>".
- q3map_noFog
- q3map_normalImage <texturepath>
This is a normal map, which is used to create shadows when baking lightmaps, simulating bumpmapping. Source supports real bumpmapping (which looks a lot better when interacting with dynamic lights), so go ahead and use this as a $bumpmap if you have it.
Oddly, Q3Map2 uses DirectX-formatted normal maps despite IdTech 3 running on OpenGL, so the normal map will be able to be used as-is in Source, without the need to flip the green channel.
- q3map_rgbGen const ( <red> <green> <blue> )
Same as q3map_colorGen
- q3map_surfaceLight <intensity>
Put the texture in a RAD file. By default, the emission color is the average color of the q3map_lightImage, unless q3map_lightRGB is defined.
The easiest way to determine the average color of an image is to generate a 1x1 box mipmap. Using Gimp or Paint.NET, set the image scaling mode to "bilinear", then repeatedly rescale both axes by 50% until the canvas is 1x1 (we don't want to do a direct downscale, as this results in some strong approximations), then use the color picker to determine the 0-255 RGB values.
- q3map_surfaceModel <modelpath> <density> <odds> <minscale> <maxscale> <minangle> <maxangle> <oriented>
Like detail props. Annoyingly, VBSP has a bug that makes %detailtype not work correctly on brushes 99.9% of the time, so you might want to either take the time to convert the geometry to displacements (which it might need to be anyway for blended textures), or place prop_static or prop_detail entities manually (via the sprinkle tool).
If there's discrepancy between different materials using the same textures, go by whichever material is more important; since the textures are only uploaded to the GPU once, most IdTech 3 games go by whichever material is loaded first.
- noMipMaps
Set the "no mipmaps" flag in the applicable VTFs
- noPicMip
Set the "No LoD" flag in the applicable VTFs
- noTC (in JK2, JA)
- noCompress (in WolfET)
Don't use DXTn texture compression when creating the applicable VTFs (use BGR565, BGR888, or BGRA8888)
- allowCompress (in WolfET)
Use DXT1 or DXT5 texture compression when creating the applicable VTFs, even if you are making most of the VTFs uncompressed
WolfET implicit materials
Wolfenstein Enemy Territory has some parameters that can be used as a shorthand for materials with only a diffuse map and lightmap, instead of defining all the texture stages for a material. These either contain a texture path, or use -
, which uses the name of the material as the texture path.
If you're curious how these work in WolfET, see this pastebin.
- implicitMap <texturepath>
Material is opaque; no additional VMT parameters necessary.
- implicitMask <texturepath>
Material is alpha-tested and backface culling is disabled; use $alphatest
, $alphatestreference 0.5
, and $nocull
.
- implicitBlend <texturepath>
Material is alpha-blended and backface culling is disabled; use $translucent
and $nocull
ETLegacy Rend2 implicit stages
These are used to handle the fancy rend2 stuff when using implicit materials. The three commands above are still used in conjunction with the below, in order to determine whether a material is alpha tested, translucent, or opaque.
- diffuseMap <texturepath>
- bumpMap <texturepath>
$bumpmap (or occasionally $normalmap)
- specularMap <texturepath>
$envmapmask if there isn't a normal map.
If there is also a normal map, then put the specular mask in the normal map's alpha channel and use $normalmapalphaenvmapmask.
Editor commands
- qer_editorImage <texturepath>
This is roughly equivalent to %tooltexture, although it differs slightly in that it can also be used in the 3D view for alignment purposes.
Rendering commands
- cull none
- cull disable
- deformVertexes autoSprite
$spriteorientation VP_PARALLEL
- deformVertexes autoSprite2
$spriteorientation VP_PARALLEL_ORIENTED
- deformVertexes normal <func> <base> <amplitude> <freq>
Dynamically modifies vertex normals, without moving the actual vertices. In theory, this could be replicated using an animated normal map, but I don't know of any way that you could actually do that.
- novlcollapse
In Quake Live. This material always uses the lightmap even if the user has lightmaps disabled in their graphics settings. If this parameter is in a material used on patch meshes or misc_model, it may be that there are some complex shadows cast on them, in which case configuring or faking lightmapping is imperative.
- polygonOffset
$decal (yes, this really works).
- skyParms <farbox> <cloudheight> <nearbox>
If this texture is a sky, this is how it
- farbox - This is your standard Quake II-style 2D skybox. The
_bk.tga
etc are omitted. If set to-
, then this parameter is ignored, and a plain black 2D skybox should be assumed. - cloudheight - Curvature of the clouds (lower numbers are curvier). The cloud layers themselves are defined in the texture stages; see TopHattWaffle's tutorial for how to make clouds in the 3D skybox.
- nearbox - Another 2D skybox, alpha blended in front of the clouds. Very rarely used, if ever. If set to
-
, then this parameter is ignored.
Per texture stage
- stage <diffuseMap, bumpMap, or specularMap>
For Rend2. Indicates the type of texture the given stage uses. Rend2 materials function more similar to the materials that Source 1 shaders use, so they should be preferred when available.
If there are no more than one of each type, then they are directly equivalent to $basetexture, $bumpmap/$normalmap, and $envmapmask.
If a material has both normal and specular stages, you need to put the specular in the alpha channel of the normal map and use $normalmapalphaenvmapmask.
Note that Rend2 normal maps are OpenGL format, and will need to have their green channels inverted to look correct in Source.
- map <texturepath>
This is the texture. Technically a diffuse texture, but it could be more specifically a lightmap, a detail texture, or a matcap.
- clampMap <texturepath>
Like `map`, but clamps the UV coordinates to prevent usage as a tiled texture. Set these in the VTF.
- animMap <texturepath>
Like `map`, but animated. The number before the texture list indicates the frame rate. Combine these into a single VTF and use a material proxy to set the animation. Up to 8 frames in vanilla Quake III. Up to 16 frames in vanilla RTCW and WolfET. Up to 32 frames in vanilla Jedi Academy.
- clampAnimMap <texturepath>
Like clampMap and animMap combined. Not in vanilla Quake 3.
- videoMap <videopath>
Like `clampAnimMap`, but uses a ROQ video file instead of defining a set of individual image files. This allows for much longer animations, but lacks an alpha channel.
Use ffmpeg -i input.roq out%03d.png
to extract all the frames from the ROQ, and ffprobe input.roq
to determine the original framerate.
- blendFunc <func>
Can blend textures together (detail textures, glowing textures, etc.), be used for translucency, or even do specular lighting, depending upon parameters and stage position. These directly line up with OpenGL's glBlendFunc values, but also have three shorthand options:
- add (GL_ONE GL_ONE) - additive blending; like $additive or $detailblendmode 5
- blend (GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA) - like $translucent or $detailblendmode 2
- filter (GL_DST_COLOR GL_ZERO) - like $detailblendmode 8 or modulate shader without $mod2x
A couple other explicit blends worth knowing:
- GL_DST_COLOR GL_SRC_COLOR - DecalModulate, $detailblendmode 0, modulate shader with $mod2x
- GL_ONE_MINUS_SRC_ALPHA GL_SRC_ALPHA - like blendFunc blend, but the alpha channel is inverted; you might need to invert the alpha channel manually before converting to VTF
- alphaFunc <func>
Alphatesting. Unlike , supports alpha-clipping translucent textures. Any textures with translucency will need to not have alpha-testing when ported to , and may need to be edited (to sharpen the alpha channel). It takes one parameter:
Func | Description | VMT equivalent and additional setup |
---|---|---|
GT0 | Greater Than 0.
Usually used in conjunction with a translucent blendFunc, to avoid rendering the surface where completely transparent. |
If not translucent (rare): |
LT128 | Less Than 128.
This designates an inverted alpha channel. |
If not translucent:
First invert the alpha channel in an image editor (linear invert). |
GE128 | Greater than or Equal to 128.
Standard alpha testing; anything less than 127 will be transparent, and anything greater than or equal to 128 will be opaque. |
If not translucent: |
GE192 | Greater than or Equal to 192.
Added in Jedi Academy. Like GE128, but with the clipping threshold set to 192 |
If not translucent: |
- alphaGen lightingSpecular
Used on dynamically-lit models to have the alpha be lower the brighter the model is lit. In this situation, you probably want to use env_cubemap instead of the original matcap, or perhaps even $phong.
- alphaGen vertex
- alphaGen oneMinusVertex
Usually a good indication that the material uses vertex alpha for texture blending, and will probably need to be used on a displacement.
If the top diffuse texture has an alpha channel, move that to the green channel of a $blendmodulatetexture, making the red channel a constant 128 (save as DXT1), and make the aforementioned diffuse texture opaque.
- alphaGen sin <base> <amplitude> <phase> <frequency>
- rgbGen sin <base> <amplitude> <phase> <frequency>
Split this stage off into a separate material with $decal to use as a decal mesh/brush, then use the Sine material proxy to adjust $alpha or $color, respectively.
"Sine" { "sineperiod" xxx // set to frequency "sinemin" xxx // set to base-amplitude "sinemax" xxx // set to base+amplitude "timeoffset" xxx // set to phase "resultVar" xxx // set to $alpha for alphaGen, or $color for rgbGen }
- tcGen environment
Stage is an environment map; use as a $envmap. Subsequent stages use the alpha channel of the textures of the texture as a specular mask. If the blendFunc is blend or GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA, then invert the mask before using it as a $envmapmask. If the blendFunc is GL_ONE_MINUS_SRC_ALPHA GL_SRC_ALPHA, then the alpha channel can be used as an $envmapmask as-is.
- detail
Doesn't actually do anything on its own, but causes the stage (and due to a bug, any subsequent stages) to not be rendered when r_detailtextures is set to 0. This is a good hint that a given stage is (probably) a detail texture.