为什么我的着色器不使用颜色渲染子着色器?
Why my shader doesn't render the subshader with the color?
我找到了一个着色器,它是一个没有对角线的线框着色器(参见参考文献 here). I'd like to fill is with color so I added a subshader that will render the color (taking from here)。
两个着色器都可以独立工作,但是当我尝试将它们组合时,第二个着色器的颜色没有渲染。可能是什么问题?
这是我的代码:
Shader "Custom/TransparentSingleColorShader" {
Properties{
_Color("Color", Color) = (1.0, 1.0, 1.0, 1.0)
[PowerSlider(3.0)]
_WireframeVal("Wireframe width", Range(0., 0.5)) = 0.05
_FrontColor("Front color", color) = (1., 1., 1., 1.)
_BackColor("Back color", color) = (1., 1., 1., 1.)
[Toggle] _RemoveDiag("Remove diagonals?", Float) = 0.
}
SubShader
{
Tags { "Queue" = "Geometry" "RenderType" = "Opaque" }
Pass
{
Cull Front
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma geometry geom
// Change "shader_feature" with "pragma_compile" if you want set this keyword from c# code
#pragma shader_feature __ _REMOVEDIAG_ON
#include "UnityCG.cginc"
struct v2g {
float4 worldPos : SV_POSITION;
};
struct g2f {
float4 pos : SV_POSITION;
float3 bary : TEXCOORD0;
};
v2g vert(appdata_base v) {
v2g o;
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
return o;
}
[maxvertexcount(3)]
void geom(triangle v2g IN[3], inout TriangleStream<g2f> triStream) {
float3 param = float3(0., 0., 0.);
#if _REMOVEDIAG_ON
float EdgeA = length(IN[0].worldPos - IN[1].worldPos);
float EdgeB = length(IN[1].worldPos - IN[2].worldPos);
float EdgeC = length(IN[2].worldPos - IN[0].worldPos);
if (EdgeA > EdgeB && EdgeA > EdgeC)
param.y = 1.;
else if (EdgeB > EdgeC && EdgeB > EdgeA)
param.x = 1.;
else
param.z = 1.;
#endif
g2f o;
o.pos = mul(UNITY_MATRIX_VP, IN[0].worldPos);
o.bary = float3(1., 0., 0.) + param;
triStream.Append(o);
o.pos = mul(UNITY_MATRIX_VP, IN[1].worldPos);
o.bary = float3(0., 0., 1.) + param;
triStream.Append(o);
o.pos = mul(UNITY_MATRIX_VP, IN[2].worldPos);
o.bary = float3(0., 1., 0.) + param;
triStream.Append(o);
}
float _WireframeVal;
fixed4 _BackColor;
fixed4 frag(g2f i) : SV_Target {
if (!any(bool3(i.bary.x < _WireframeVal, i.bary.y < _WireframeVal, i.bary.z < _WireframeVal)))
discard;
return _BackColor;
}
ENDCG
}
Pass
{
Cull Back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma geometry geom
// Change "shader_feature" with "pragma_compile" if you want set this keyword from c# code
#pragma shader_feature __ _REMOVEDIAG_ON
#include "UnityCG.cginc"
struct v2g {
float4 worldPos : SV_POSITION;
};
struct g2f {
float4 pos : SV_POSITION;
float3 bary : TEXCOORD0;
};
v2g vert(appdata_base v) {
v2g o;
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
return o;
}
[maxvertexcount(3)]
void geom(triangle v2g IN[3], inout TriangleStream<g2f> triStream) {
float3 param = float3(0., 0., 0.);
#if _REMOVEDIAG_ON
float EdgeA = length(IN[0].worldPos - IN[1].worldPos);
float EdgeB = length(IN[1].worldPos - IN[2].worldPos);
float EdgeC = length(IN[2].worldPos - IN[0].worldPos);
if (EdgeA > EdgeB && EdgeA > EdgeC)
param.y = 1.;
else if (EdgeB > EdgeC && EdgeB > EdgeA)
param.x = 1.;
else
param.z = 1.;
#endif
g2f o;
o.pos = mul(UNITY_MATRIX_VP, IN[0].worldPos);
o.bary = float3(1., 0., 0.) + param;
triStream.Append(o);
o.pos = mul(UNITY_MATRIX_VP, IN[1].worldPos);
o.bary = float3(0., 0., 1.) + param;
triStream.Append(o);
o.pos = mul(UNITY_MATRIX_VP, IN[2].worldPos);
o.bary = float3(0., 1., 0.) + param;
triStream.Append(o);
}
float _WireframeVal;
fixed4 _FrontColor;
fixed4 frag(g2f i) : SV_Target {
if (!any(bool3(i.bary.x <= _WireframeVal, i.bary.y <= _WireframeVal, i.bary.z <= _WireframeVal)))
discard;
return _FrontColor;
}
ENDCG
}
}
SubShader{
Tags { "RenderType" = "Transparent" "Queue" = "Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
Cull Front
LOD 200
CGPROGRAM
#pragma surface surf Lambert
fixed4 _Color;
// Note: pointless texture coordinate. I couldn't get Unity (or Cg)
// to accept an empty Input structure or omit the inputs.
struct Input {
float2 uv_MainTex;
};
void surf(Input IN, inout SurfaceOutput o) {
o.Albedo = _Color.rgb;
o.Emission = _Color.rgb; // * _Color.a;
o.Alpha = _Color.a;
}
ENDCG
}
FallBack "Diffuse"
}
这是照片:右边一张(我想要它的样子,但没有对角线)左边一张(我想要它的样子,但颜色不见了)
子着色器并不像您认为的那样。子着色器用于为同一着色器提供不同的兼容性级别。 Unity 将始终 select 第一个兼容的子着色器 - 例如,如果第一个使用曲面细分,而您的硬件不支持它,Unity 将在列表中向下查找,直到找到适合您的机器的子着色器。
您想要的是第二个渲染通道。表面着色器生成自己的通道,因此您只需将代码粘贴到第一个着色器的末尾,即最后一个通道之后。
我找到了一个着色器,它是一个没有对角线的线框着色器(参见参考文献 here). I'd like to fill is with color so I added a subshader that will render the color (taking from here)。
两个着色器都可以独立工作,但是当我尝试将它们组合时,第二个着色器的颜色没有渲染。可能是什么问题?
这是我的代码:
Shader "Custom/TransparentSingleColorShader" {
Properties{
_Color("Color", Color) = (1.0, 1.0, 1.0, 1.0)
[PowerSlider(3.0)]
_WireframeVal("Wireframe width", Range(0., 0.5)) = 0.05
_FrontColor("Front color", color) = (1., 1., 1., 1.)
_BackColor("Back color", color) = (1., 1., 1., 1.)
[Toggle] _RemoveDiag("Remove diagonals?", Float) = 0.
}
SubShader
{
Tags { "Queue" = "Geometry" "RenderType" = "Opaque" }
Pass
{
Cull Front
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma geometry geom
// Change "shader_feature" with "pragma_compile" if you want set this keyword from c# code
#pragma shader_feature __ _REMOVEDIAG_ON
#include "UnityCG.cginc"
struct v2g {
float4 worldPos : SV_POSITION;
};
struct g2f {
float4 pos : SV_POSITION;
float3 bary : TEXCOORD0;
};
v2g vert(appdata_base v) {
v2g o;
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
return o;
}
[maxvertexcount(3)]
void geom(triangle v2g IN[3], inout TriangleStream<g2f> triStream) {
float3 param = float3(0., 0., 0.);
#if _REMOVEDIAG_ON
float EdgeA = length(IN[0].worldPos - IN[1].worldPos);
float EdgeB = length(IN[1].worldPos - IN[2].worldPos);
float EdgeC = length(IN[2].worldPos - IN[0].worldPos);
if (EdgeA > EdgeB && EdgeA > EdgeC)
param.y = 1.;
else if (EdgeB > EdgeC && EdgeB > EdgeA)
param.x = 1.;
else
param.z = 1.;
#endif
g2f o;
o.pos = mul(UNITY_MATRIX_VP, IN[0].worldPos);
o.bary = float3(1., 0., 0.) + param;
triStream.Append(o);
o.pos = mul(UNITY_MATRIX_VP, IN[1].worldPos);
o.bary = float3(0., 0., 1.) + param;
triStream.Append(o);
o.pos = mul(UNITY_MATRIX_VP, IN[2].worldPos);
o.bary = float3(0., 1., 0.) + param;
triStream.Append(o);
}
float _WireframeVal;
fixed4 _BackColor;
fixed4 frag(g2f i) : SV_Target {
if (!any(bool3(i.bary.x < _WireframeVal, i.bary.y < _WireframeVal, i.bary.z < _WireframeVal)))
discard;
return _BackColor;
}
ENDCG
}
Pass
{
Cull Back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma geometry geom
// Change "shader_feature" with "pragma_compile" if you want set this keyword from c# code
#pragma shader_feature __ _REMOVEDIAG_ON
#include "UnityCG.cginc"
struct v2g {
float4 worldPos : SV_POSITION;
};
struct g2f {
float4 pos : SV_POSITION;
float3 bary : TEXCOORD0;
};
v2g vert(appdata_base v) {
v2g o;
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
return o;
}
[maxvertexcount(3)]
void geom(triangle v2g IN[3], inout TriangleStream<g2f> triStream) {
float3 param = float3(0., 0., 0.);
#if _REMOVEDIAG_ON
float EdgeA = length(IN[0].worldPos - IN[1].worldPos);
float EdgeB = length(IN[1].worldPos - IN[2].worldPos);
float EdgeC = length(IN[2].worldPos - IN[0].worldPos);
if (EdgeA > EdgeB && EdgeA > EdgeC)
param.y = 1.;
else if (EdgeB > EdgeC && EdgeB > EdgeA)
param.x = 1.;
else
param.z = 1.;
#endif
g2f o;
o.pos = mul(UNITY_MATRIX_VP, IN[0].worldPos);
o.bary = float3(1., 0., 0.) + param;
triStream.Append(o);
o.pos = mul(UNITY_MATRIX_VP, IN[1].worldPos);
o.bary = float3(0., 0., 1.) + param;
triStream.Append(o);
o.pos = mul(UNITY_MATRIX_VP, IN[2].worldPos);
o.bary = float3(0., 1., 0.) + param;
triStream.Append(o);
}
float _WireframeVal;
fixed4 _FrontColor;
fixed4 frag(g2f i) : SV_Target {
if (!any(bool3(i.bary.x <= _WireframeVal, i.bary.y <= _WireframeVal, i.bary.z <= _WireframeVal)))
discard;
return _FrontColor;
}
ENDCG
}
}
SubShader{
Tags { "RenderType" = "Transparent" "Queue" = "Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
Cull Front
LOD 200
CGPROGRAM
#pragma surface surf Lambert
fixed4 _Color;
// Note: pointless texture coordinate. I couldn't get Unity (or Cg)
// to accept an empty Input structure or omit the inputs.
struct Input {
float2 uv_MainTex;
};
void surf(Input IN, inout SurfaceOutput o) {
o.Albedo = _Color.rgb;
o.Emission = _Color.rgb; // * _Color.a;
o.Alpha = _Color.a;
}
ENDCG
}
FallBack "Diffuse"
}
这是照片:右边一张(我想要它的样子,但没有对角线)左边一张(我想要它的样子,但颜色不见了)
子着色器并不像您认为的那样。子着色器用于为同一着色器提供不同的兼容性级别。 Unity 将始终 select 第一个兼容的子着色器 - 例如,如果第一个使用曲面细分,而您的硬件不支持它,Unity 将在列表中向下查找,直到找到适合您的机器的子着色器。
您想要的是第二个渲染通道。表面着色器生成自己的通道,因此您只需将代码粘贴到第一个着色器的末尾,即最后一个通道之后。