After the basic vertex lighting has been calculated, textures are applied. In ShaderLab this is done using SetTexture command.
SetTexture commands have no effect when fragment programs are used; as in that case pixel operations are completely described in the shader.
Texturing is the place to do old-style combiner effects. You can have multiple SetTexture commands inside a pass - all textures are applied in sequence, like layers in a painting program. SetTexture commands must be placed at the end of a Pass.
The texture block controls how the texture is applied. Inside the texture block can be up to three commands: combine
, matrix
and constantColor
.
combine
commandcombine
src1 * src2combine
src1 + src2combine
src1 - src2combine
src1 +- src2combine
src1 lerp
(src2) src3combine
src1 * src2 + src3combine
src1 * src2 +- src3combine
src1 * src2 - src3All the src properties can be either one of previous, constant, primary or texture.
lerp
argument, can optionally be preceded by one - to make the resulting color negated.
constantColor
commandmatrix
commandBefore fragment programs existed, older graphics cards used a layered approach to textures. The textures are applied one after each other, modifying the color that will be written to the screen. For each texture, the texture is typically combined with the result of the previous operation.
Note that on "true fixed function" devices (OpenGL, OpenGL ES 1.1, Wii) the value of each SetTexture stage is clamped to 0..1 range. Everywhere else (Direct3D, OpenGL ES 2.0) the range may or may not be higher. This might affect SetTexture stages that can produce values higher than 1.0.
By default, the combiner formula is used for calculating both the RGB and alpha component of the color. Optionally, you can specify a separate formula for the alpha calculation. This looks like this:
SetTexture [_MainTex] { combine previous * texture, previous + texture }
Here, we multiply the RGB colors and add the alpha.
By default the primary color is the sum of the diffuse, ambient and specular colors (as defined in the Lighting calculation). If you specify SeparateSpecular On in the pass options, the specular color will be added in after the combiner calculation, rather than before. This is the default behavior of the built-in VertexLit shader.
Modern graphics cards with fragment shader support ("shader model 2.0" on desktop, OpenGL ES 2.0 on mobile) support all SetTexture modes and at least 4 texture stages (many of them support 8). If you're running on really old hardware (made before 2003 on PC, or before iPhone3GS on mobile), you might have as low as two texture stages. The shader author should write separate SubShaders for the cards he or she wants to support.
This small examples takes two textures. First it sets the first combiner to just take the _MainTex, then is uses the alpha channel of _BlendTex to fade in the RGB colors of _BlendTex
Shader "Examples/2 Alpha Blended Textures" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _BlendTex ("Alpha Blended (RGBA) ", 2D) = "white" {} } SubShader { Pass { // Apply base texture SetTexture [_MainTex] { combine texture } // Blend in the alpha texture using the lerp operator SetTexture [_BlendTex] { combine texture lerp (texture) previous } } } }
This shader uses the alpha component of the _MainTex to decide where to apply lighting. It does this by applying the texture to two stages; In the first stage, the alpha value of the texture is used to blend between the vertex color and solid white. In the second stage, the RGB values of the texture are multiplied in.
Shader "Examples/Self-Illumination" { Properties { _MainTex ("Base (RGB) Self-Illumination (A)", 2D) = "white" {} } SubShader { Pass { // Set up basic white vertex lighting Material { Diffuse (1,1,1,1) Ambient (1,1,1,1) } Lighting On // Use texture alpha to blend up to white (= full illumination) SetTexture [_MainTex] { constantColor (1,1,1,1) combine constant lerp(texture) previous } // Multiply in texture SetTexture [_MainTex] { combine previous * texture } } } }
We can do something else for free here, though; instead of blending to solid white, we can add a self-illumination color and blend to that. Note the use of ConstantColor to get a _SolidColor from the properties into the texture blending.
Shader "Examples/Self-Illumination 2" { Properties { _IlluminCol ("Self-Illumination color (RGB)", Color) = (1,1,1,1) _MainTex ("Base (RGB) Self-Illumination (A)", 2D) = "white" {} } SubShader { Pass { // Set up basic white vertex lighting Material { Diffuse (1,1,1,1) Ambient (1,1,1,1) } Lighting On // Use texture alpha to blend up to white (= full illumination) SetTexture [_MainTex] { // Pull the color property into this blender constantColor [_IlluminCol] // And use the texture's alpha to blend between it and // vertex color combine constant lerp(texture) previous } // Multiply in texture SetTexture [_MainTex] { combine previous * texture } } } }
And finally, we take all the lighting properties of the vertexlit shader and pull that in:
Shader "Examples/Self-Illumination 3" { Properties { _IlluminCol ("Self-Illumination color (RGB)", Color) = (1,1,1,1) _Color ("Main Color", Color) = (1,1,1,0) _SpecColor ("Spec Color", Color) = (1,1,1,1) _Emission ("Emmisive Color", Color) = (0,0,0,0) _Shininess ("Shininess", Range (0.01, 1)) = 0.7 _MainTex ("Base (RGB)", 2D) = "white" {} } SubShader { Pass { // Set up basic vertex lighting Material { Diffuse [_Color] Ambient [_Color] Shininess [_Shininess] Specular [_SpecColor] Emission [_Emission] } Lighting On // Use texture alpha to blend up to white (= full illumination) SetTexture [_MainTex] { constantColor [_IlluminCol] combine constant lerp(texture) previous } // Multiply in texture SetTexture [_MainTex] { combine previous * texture } } } }
Page last updated: 2012-08-17