removing artifact on reverse xray shader

So I found that by putting a reverse gradient map into the xray shader it can produce a pseudo-glow effect

The only problem is, if you notice around the rim, there is a very thin 1 pixel outline of the sphere. This 1 pixel outline kinda jumps and pops around the sphere depending on the angle you look at it. It seems like at the .0001 facing ratio, some quirk in the calculation happens and it makes it fully red at the very very edge.

I don’t know how to get rid of this. Does anyone know how to correct this?

Here is the code

Shader "XRay" {

    Properties {
        _Color ("Tint (RGB)", Color) = (1,1,1,1)
        _RampTex ("Facing Ratio Ramp (RGB)", 2D) = "white" {}
    }
	
    SubShader {
	
        ZWrite Off
		Cull Back

        Blend One One
		
        Pass {
           
            CGPROGRAM
            #pragma vertex vert
            #include "UnityCG.cginc"

			struct appdata {
				float4 vertex;
				float3 normal;
				float4 texcoord;
			};

            struct v2f {
				float4 pos : POSITION;
				float4 color : COLOR;
				float fog : FOGC;				
                float4 uv : TEXCOORD0;
            };
           
            v2f vert (appdata v) {
                v2f o;
				
				o.pos = mul( glstate.matrix.mvp, v.vertex );		
				
                float3 viewDir = normalize(ObjSpaceViewDir(v.vertex));
                o.uv = float4( dot(viewDir,v.normal), 0.5, 0.0, 1.0 );
                return o;
            }
            ENDCG

            SetTexture [_RampTex] {constantColor[_Color] combine texture * constant}
			
        }
    }
    Fallback Off
}

My guess would be that imprecision when the dot product is supposed to be zero is giving you a negative U coordinate. Try clamping the result:

saturate(dot(viewDir,v.normal))

thank you for that

albeit 0,1 was not enough

I found the clamp command and put that in for .1 to 1.0

o.uv = float4( clamp(dot(viewDir,v.normal),0.1,1.0), 0.5, 0.0, 1.0 );

that fixed it

Another possible fix is to make sure your ramp texture is set to Clamp.

how do I clamp the texture?

The Wrap Mode setting can be changed at the top of the Texture’s Inspector:

http://unity3d.com/support/documentation/Components/class-Texture2D.html

that helped, but still not completely gone unless I turned the aniso all the way up, which wont work. So I gotta keep the clamp in the shader file too

Try just turning off mipmaps for the ramp. They aren’t really saving you much space with a one-dimensional texture. Then you shouldn’t need aniso, and the texture settings clamping should be adequate to get rid of the fringe.

that like ALMOST gets rid of it, theres maybe like 20 single pixel that sparkle around the rim… but still had to clamp it in the shader to get rid of those

ALRIGHT SO I HAVE officially managed to combine the reverse xray shader with the toon shader and produce a pseudo glow effect over a diffuse surface.

It just uses the toon shader to extrude the mesh, then instead of making it black, it applies the xray shader effect to the extruded mesh.

The only problem is that, if you notice in the center of the spheres, theres a small chunk that is not covered in the glow effect. This is done because I think the toon shader does not extrude the mesh in xy and z, but rather only x and y. So the extruded mesh of the toon shader actually does intersect the sphere in the middle.

How would I go about telling it draw the extruded mesh with the xray effect first, and the diffuse surface second? So then they don’t intersect?

Also how would I go about telling it to draw the diffuse first, and the xray/toon effect second, so then you only see the glow behind the object and not covering it? I’ve tried Cull Front, but, apparently the xray effect is not on both side of the surfaces, so that just makes it dissapear entirely.

Here is the code

Shader "Toon Diffuse" {
	Properties {
		_Color ("Main Color", Color) = (.5,.5,.5,1)
		_OutlineColor ("Outline Color", Color) = (0,0,0,1)
		_Outline ("Outline width", Range (.002, 0.03)) = .005
		_MainTex ("Base (RGB)", 2D) = "white" { }
        _RampTex ("Facing Ratio Ramp (RGB)", 2D) = "white" {}
		//_ToonShade ("ToonShader Cubemap(RGB)", CUBE) = "" { Texgen CubeNormal }
	}

	SubShader {

			UsePass "Diffuse/BASE"
					
		Pass {
			Name "OUTLINE"
			cull back
			ZWrite Off
			
CGPROGRAM
#pragma vertex vert
#include "UnityCG.cginc"

struct appdata {
    float4 vertex;
    float3 normal;
	float4 texcoord;
};

struct v2f {
	float4 pos : POSITION;
	float4 color : COLOR;
	float fog : FOGC;
	float4 uv : TEXCOORD0;
};

uniform float _Outline;

v2f vert(appdata v) {
	v2f o;
	
	//toon shader extrusion
	o.pos = mul(glstate.matrix.mvp, v.vertex);
	float3 norm = mul ((float3x3)glstate.matrix.modelview[0], v.normal);
	norm.x *= glstate.matrix.projection[0][0];
	norm.y *= glstate.matrix.projection[1][1];

	o.pos.xy += norm.xy * 50 * _Outline;
	
	//multiplying by o.pos.z changes glow size based on distance from camera
	//o.pos.xy += norm.xy * o.pos.z * _Outline;

	//XRAY effect
	float3 viewDir = normalize(ObjSpaceViewDir(v.vertex));
	o.uv = float4( clamp(dot(viewDir,v.normal),0.1,1.0), 0.0, 0.0, 0.0 );
		
	o.fog = o.pos.z;

	return o;
}
ENDCG

			Blend One One
            SetTexture [_RampTex] {constantColor[_OutlineColor] combine texture * constant}

		}
		
	}

}

Now I know that you can just move the UsePass “Diffuse/Base” command after the Pass{} that has the CGProgram. But the problem with this is. The CG Program and the Xray effect needs the Blend One One setting to work properly. And if I move the UsePass “Diffuse/Base” after the CGProgram, and thus the Blend One One command, then it obviously applies the Blend One One to the diffuse pass turning the object transparent. Which is interesting in itself, but not what I need.

How do I keep the blend One One on the xray effect, then have it put on the Diffuse Pass second, but without the Blend One One effect?

I FIXED THIS SHIT

Shader "Toon Diffuse" {
	Properties {
		_Color ("Main Color", Color) = (.5,.5,.5,1)
		_OutlineColor ("Outline Color", Color) = (0,0,0,1)
		_Outline ("Outline width", Range (.002, 0.03)) = .005
		_MainTex ("Base (RGB)", 2D) = "white" { }
        _RampTex ("Facing Ratio Ramp (RGB)", 2D) = "white" {}
		//_ToonShade ("ToonShader Cubemap(RGB)", CUBE) = "" { Texgen CubeNormal }
	}

	SubShader {

			UsePass "Diffuse/BASE"
					
		Pass {
			Name "OUTLINE"
			cull back
			ZWrite Off
			
CGPROGRAM
#pragma vertex vert
#include "UnityCG.cginc"

struct appdata {
    float4 vertex;
    float3 normal;
	float4 texcoord;
};

struct v2f {
	float4 pos : POSITION;
	float4 color : COLOR;
	float fog : FOGC;
	float4 uv : TEXCOORD0;
};

uniform float _Outline;

v2f vert(appdata v) {
	v2f o;
	
	//toon shader extrusion
	o.pos = mul(glstate.matrix.mvp, v.vertex);
	float3 norm = mul ((float3x3)glstate.matrix.modelview[0], v.normal);
	norm.x *= glstate.matrix.projection[0][0];
	norm.y *= glstate.matrix.projection[1][1];
	norm.z =  1;

	o.pos.xy += norm.xy * 50 * _Outline;

	//Puts glow in front of object
 //o.pos.z -= .0001;
	
	//Puts glow behind object
	o.pos.z += .01;

	//XRAY effect
	float3 viewDir = normalize(ObjSpaceViewDir(v.vertex));
	o.uv = float4( clamp(dot(viewDir,v.normal),0.1,1.0), 0.0, 0.0, 0.0 );
		
	o.fog = o.pos.z;

	return o;
}
ENDCG

			Blend One One
            SetTexture [_RampTex] {constantColor[_OutlineColor] combine texture * constant}

		}
		
	}

}

:smile: :smile: :smile: :smile:

In the comments it has two lines, one commented out that says

//Puts glow in front of object
//o.pos.z -= .0001;

and the other that says

//Puts glow behind object
o.pos.z += .01;

You just uncomment one, and comment the other to switch where you want the glow to be. Then the glow will appear behind, or in front of the object

Can I put this on the wiki?

Also, if someone gets benefit from this. Could you please do me a favor and explain to me how the hell this works? I still have no clue. I honestly hacked this together by trial and error :smile:

thanks!

btw, got some work to be able to use this AND the xray

you should change the names of the “o” and “vert”

I think this shader is great for highlighting objects.

But I can’t get it to run in my project.
It says:
“Shader has error or is not supported on this graphics card
Errors: No Subshader supported on this graphics card. (I have tested it on many differnet machines)”

The XRay shader at the beginning of the thread runs nice.
I think there is a Problem with Passes, but I don’t know.
I am not a programmer so, maybe you can help me how to use ist.