# Rotoscope Shader v1.0 by Hellborg leif@gravity-music.net # 30/7/06 # Credits: # Edge detection algorithm was adopted from sobel filter by John Rittenhouse # The steep edge rotoscope effect was inspired by the Black-white shader from # XPac_27; SDK changes to render the effect on all guis were originally # posted by leahcim. ############## # VERTEX SHADER # ############# !!ARBvp1.0 OPTION ARB_position_invariant ; #from sobel filter by John Rittenhouse PARAM size = 0.0016; MUL result.texcoord[0], size, program.local[0]; END ############# # PIXEL SHADER # ############ !!ARBfp1.0 OPTION ARB_precision_hint_fastest; TEMP huetemp; #sobel edge filter algorithm by John Rittenhouse TEMP R0,R1,R2,R3,R4,R5,R6, XEdge,YEdge,sobel; PARAM off00 = {-0.5, -0.5, 0, 0 }; PARAM off01 = {-0.5, 0.0, 0, 0 }; PARAM off02 = {-0.5, 0.5, 0, 0 }; PARAM off03 = { 0.5, -0.5, 0, 0 }; PARAM off04 = { 0.5, 0.0, 0, 0 }; PARAM off05 = { 0.5, 0.5, 0, 0 }; PARAM off06 = { 0.0, -0.5, 0, 0 }; PARAM off07 = { 0.0, 0.5, 0, 0 }; PARAM specExp = { 0.5, 0, 0, 0 }; # calculate the screen texcoord in the 0.0 to 1.0 range MUL R0, fragment.position, program.env[1]; # scale by the screen non-power-of-two-adjust to give us normal screen coords in R0 MUL R0, R0, program.env[0]; # Calculate offsets MAD R1, fragment.texcoord[0], off01, R0; MAD R2, fragment.texcoord[0], off04, R0; MAD R3, fragment.texcoord[0], off06, R0; MAD R4, fragment.texcoord[0], off07, R0; # Look at the values along the center TEX R1, R1, texture[0], 2D; TEX R3, R3, texture[0], 2D; TEX R2, R2, texture[0], 2D; TEX R4, R4, texture[0], 2D; # Each of them have a scale value of two in MOV XEdge, R1; MOV YEdge, R3; ADD XEdge, XEdge, R1; ADD YEdge, YEdge, R3; SUB XEdge, XEdge, R2; SUB YEdge, YEdge, R4; SUB XEdge, XEdge, R2; SUB YEdge, YEdge, R4; # Calculate offsets for the corners MAD R1, fragment.texcoord[0], off00, R0; MAD R2, fragment.texcoord[0], off02, R0; MAD R3, fragment.texcoord[0], off03, R0; MAD R4, fragment.texcoord[0], off05, R0; # Look at the values along the center TEX R1, R1, texture[0], 2D; TEX R2, R2, texture[0], 2D; TEX R3, R3, texture[0], 2D; TEX R4, R4, texture[0], 2D; ADD XEdge, XEdge, R1; ADD YEdge, YEdge, R1; ADD XEdge, XEdge, R2; SUB YEdge, YEdge, R2; SUB XEdge, XEdge, R3; ADD YEdge, YEdge, R3; SUB XEdge, XEdge, R4; SUB YEdge, YEdge, R4; #Square each and add and take the sqrt MUL XEdge, XEdge, XEdge; MUL YEdge, YEdge, YEdge; ADD R1, XEdge, YEdge; MAX R1.x, R1.x, R1.y; MAX R1.x, R1.x, R1.z; ###write result from edge detection into sobel variable #POW sobel, R1.x, specExp.x; MOV sobel,R1; ###load texture information TEX R0, R0, texture[0], 2D; ###normalize the color hue #calculate [sum RGB] ADD huetemp.x, R0.x, R0.y; ADD huetemp.x, huetemp.x, R0.z; #calculate 1/[sum RGB] RCP huetemp.y, huetemp.x; #multiply pixel color with 1/[sum RGB] MUL R0, R0, huetemp.y; ###calculate the pixel intensity # make everything with [sum RGB] <.2 black # define darktones ([sum RGB] >.2) and store in channel z SGE huetemp.z, huetemp.x, .2; # darktones will be normalized HUE * 0.5 MUL huetemp.z, huetemp.z, 0.5; # define midtones ([sum RGB] >.8) and store in channel y SGE huetemp.y, huetemp.x, 0.8; # midtones will be normalized HUE * (0.5+0.5) MUL huetemp.y, huetemp.y, 0.5; # define brighttones ([sum RGB] >1.5) and store in channel x SGE huetemp.x, huetemp.x, 1.5; # brighttones will be normalized HUE * (0.5+0.5+1.5) MUL huetemp.x, huetemp.x, 1.5; # sum darktones+midtones+brighttones to calculate final pixel intensity ADD huetemp.x, huetemp.x, huetemp.y; ADD huetemp.x, huetemp.x, huetemp.z; #multiply pixel color with rotoscope intensity MUL R0, R0, huetemp.x; #generate edge mask -> make 1 for all regions not belonging to an edge #use 0.8 as threshold for edge detection SLT sobel.x, sobel.x, 0.1; #blend white into edge artifacts (occuring in bright areas) #find pixels with intensity>2 SGE sobel.y, huetemp.x, 2; #set the edge mask to 1 in such areas MAX sobel.x, sobel.x, sobel.y; #multiply cleaned up edge mask with final color image MUL R0, R0, sobel.x; #transfer image to output MOV result.color, R0; #MOV result.color, sobel.x; END