ShaderCelshading
From SimsWiki
EP5-SS
0xCD7FE87A
0x1C0532FA
0x30A51061
0xFFF61EBE
# celshading
#
# Cel Shaders
#
# Implements a simple cel-shader with diffuse, specular, and edge terms,
# an outline (using offset normal trick), and environment map. Everything
# is optional except the diffuse stage. One stage each for diffuse/specular/edge.
#beginshader CelShadedMaterial
#description Simple Cel shader (one light)
#BeginStdAttrBlock
set csRampTexture "64shade"
#attrdescription Lookup texture for diffuse intensity.
sete csShadeFilter point (point bilinear)
#attrdescription Filtering of the shade ramp
sete csColorFilter point (point bilinear)
#attrdescription Filtering of any color ramp
setb csAddSpecular false
#attrdescription Whether to enable specular intensity term.
set csSpecRampTexture "blackwhite"
#attrdescription Lookup texture for specular intensity
setf csShininess 100 # min:0 max:10000
#attrdescription Shininess of specular intensity highlight.
#attrdescription The shader may be more efficient if you
#attrdescription leave this at one and use the texture ramp
#attrdescription to modulate sharpness.
setb csAddEdge true
#attrdescription Whether to enable the edge intensity term.
set csEdgeRampTexture "blackwhite"
#attrdescription Lookup texture for edge intensity: how much the
#attrdescription surface faces the camera. The left of the texture
#attrdescription faces the camera, the middle is edge-on, and the right
#attrdescription faces away. This can be used to provide an outline or fresnel effect.
sete csEdgeFilter point (point bilinear)
#attrdescription Filtering of the edge ramp
setb csEdgeRampTextureAlphaInvert true
#attrdescription Whether to invert alpha from edge intensity ramp texture.
setf csEdgeOffset 0.3 # min:-1 max:1
#attrdescription Applies bias to the edge intensity term,
#attrdescription shifting it towards the camera (positive) or
#attrdescription away from the camera (negative).
setf csEdgeLightDamping 0 # min:-1000 max:1000
#attrdescription Offsets the edge term by diffuse lighting, which has
#attrdescription the effect of suppressing it in lit areas.
setb csRouteColorFromAlpha true
#attrdescription Whether to use vertex alpha rather than 'v' texture
#attrdescription coordinate to select a color ramp.
setb csAddOutline false
#attrdescription Whether to add in an outline
setf csOutlineWidth 0.01 # min:0 max:1
#attrdescription Width of outline
setv3 csOutlineColor (1, 0.3, 0)
#attrdescription Color of the outline
setf csOutlineAlpha 1 # min:0 max:1
#attrdescription Opacity of the outline.
setb csAddEnvironmentMap false
#attrdescription Whether to add in an environment cube map.
set csEnvironmentMapTexture "reflectionoutdoorwater-envcube"
#attrdescription Environment cube map texture
setv3 csEnvironmentMapTint (1, 1, 1)
#attrdescription Color to tint the environment map
setf csEnvironmentMapStrength 0.4 # min:0 max:1
#attrdescription Overall environment map strength
setb csEnvironmentMapCameraRelative false
#attrdescription Whether cube map is camera relative
setb csParticleMode false
#attrdescription Whether material should respect particle attributes
seti csMatLayer 0 # min:-32 max:32
#attrdescription Layer for drawing. Higher numbers are drawn later.
setb csUseCameraLight true
#attrdescription Whether to use the given camera light instead of normal
#attrdescription lighting.
setv4 csCameraLightDir (1, 0, 0.5, 0)
#attrdescription Direction of camera light
#EndStdAttrBlock
define CelShadedMaterial()
material
create DetermineHardwareSupport()
if ($useFixedFunctionPath or $useSWVertexShaderPath)
shader -layer ($csMatLayer * 8)
pass -fixedFunction
colorScalar $csOutlineColor $csOutlineAlpha
create LightingStates()
stage
texture $csRampTexture
textureBlend multiply(texture diffuse) select(texture)
end
end
end
else
create CelShadedMaterialRender()
endif
end
enddef
define CelShadedMaterialRender()
# Debugging
#set csAddEdge false
#set csAddSpecular true
#set csRampTexture blackwhite
#set csRouteColorFromAlpha false
#set csAddEnvironmentMap false
#setb csAddOutline false
#setf csOutlineWidth 0.1
#setf csOutlineAlpha 1
#setb csParticleMode true
#set csSpecRampTexture "blackwhite"
#setf csShininess 1
#set stdMatBaseTextureEnabled false
#set stdMatDiffCoef (0, 0, 0)
#set stdMatFillMode wireframe
if ($csParticleMode)
attributes
attribute colorAlpha4 float4
attribute scale4 float4
attribute info4 float4
end
endif
shader -layer ($csMatLayer * 8)
if (not hasVertexFormat(color, 0))
set csRouteColorFromAlpha false
endif
vertexFormatPred position 0 true
vertexFormatPred normal 0 true
if ($stdMatBaseTextureEnabled)
vertexFormatPred texcoord 0 true
endif
vertexFormatPred color 0 $csRouteColorFromAlpha
create SetupSkinningStateAndPredicates()
create SetupMorphingStateAndPredicates()
if ($csAddOutline)
pass
if ($doSkinning or $doMorphing)
create PreprocessVertexShader()
endif
# was create VS_NormalOffsetProgram($csOutlineWidth)
shaderProgram -target vertexProgram -method assemble
bindConstants 0 -bindingID geomToCamera -constantCount 3
bindConstants 3 -bindingID cameraToClip -constantCount 4
bindConstants 7 -bindingID immediateData -data ($csOutlineWidth, 1, 0.005, 1)
if ($csParticleMode)
bindConstants 8 -bindingID immediateData -data @scale4
bindConstants 9 -bindingID immediateData -data @info4
endif
shaderSource
vs_1_1
dcl_position0 v0
dcl_normal0 v1
# transform normal to camera space
mov r3, c7 # so we can multiply below if in particle mode
mov r0.w, r3.w
m3x3 r0, v1, c0
endShaderSource
if ($csParticleMode)
shaderSource
mul r1, c8, v0
m4x3 r2, r1, c0 # position in camera space.
mul r3.x, r3.x, c9.z # aspect from info4
endShaderSource
else
shaderSource "m4x3 r2, v0, c0" # position in camera space.
endif
shaderSource
mov r2.w, r3.w
mad r2, r0, r3.x, r2 # add offset.
#mul r2.y, r2.y, c7.y # cheat away from the camera in camera space.
m4x4 r3, r2, c3 # to clip space.
mad r3.z, r3.w, c7.z, r3.z # cheat back depth in clip space: z' += eps, -> z += eps * w.
mov oPos, r3
endShaderSource
end
create NonStandardLighting()
alphaBlend srcFactor(one) add dstFactor(zero)
depthTest true -enableDepthWrite true
depthTestFunction acceptIfLess
cullmode cullCounterClockwise
if ($csOutlineAlpha < 1)
alphaBlend srcFactor(srcAlpha) add dstFactor(invSrcAlpha)
endif
fillmode $stdMatFillMode
colorScalar $csOutlineColor $csOutlineAlpha
stage
textureBlend select(colorScalar) select(colorScalar)
end
end
endif
# MAIN CEL SHADER PASS
pass
if (not $csAddOutline)
create PreprocessVertexShader()
endif
seti ts 1
if ($stdMatBaseTextureEnabled)
seti texReg $ts
seti ts ($ts + 1)
endif
if ($csAddEdge)
seti edgeReg $ts
seti ts ($ts + 1)
endif
if ($csAddSpecular)
seti specReg $ts
endif
shaderProgram -target vertexProgram -method assemble
bindConstants 0 -bindingID geomToClip -constantCount 4
bindConstants 4 -bindingID geomToCamera -constantCount 3
bindConstants 7 -bindingID immediateData -data ($csEdgeOffset, $csShininess, 0.5, 1)
bindConstants 8 -bindingID immediateData -data ($csEdgeLightDamping, 0, 0, 0)
if ($csUseCameraLight)
bindConstants 10 -data $csCameraLightDir
else
bindConstants 10 -bindingID camLocalToDirLight1 -constantCount 1
endif
if ($csParticleMode)
bindConstants 11 -bindingID immediateData -data @colorAlpha4
bindConstants 12 -bindingID immediateData -data @scale4
endif
shaderSource
vs_1_1
dcl_position0 v0
dcl_normal0 v1
dcl_texcoord0 v2
endShaderSource
if (hasVertexFormat(texcoord, 1))
shaderSource "dcl_texcoord1 v3"
endif
if ($csRouteColorFromAlpha)
shaderSource "dcl_color0 v4"
endif
# r0 = N
# r1 = H
# r2 = E
# r3 = scratch
# r4 = local position
if ($csParticleMode)
shaderSource "mul r4, v0, c12"
else
shaderSource "mov r4, v0"
endif
shaderSource
# transform position
m4x4 oPos, r4, c0
# transform normal to camera space
mov r0.w, c7.w
m3x3 r0, v1, c4
# N.L in camera space.
dp3 r3.x, r0, c10
# position in camera space
mov r2.w, c7.w
m4x3 r2, r4, c4
# vector from point to eye, E
mov r2, -r2
# normalize E
# create VS_Normalize(r2 r2)
dp3 r2.w, r2, r2
rsq r2.w, r2.w
mul r2, r2, r2.w
# find H = (L + E) / 2
add r1, c10, r2
mul r1, r1, c7.z
# normalize H
# create VS_Normalize(r1 r1)
dp3 r1, r1, r1
rsq r1, r1.w
mul r1, r1, r1.w
# N.H in camera space.
dp3 r3.y, r0, r1
# lit: (N.L) (N.S) -> clamped diff and spec
# exponent
mov r3.w, c7.y
lit r1, r3
# diffuse intensity
mov oT0.x, r1.y
endShaderSource
if ($csRouteColorFromAlpha)
shaderSource "mov oT0.y, v4.w" # pass through color0 alpha
else
if ($stdMatBaseTextureEnabled and (hasVertexFormat(texcoord, 1)))
shaderSource "mov oT0.y, v3.y" # pass through t1.v
else
shaderSource "mov oT0.y, v2.y" # pass through t0.v
endif
endif
if ($stdMatBaseTextureEnabled)
shaderSource "mov oT${texReg}, v2"
endif
if ($csAddEdge)
shaderSource "dp3 r3, r0, r2" # N . E
if ($csEdgeLightDamping != 0)
shaderSource "mad r3, r1.y, c8.x, r3" # offset by scaled diffuse term
endif
shaderSource "add oT${edgeReg}.x, c7.x, r3.x" # edge intensity + k
endif
if ($csAddSpecular)
shaderSource "mov oT${specReg}.x, r1.z" # specular intensity
endif
if ($csParticleMode)
shaderSource "mov oD0, c11" # particle colour/alpha
endif
end
#######################################################
create NonStandardLighting()
if ($csAddOutline)
depthTestFunction acceptIfLessOrEqual
endif
if ($stdMatBaseTextureEnabled)
if ($csUseCameraLight)
colorScalar ($stdMatDiffCoef * (0.25).xxx)
else
colorScalar -lightRadiance directional 0 ($stdMatDiffCoef * (0.25).xxx)
endif
else
if ($csUseCameraLight)
colorScalar $stdMatDiffCoef
else
colorScalar -lightRadiance directional 0 $stdMatDiffCoef
endif
endif
if ($csParticleMode)
alphaBlend srcFactor(srcAlpha) add dstFactor(invSrcAlpha)
endif
fillmode $stdMatFillMode
stage
texture $csRampTexture
textureMIPFilterHint disabled
textureFilterHint $csShadeFilter $csColorFilter
textureAddressing clamp clamp
textureBlend multiply(texture colorScalar) select(texture)
end
if ($stdMatBaseTextureEnabled)
# base texture stage
stage
texture $stdMatBaseTextureName
textureAddressing $stdMatBaseTextureAddressingU $stdMatBaseTextureAddressingV $stdMatBaseTextureAddressingW
textureBlend multiplyScale4(texture outRegister) multiply(texture outRegister)
end
endif
if ($csParticleMode)
stage
textureBlend multiply(outRegister diffuse) multiply(outRegister diffuse)
end
endif
if ($csAddEdge)
stage
texture $csEdgeRampTexture
textureAddressing clamp clamp
textureFilterHint $csEdgeFilter $csEdgeFilter
if ($csEdgeRampTextureAlphaInvert)
textureBlend lerpTextureAlpha(outRegister texture) select(outRegister)
else
textureBlend lerpTextureAlpha(texture outRegister) select(outRegister)
endif
end
endif
if ($csAddSpecular)
stage
texture $csSpecRampTexture
textureMIPFilterHint disabled
textureFilterHint bilinear bilinear # $csShadeFilter $csColorFilter
textureAddressing clamp clamp
textureBlend lerpTextureAlpha(texture outRegister) select(outRegister)
end
endif
end
if ($csAddEnvironmentMap)
pass
alphaBlend srcFactor(srcAlpha) add dstFactor(one)
depthTest true -enableDepthWrite false
depthTestFunction acceptIfEqual
# we must use a vertex program again, or we'll get inconsistent
# depth results with the previous pass.
shaderProgram
bindConstants 0 -bindingID geomToClip -constantCount 4
bindConstants 4 -bindingID geomToCamera -constantCount 3
bindConstants 7 -bindingID immediateData -data (0, 0, 0, 1)
shaderSource
vs_1_1
dcl_position0 v0
dcl_normal0 v1
m4x4 oPos, v0, c0
endShaderSource
if ($csEnvironmentMapCameraRelative)
shaderSource
# transform normal to camera space
mov r0.w, c7.w
m3x3 r0, v1, c4
# look up cube map.
mov oT0, r0
endShaderSource
else
shaderSource "mov oT0, v1"
endif
end
colorScalar $csEnvironmentMapTint $csEnvironmentMapStrength
fillmode $stdMatFillMode
stage
texture $csEnvironmentMapTexture
textureMIPFilterHint disabled
textureFilterHint bilinear bilinear
textureAddressing clamp clamp clamp
textureBlend multiply(texture colorScalar) multiply(texture colorScalar)
end
end
endif
end
enddef
#endshader CelShadedMaterial