I'm trying to make a single shader that checks if it has collided with a mesh (with the same shader), if it has, then it should not render that collided part at all. For both meshes.
I'm trying to get this effect:
I have used a crosssection shader to achieve this but it's not what I want:
This is the shader code:
// Upgrade NOTE: replaced 'glstate.matrix.invtrans.modelview[0]' with 'UNITY_MATRIX_IT_MV'
// Upgrade NOTE: replaced 'glstate.matrix.mvp' with 'UNITY_MATRIX_MVP'
// 2 Pass Edition
Shader "cross_section_v004a"
{
Properties
{
section_depth ("section depth (x, y, z, depth)", vector) = (0,0,0,0.15)
section_color ("section color", color) = (0.5,0.1, 0.1, 1)
color_map ("color map", 2D) = "white" {}
}
SubShader
{
Pass
{
CULL OFF
CGPROGRAM //--------------
//#pragma target 3.0
#pragma vertex vertex_shader
#pragma fragment fragment_shader
#include "UnityCG.cginc"
uniform float4 section_depth;
uniform float4 section_color;
uniform sampler2D color_map;
float4x4 rotate(float3 r)
{
float3 c, s;
sincos(r.x, s.x, c.x);
sincos(r.y, s.y, c.y);
sincos(r.z, s.z, c.z);
return float4x4( c.y*c.z, -s.z, s.y, 0,
s.z, c.x*c.z, -s.x, 0,
-s.y, s.x, c.x*c.y, 0,
0, 0, 0, 1 );
}
struct a2v
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD;
float3 normal : NORMAL;
};
struct v2f
{
float4 position : POSITION;
float2 texcoord : TEXCOORD0;
float4 normal : TEXCOORD1;
float4 vertex : TEXCOORD2;
float4 mask : TEXCOORD3;
};
v2f vertex_shader( a2v IN )
{
v2f OUT;
float4x4 r = rotate(radians(section_depth.xyz) +_SinTime.xyz);
float4 c = float4(IN.vertex.xyz,1);
OUT.mask = mul(r, c);
OUT.position = mul(UNITY_MATRIX_MVP, IN.vertex);
OUT.texcoord = IN.texcoord;
r *= float4x4( 1,-1,-1, 0,
-1, 1,-1, 0,
-1,-1, 1, 0,
0, 0, 0, 1 ); // the section_depth.xyz need to be inverted !
OUT.normal = mul(r, float4(1,0,0,1));
OUT.vertex = IN.vertex;
return OUT;
}
void fragment_shader( v2f IN,
out float4 finalcolor : COLOR)
{
if(IN.mask.x > section_depth.w)
discard;
float3 N = IN.normal.xyz;
N = mul(UNITY_MATRIX_IT_MV, float4(N, 1));
//float diffuse = saturate(dot(glstate.light[0].position, N));
finalcolor = float4(0,0,0,1);
finalcolor.xyz = section_color *(0.6 +0.4);
}
ENDCG //--------------
} // Pass
//---------------------------------------------------------------------------------
Pass
{
CULL BACK
CGPROGRAM //--------------
#pragma vertex vertex_shader
#pragma fragment fragment_shader
#include "UnityCG.cginc"
uniform float4 section_depth;
uniform float4 section_color;
uniform sampler2D color_map;
float4x4 rotate(float3 r)
{
float3 c, s;
sincos(r.x, s.x, c.x);
sincos(r.y, s.y, c.y);
sincos(r.z, s.z, c.z);
return float4x4( c.y*c.z, -s.z, s.y, 0,
s.z, c.x*c.z, -s.x, 0,
-s.y, s.x, c.x*c.y, 0,
0, 0, 0, 1 );
}
struct a2v
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD;
float3 normal : NORMAL;
};
struct v2f
{
float4 position : POSITION;
float2 texcoord : TEXCOORD0;
float3 normal : TEXCOORD1;
float4 vertex : TEXCOORD2;
float4 mask : TEXCOORD3;
};
v2f vertex_shader( a2v IN )
{
v2f OUT;
float4x4 r = rotate(radians(section_depth.xyz) +_SinTime.xyz);
float4 c = float4(IN.vertex.xyz,1);
OUT.mask = mul(r, c);
OUT.position = mul(UNITY_MATRIX_MVP, IN.vertex);
OUT.texcoord = IN.texcoord;
OUT.normal = IN.normal;
OUT.vertex = IN.vertex;
return OUT;
}
void fragment_shader( v2f IN,
out float4 finalcolor : COLOR)
{
if(IN.mask.x > section_depth.w)
discard;
float3 N = IN.normal;
N = mul(UNITY_MATRIX_IT_MV, float4(N, 1));
//float diffuse = saturate(dot(glstate.light[0].position, N));
finalcolor = float4(0,0,0,1);
finalcolor.xyz = tex2D(color_map, IN.texcoord).xyz *(0.6 +0.4);
}
ENDCG //--------------
} // Pass
} // SubShader
} // Shader
However, the rest of the object should be visible, I mean to say that I don't want the parts that are NOT getting intersected to be invisible (when viewed from the invisible parts) so Stencil shaders won't or aren't doing the trick. Something like this:
I want to know what is the correct way to approach to this problem. I'm fairly new to shader programming and I don't know to solve this issue. Any help would be appreciated.
Thanks!
Related
I watched b3agz's making minecraft in unity tutorial on episode 15 there was an error when i coded the shade saying unexpected token 'uv' please help.
Here is my code for it:
Shader "Minecraft/Blocks"
{
Properties
{
_MainTex("Block Texture Atlas", 2D) = "white" {}
}
SubShader
{
Tags{"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
LOD 100
Lighting Off
Pass
{
CGPROGRAM
#pragma vertex vertFunction
#pragma fragment fragFunction
#pragma target 2.0
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION:
float2 uv : TEXCOORD0;
float4 color : COLOR;
};
struct v2f
{
float4 vertex : SV_POSITION:
float2 uv : TEXCOORD0;
float4 color : COLOR;
};
sampler2D _MainTex;
float GlobalLightLevel;
v2f vertFunction(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.color = v.color;
return o;
}
fixed4 fragFunction(v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
float localLightLevel = clamp(GlobalLightLevel + i.color.a,0,1);
clip(col.a - 1);
col = lerp(col, float4(0,0,0,1), localLightLevel);
return col;
}
ENDCG
}
}
}
Both of your struct definitions, appdata and v2f have a colon in place of a semi-colon for the float4 vertex.
The correct syntax would be:
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float4 color : COLOR;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
float4 color : COLOR;
};
I want the same effect as the Unity editor when an object clicked, same as the top on the picture.
The camera view at bottom show that no any edges on model.
I google a bit, there are many topic about wireframe and edge detection, but i cant find anything useful about showing the inner edges.
You need a wireframe shader. That link is one of many (and free).
For your specific use-case, you also want...
Rendering the object normally while the wireframe is visible
Be able to enable/disable the wireframe
Which means you need a method of knowing what object is "selected" and enabling either a shader tag which you can set once or rendering the object a second time with a new material, but have to draw the object manually every frame.
Since I had same, I wrote custom shader.
Code Listing :
Shader "DESS/WireframeShader"
{
Properties
{
_WireColor("Edges Color", Color) = (0,0,0,1)
_WireThickness("Edge Thickness", RANGE(0, 800)) = 100
_WireSmoothness("Edge Smoothness", RANGE(0, 20)) = 3
_AlbedoColor("Albedo Color", Color) = (1,1,1,1)
_MainTex("Albedo (RGB)", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType" = "Opaque" }
LOD 200
Pass
{
CGPROGRAM
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
#include "UnityCG.cginc"
#pragma vertex vert
#pragma fragment frag
#pragma geometry geom
uniform sampler2D _MainTex;
uniform float4 _MainTex_ST;
struct Input
{
float2 uv_MainTex;
};
fixed4 _WireColor;
fixed4 _AlbedoColor;
uniform float _WireThickness;
uniform float _WireSmoothness;
struct appdata
{
float4 vertex : POSITION;
float2 texcoord0 : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2g
{
float4 projSpaceVertex : SV_POSITION;
float2 uv0 : TEXCOORD0;
float4 worldSpacePosition : TEXCOORD1;
UNITY_VERTEX_OUTPUT_STEREO
};
struct g2f
{
float4 projSpaceVertex : SV_POSITION;
float2 uv0 : TEXCOORD0;
float4 worldSpacePosition : TEXCOORD1;
float4 dist : TEXCOORD2;
UNITY_VERTEX_OUTPUT_STEREO
};
v2g vert(appdata v)
{
v2g o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.projSpaceVertex = UnityObjectToClipPos(v.vertex);
o.worldSpacePosition = mul(unity_ObjectToWorld, v.vertex);
o.uv0 = TRANSFORM_TEX(v.texcoord0, _MainTex);
return o;
}
[maxvertexcount(3)]
void geom(triangle v2g i[3], inout TriangleStream<g2f> triangleStream)
{
float2 p0 = i[0].projSpaceVertex.xy / i[0].projSpaceVertex.w;
float2 p1 = i[1].projSpaceVertex.xy / i[1].projSpaceVertex.w;
float2 p2 = i[2].projSpaceVertex.xy / i[2].projSpaceVertex.w;
float2 edge0 = p2 - p1;
float2 edge1 = p2 - p0;
float2 edge2 = p1 - p0;
float area = abs(edge1.x * edge2.y - edge1.y * edge2.x);
float wireThickness = 800 - _WireThickness;
g2f o;
o.uv0 = i[0].uv0;
o.worldSpacePosition = i[0].worldSpacePosition;
o.projSpaceVertex = i[0].projSpaceVertex;
o.dist.xyz = float3((area / length(edge0)), 0.0, 0.0) * o.projSpaceVertex.w * wireThickness;
o.dist.w = 1.0 / o.projSpaceVertex.w;
UNITY_TRANSFER_VERTEX_OUTPUT_STEREO(i[0], o);
triangleStream.Append(o);
o.uv0 = i[1].uv0;
o.worldSpacePosition = i[1].worldSpacePosition;
o.projSpaceVertex = i[1].projSpaceVertex;
o.dist.xyz = float3(0.0, (area / length(edge1)), 0.0) * o.projSpaceVertex.w * wireThickness;
o.dist.w = 1.0 / o.projSpaceVertex.w;
UNITY_TRANSFER_VERTEX_OUTPUT_STEREO(i[1], o);
triangleStream.Append(o);
o.uv0 = i[2].uv0;
o.worldSpacePosition = i[2].worldSpacePosition;
o.projSpaceVertex = i[2].projSpaceVertex;
o.dist.xyz = float3(0.0, 0.0, (area / length(edge2))) * o.projSpaceVertex.w * wireThickness;
o.dist.w = 1.0 / o.projSpaceVertex.w;
UNITY_TRANSFER_VERTEX_OUTPUT_STEREO(i[2], o);
triangleStream.Append(o);
}
fixed4 frag(g2f i) : SV_Target
{
float minDistanceToEdge = min(i.dist[0], min(i.dist[1], i.dist[2])) * i.dist[3];
float4 baseColor = _AlbedoColor * tex2D(_MainTex, i.uv0);
// Early out if we know we are not on a line segment.
if (minDistanceToEdge > 0.9)
{
return fixed4(baseColor.rgb,0);
}
// Smooth our line out
float t = exp2(_WireSmoothness * -1.0 * minDistanceToEdge * minDistanceToEdge);
fixed4 finalColor = lerp(baseColor, _WireColor, t);
finalColor.a = t;
return finalColor;
}
ENDCG
}
}
FallBack "Diffuse"
}
I have drawn a circle by shader, but I can't get anti-aliasing to work.
I tried finding an answer here http://answers.unity3d.com/questions/521984/how-do-you-draw-2d-circles-and-primitives.html, but I have to use discard to draw circle.
Here is a picture of my current shader result and the shader code:
Shader "Unlit/CircleSeletor"
{
Properties
{
_BoundColor("Bound Color", Color) = (1,1,1,1)
_BgColor("Background Color", Color) = (1,1,1,1)
_MainTex("Albedo (RGB)", 2D) = "white" {}
_BoundWidth("BoundWidth", float) = 10
_ComponentWidth("ComponentWidth", float) = 100
}
SubShader{
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag Lambert alpha
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
sampler2D _MainTex;
float _BoundWidth;
fixed4 _BoundColor;
fixed4 _BgColor;
float _ComponentWidth;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
float4 _MainTex_ST;
v2f vert(appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
float antialias(float w, float d, float r) {
return 1-(d-r-w/2)/(2*w);
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 c = tex2D(_MainTex,i.uv);
float x = i.uv.x;
float y = i.uv.y;
float dis = sqrt(pow((0.5 - x), 2) + pow((0.5 - y), 2));
if (dis > 0.5) {
discard;
} else {
float innerRadius = (_ComponentWidth * 0.5 - _BoundWidth) / _ComponentWidth;
if (dis > innerRadius) {
c = _BoundColor;
//c.a = c.a*antialias(_BoundWidth, dis, innerRadius);
}
else {
c = _BgColor;
}
}
return c;
}
ENDCG
}
}
}
It's really easy to apply anti-alias to a circle.
1.First, you need 3 variables to do this. Get the radius, distance of the circle. Also create a float value(let's called that borderSize) that can be used to determine how far the anti-alias should go. The radius, distance and borderSize are the three variables.
2.Find the t with smoothstep function using those 3 variables from #1.
float t = smoothstep(radius + borderSize, radius - borderSize, distance);
3.Mix the color before returning it.
Let's say that _BoundColor is the circle fill color and _BgColor is the background color.
If using GLSL using the mix function. If using Unity, use the lerp function. Both function are interchanging and the parameters are the-same.
col = lerp(_BoundColor, _BgColor, t);
The t is from #2. You can now return col in the fragment function.
These are the 3 steps put together:
if (dis > radius) {
float t = smoothstep(radius + borderSize, radius - borderSize, distance);
col = lerp(_BoundColor, _BgColor, t);
}
else {
float t = smoothstep(radius + borderSize, radius - borderSize, distance);
col = lerp(_BoundColor, _BgColor, t);
}
return col;
OUTPUT WITHOUT ANTI-ALIASING:
OUTPUT WITH ANTI-ALIASING(4.5 Threshold):
Finally, the whole code(Tested on PC and Android but should work on iOS too)
Shader "Unlit/Circle Anti-Aliasing"
{
Properties
{
_BoundColor("Bound Color", Color) = (0,0.5843137254901961,1,1)
_BgColor("Background Color", Color) = (0.1176470588235294,0,0.5882352941176471,1)
_circleSizePercent("Circle Size Percent", Range(0, 100)) = 50
_border("Anti Alias Border Threshold", Range(0.00001, 5)) = 0.01
}
SubShader
{
Tags { "RenderType" = "Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
float _border;
fixed4 _BoundColor;
fixed4 _BgColor;
float _circleSizePercent;
struct v2f
{
float2 uv : TEXCOORD0;
};
v2f vert(
float4 vertex : POSITION, // vertex position input
float2 uv : TEXCOORD0, // texture coordinate input
out float4 outpos : SV_POSITION // clip space position output
)
{
v2f o;
o.uv = uv;
outpos = UnityObjectToClipPos(vertex);
return o;
}
float2 antialias(float radius, float borderSize, float dist)
{
float t = smoothstep(radius + borderSize, radius - borderSize, dist);
return t;
}
fixed4 frag(v2f i, UNITY_VPOS_TYPE screenPos : VPOS) : SV_Target
{
float4 col;
float2 center = _ScreenParams.xy / 2;
float maxradius = length(center);
float radius = maxradius*(_circleSizePercent / 100);
float dis = distance(screenPos.xy, center);
if (dis > radius) {
float aliasVal = antialias(radius, _border, dis);
col = lerp(_BoundColor, _BgColor, aliasVal); //NOT needed but incluse just incase
}
else {
float aliasVal = antialias(radius, _border, dis);
col = lerp(_BoundColor, _BgColor, aliasVal);
}
return col;
}
ENDCG
}
}
}
Try this:
Shader "Unlit/CircleSeletor"
{
Properties
{
_BoundColor("Bound Color", Color) = (1,1,1,1)
_BgColor("Background Color", Color) = (1,1,1,1)
_MainTex("Albedo (RGB)", 2D) = "white" {}
_BoundWidth("BoundWidth", float) = 10
_ComponentWidth("ComponentWidth", float) = 100
}
SubShader
{
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag Lambert alpha
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
sampler2D _MainTex;
float _BoundWidth;
fixed4 _BoundColor;
fixed4 _BgColor;
float _ComponentWidth;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
float4 _MainTex_ST;
v2f vert(appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
float antialias(float w, float d, float r) {
return 1 - (d - r - w / 2) / (2 * w);
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 c = tex2D(_MainTex,i.uv);
float x = i.uv.x;
float y = i.uv.y;
float dis = sqrt(pow((0.5 - x), 2) + pow((0.5 - y), 2));
if (dis > 0.5) {
c.a = 0;
discard;
}
else {
float innerRadius = (_ComponentWidth * 0.5 - _BoundWidth) / _ComponentWidth;
if (dis > innerRadius) {
c = _BoundColor;
//c.a = c.a*antialias(_BoundWidth, dis, innerRadius);
}
else {
c = _BgColor;
}
}
return c;
}
ENDCG
}
GrabPass{
"_MainTex2"
}
Pass
{
Blend One zero
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
fixed4 color : COLOR;
};
struct v2f
{
float4 pos : SV_POSITION;
fixed4 color : COLOR;
float4 scrPos : TEXCOORD0;
};
float4 _MainTex_ST;
v2f vert(appdata v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.scrPos = ComputeScreenPos(o.pos);
o.color = v.color;
return o;
}
sampler2D _MainTex2;
float4 _MainTex2_TexelSize;
fixed4 frag(v2f i) : SV_Target
{
float2 uv = (i.scrPos.xy / i.scrPos.w);
fixed4 c = tex2D(_MainTex2, uv );
fixed4 up = tex2D(_MainTex2, uv + fixed2(0, _MainTex2_TexelSize.y));
fixed4 down = tex2D(_MainTex2, uv - fixed2(0, _MainTex2_TexelSize.y));
fixed4 left = tex2D(_MainTex2, uv - fixed2(_MainTex2_TexelSize.x, 0));
fixed4 right = tex2D(_MainTex2, uv + fixed2(_MainTex2_TexelSize.x, 0));
c.rgb = (c.rgb + up.rgb + down.rgb + left.rgb + right.rgb) / 5;
c.a = (c.a + up.a + down.a + left.a + right.a) / 5;
return c;
}
ENDCG
}
}
}
After first pass I GrabPass result and apply anti-alias in second pass by averaging border pixels.
I'm new to writing shaders and I'm working on a practice geometry shader. The goal of the shader is to make the "normal" pass produce transparent pixels such that the object is invisible, while the "geometry" pass will take each triangle, redraw in the same place as the original but colored black. Thus, I expect the output to be the original object, but black. However, my geometry pass seems to not produce any output I can see:
Here is the code I currently have for the shader.
Shader "Outlined/Silhouette2" {
Properties
{
_Color("Color", Color) = (0,0,0,1)
_MainColor("Main Color", Color) = (1,1,1,1)
_Thickness("Thickness", float) = 4
_MainTex("Main Texture", 2D) = "white" {}
}
SubShader
{
Tags{ "Queue" = "Geometry" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
Cull Back
ZTest always
Pass
{
Stencil{
Ref 1
Comp always
Pass replace
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct v2g
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 viewT : TANGENT;
float3 normals : NORMAL;
};
struct g2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 viewT : TANGENT;
float3 normals : NORMAL;
};
float4 _LightColor0;
sampler2D _MainTex;
float4 _MainColor;
v2g vert(appdata_base v)
{
v2g OUT;
OUT.pos = mul(UNITY_MATRIX_MVP, v.vertex);
OUT.uv = v.texcoord;
OUT.normals = v.normal;
OUT.viewT = ObjSpaceViewDir(v.vertex);
return OUT;
}
half4 frag(g2f IN) : COLOR
{
//this renders nothing, if you want the base mesh and color
//fill this in with a standard fragment shader calculation
float4 texColor = tex2D(_MainTex, IN.uv);
float3 normal = mul(float4(IN.normals, 0.0), _Object2World).xyz;
float3 normalDirection = normalize(normal);
float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz * -1);
float3 diffuse = _LightColor0.rgb * _MainColor.rgb * max(0.0, dot(normalDirection, lightDirection));
texColor = float4(diffuse,1) * texColor;
//
//return texColor;
return float4(0, 0, 0, 0);
}
ENDCG
}
Pass
{
Stencil{
Ref 0
Comp equal
}
CGPROGRAM
#include "UnityCG.cginc"
#pragma target 4.0
#pragma vertex vert
#pragma geometry geom
#pragma fragment frag
half4 _Color;
float _Thickness;
struct v2g
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float4 local_pos: TEXCOORD1;
float3 viewT : TANGENT;
float3 normals : NORMAL;
};
struct g2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 viewT : TANGENT;
float3 normals : NORMAL;
};
v2g vert(appdata_base v)
{
v2g OUT;
OUT.pos = mul(UNITY_MATRIX_MVP, v.vertex);
OUT.local_pos = v.vertex;
OUT.uv = v.texcoord;
OUT.normals = v.normal;
OUT.viewT = ObjSpaceViewDir(v.vertex);
return OUT;
}
[maxvertexcount(12)]
void geom(triangle v2g IN[3], inout TriangleStream<g2f> triStream)
{
g2f OUT;
OUT.pos = IN[0].pos;
OUT.uv = IN[0].uv;
OUT.viewT = IN[0].viewT;
OUT.normals = IN[0].normals;
triStream.Append(OUT);
OUT.pos = IN[1].pos;
OUT.uv = IN[1].uv;
OUT.viewT = IN[1].viewT;
OUT.normals = IN[1].normals;
triStream.Append(OUT);
OUT.pos = IN[2].pos;
OUT.uv = IN[2].uv;
OUT.viewT = IN[2].viewT;
OUT.normals = IN[2].normals;
triStream.Append(OUT);
}
half4 frag(g2f IN) : COLOR
{
_Color.a = 1;
return _Color;
}
ENDCG
}
}
FallBack "Diffuse"
}
Since all I'm doing is taking the same triangles I've been given and appending them to the triangle stream I'm not sure what I could be doing wrong to cause nothing to appear. Anyone know why this is happening?
I notice that you don't call
triStrem.RestartStrip(); after feeding in 3 vertices of a triangle in your geometry shader.
This informs the stream that a particular triangle strip has ended, and a new triangle strip will begin. If you don't do this, each (single) vertex passed to the stream will add on to the existing triangle strip, using the triangle strip pattern: https://en.wikipedia.org/wiki/Triangle_strip
I'm fairly new to geo-shaders myself, so I'm not sure if this is your issue or not, I don't THINK the RestartStrip function is called automatically at the end of each geomerty-shader, but have not tested this. Rather I think it gets called automatically only when you you reach the maxvertexcount. For a single triangle, I would set the maxvertexcount to 3, not the 12 you have now.
(I also know it can be tough to get ANY shader answers so figgured I'd try to help.)
I was implementing a lightmap into my shader and then I got this error and I can't figure out what it means. Does any one know how I can fix this? It started happening since I added the light map in.
Shader error in 'Custom/HauntedHouseShader': incorrect number of arguments to numeric-type constructor at line 84 (on d3d11)
This is my code:
Shader "Custom/HauntedHouseShader" {
Properties {
_Texture ("Diffuse", 2D) = "white"{}
_Color ("Color", Color) = (0,0,0,1)
_TilingX ("TilingX", float) = 1
_TilingZ ("TilingZ", float) = 1
}
SubShader {
Pass{
Tags { "LightMode" = "ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
float4 _Color;
sampler2D _Texture;
float _TilingX;
float _TilingZ;
sampler2D unity_Lightmap;
float4 unity_LightmapST;
float4 _LightColor0;
struct VertexOutput
{
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD1;
float4 tex : TEXCOORD0;
float3 normalDir : TEXCOORD2;
float2 tex2 : TEXCOORD3;
};
struct VertexInput
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct FragmentOutput
{
float4 color : COLOR;
};
VertexOutput vert (VertexInput i)
{
VertexOutput VOUT;
VOUT.tex = i.texcoord;
VOUT.pos = mul(UNITY_MATRIX_MVP,i.vertex);
VOUT.posWorld = mul(_Object2World,i.vertex);
VOUT.normalDir = normalize( mul(float4(i.normal,0.0),_World2Object).xyz);
VOUT.tex2 = i.texcoord.xy * unity_LightmapST.xy + unity_LightmapST.zw;
return VOUT;
}
FragmentOutput frag(VertexOutput v)
{
FragmentOutput FOUT;
float3 lightDir;
float atten;
if(_WorldSpaceLightPos0.w == 0.0){
atten = 1;
lightDir = normalize(_WorldSpaceLightPos0.xyz);
}else
{
float3 fragmentToLightSource = _WorldSpaceLightPos0.xyz - v.posWorld.xyz;
float dist = length(fragmentToLightSource);
atten = 1.0/dist;
lightDir = normalize(fragmentToLightSource);
}
float3 lightMap = float3(DecodeLightmap(tex2D(unity_Lightmap, v.tex2.xy)),0.0);
float3 normalDir = v.normalDir;
float4 tex = tex2D(_Texture, float4(v.posWorld.x * _TilingX,v.posWorld.z * _TilingZ,0.0,0.0));
float3 diffuseReflection = atten * _LightColor0.xyz * saturate(dot(normalDir, lightDir));
float3 lightFinal = UNITY_LIGHTMODEL_AMBIENT.xyz + diffuseReflection;
float4 col = float4(tex.xyz * lightFinal * _Color + lightMap,0.0);
FOUT.color = col;
return FOUT;
}
ENDCG
}
Pass{
Tags { "LightMode" = "ForwardAdd"}
Blend One One
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
float4 _Color;
sampler2D _Texture;
float _TilingX;
float _TilingZ;
float4 _LightColor0;
struct VertexOutput
{
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD1;
float4 tex : TEXCOORD0;
float3 normalDir : TEXCOORD2;
};
struct VertexInput
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 tangent : TANGENT;
};
struct FragmentOutput
{
float4 color : COLOR;
};
VertexOutput vert (VertexInput i)
{
VertexOutput VOUT;
VOUT.tex = i.texcoord;
VOUT.pos = mul(UNITY_MATRIX_MVP,i.vertex);
VOUT.posWorld = mul(_Object2World,i.vertex);
VOUT.normalDir = normalize( mul(float4(i.normal,0.0),_World2Object).xyz);
return VOUT;
}
FragmentOutput frag(VertexOutput v)
{
FragmentOutput FOUT;
float3 lightDir;
float atten;
if(_WorldSpaceLightPos0.w == 0.0){
atten = 1;
lightDir = normalize(_WorldSpaceLightPos0.xyz);
}else
{
float3 fragmentToLightSource = _WorldSpaceLightPos0.xyz - v.posWorld.xyz;
float dist = length(fragmentToLightSource);
atten = 1.0/dist;
lightDir = normalize(fragmentToLightSource);
}
float3 normalDir = v.normalDir;
float4 tex = tex2D(_Texture, float4(v.posWorld.x * _TilingX,v.posWorld.z * _TilingZ,0.0,0.0));
float3 diffuseReflection = atten * _LightColor0.xyz * saturate(dot(normalDir, lightDir));
float3 lightFinal = UNITY_LIGHTMODEL_AMBIENT.xyz + diffuseReflection;
float4 col = float4(tex.xyz * lightFinal * _Color ,0.0);
FOUT.color = col;
return FOUT;
}
ENDCG
}
}
FallBack "Diffuse"
}
Well the error is from the line
float3 lightMap = float3(DecodeLightmap(tex2D(unity_Lightmap, v.tex2.xy)),0.0);
which is a clearly a typo, since here you try to construct float3 from 2 arguments float3 and float, which is meaningless. Maybe you meant:
float3 lightMap = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, v.tex2.xy));
or
float3 lightMap = float3(DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, v.tex2.xy)).xy, 0.0);
I assume that what makes the confusion here is that error points to a wrong line number, the reason is that Unity 5 compilation makes some automatic converions of older APIs in your shader source (quite confusing), try reloading the file and see how it actually looks.