在 unity3d 的 CG Shader 内部的两个通道之间共享一个函数
Share a function between two passes inside CG Shader for unity3d
我正在用 CG 语言为 Unity3d 编写着色器。
如果您为透明对象制作着色器,则需要在 SubShader
中创建两个相似的通道。第一个只渲染背面(Cull Front
),第二个只渲染正面(Cull Back
)。但是顶点和片段函数的代码对于两次遍历是相同的。
是否可以不将代码加倍并声明一些函数,这些函数将在各遍之间共享?
我想在我的代码示例中使用类似的东西:
Shader "cool shader" {
Properties {
...
}
SubShader {
CGPROGRAM
// need to declare vertexOutput somewhow here
float4 sharedFragFoo(vertexOutput i) : COLOR // How to make smth like this?
{
....
return float4(...);
}
ENDCG
pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
vertexOutput vert(vertexInput v) {
vertexOutput o;
...
return o;
}
float4 frag(vertexOutput i) : COLOR
{
return sharedFragFoo(i); // call the shared between passes function
}
ENDCG
}
pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
vertexOutput vert(vertexInput v) {
vertexOutput o;
...
return o;
}
float4 frag(vertexOutput i) : COLOR
{
return sharedFragFoo(i); // call the shared between passes function
}
ENDCG
}
}
}
UPD: 了解如何使用 include。
但是可以在一个文件里面做吗?
回答我自己的问题。怪人!
希望对其他人有所帮助。
您可以将 CGPROGRAM
和 ENDCG
之间的所有内容写在单独的 *.cginc 文件中,并将其包含在每个过程中。
重要!但是你需要写
#pragma vertex vert
和 #pragma fragment frag
在你的主着色器文件中,否则它会编译但不会工作。我想原因是 pragma'ss 在 include's.
之前被处理
这是我的代码示例。
主 着色器定义文件:
Shader "cool shader" {
Properties {
// properties
}
SubShader {
...
pass {
Cull Front
ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "shared.cginc"
ENDCG
}
pass {
Cull Back
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "shared.cginc"
ENDCG
}
}
}
共享文件shared.cginc:
#ifndef SHARED_FOO
#define SHARED_FOO
uniform sampler2D _MainTex;
uniform float4 _MainTex_ST;
uniform float4 _Color;
// other variables....
struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
float4 posWorld : TEXCOORD1;
float4 posInObjectCoords : TEXCOORD2;
float3 normalDir : TEXCOORD3;
};
vertexOutput vert(vertexInput v) {
vertexOutput o;
// do staff
return o;
}
float4 frag(vertexOutput i) : COLOR
{
// do staff
return float4(...);
}
#endif // SHARED_FOO
您可以使用 CGINCLUDE
在一个文件中完成。如果您查看 Unity 的 MobileBlur ("Hidden/FastBlur") 着色器,它在顶部共享代码并在下方传递。
这里只是关键部分 - 注意 CGINCLUDE
/ENDCG
在 SubShader/Pass
之外
Shader "YourShader"
{
...
CGINCLUDE
#include "UnityCG.cginc"
struct shared_v2f
{
float4 pos : SV_POSITION;
}
shared_v2f myVert( appdate_img v )
{
shared_v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
return o;
}
fixed4 myFrag( shared_v2f i ) : SV_Target
{
return fixed4( 1.0, 0.5, 0.0, 1.0 );
}
ENDCG
SubShader
{
...
Pass
{
CGPROGRAM
#pragma vertex myVert
#pragma fragment myFrag
ENDCG
}
}
}
我正在用 CG 语言为 Unity3d 编写着色器。
如果您为透明对象制作着色器,则需要在 SubShader
中创建两个相似的通道。第一个只渲染背面(Cull Front
),第二个只渲染正面(Cull Back
)。但是顶点和片段函数的代码对于两次遍历是相同的。
是否可以不将代码加倍并声明一些函数,这些函数将在各遍之间共享?
我想在我的代码示例中使用类似的东西:
Shader "cool shader" {
Properties {
...
}
SubShader {
CGPROGRAM
// need to declare vertexOutput somewhow here
float4 sharedFragFoo(vertexOutput i) : COLOR // How to make smth like this?
{
....
return float4(...);
}
ENDCG
pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
vertexOutput vert(vertexInput v) {
vertexOutput o;
...
return o;
}
float4 frag(vertexOutput i) : COLOR
{
return sharedFragFoo(i); // call the shared between passes function
}
ENDCG
}
pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
vertexOutput vert(vertexInput v) {
vertexOutput o;
...
return o;
}
float4 frag(vertexOutput i) : COLOR
{
return sharedFragFoo(i); // call the shared between passes function
}
ENDCG
}
}
}
UPD: 了解如何使用 include。
但是可以在一个文件里面做吗?
回答我自己的问题。怪人!
希望对其他人有所帮助。
您可以将 CGPROGRAM
和 ENDCG
之间的所有内容写在单独的 *.cginc 文件中,并将其包含在每个过程中。
重要!但是你需要写
#pragma vertex vert
和 #pragma fragment frag
在你的主着色器文件中,否则它会编译但不会工作。我想原因是 pragma'ss 在 include's.
这是我的代码示例。
主 着色器定义文件:
Shader "cool shader" {
Properties {
// properties
}
SubShader {
...
pass {
Cull Front
ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "shared.cginc"
ENDCG
}
pass {
Cull Back
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "shared.cginc"
ENDCG
}
}
}
共享文件shared.cginc:
#ifndef SHARED_FOO
#define SHARED_FOO
uniform sampler2D _MainTex;
uniform float4 _MainTex_ST;
uniform float4 _Color;
// other variables....
struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
float4 posWorld : TEXCOORD1;
float4 posInObjectCoords : TEXCOORD2;
float3 normalDir : TEXCOORD3;
};
vertexOutput vert(vertexInput v) {
vertexOutput o;
// do staff
return o;
}
float4 frag(vertexOutput i) : COLOR
{
// do staff
return float4(...);
}
#endif // SHARED_FOO
您可以使用 CGINCLUDE
在一个文件中完成。如果您查看 Unity 的 MobileBlur ("Hidden/FastBlur") 着色器,它在顶部共享代码并在下方传递。
这里只是关键部分 - 注意 CGINCLUDE
/ENDCG
在 SubShader/Pass
Shader "YourShader"
{
...
CGINCLUDE
#include "UnityCG.cginc"
struct shared_v2f
{
float4 pos : SV_POSITION;
}
shared_v2f myVert( appdate_img v )
{
shared_v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
return o;
}
fixed4 myFrag( shared_v2f i ) : SV_Target
{
return fixed4( 1.0, 0.5, 0.0, 1.0 );
}
ENDCG
SubShader
{
...
Pass
{
CGPROGRAM
#pragma vertex myVert
#pragma fragment myFrag
ENDCG
}
}
}