ShaderCelshading

From SimsWiki
Jump to: navigation, search

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

Personal tools
Namespaces

Variants
Actions
Navigation
game select
Toolbox