Unity 中使用Geomotry Shader(几何着色器)扩展点创建其他图形(并实现处理锯齿)
问题背景:
我们开发中需要有“点”对象,可以是像素的(不具备透视效果),始终等大,还有就是3D场景下的矢量点(随相机距离透视变化的)。
问题解决思路:
方案1:使用GS扩充顶点,并扩充三角面,通过GS直接绘制出想要图形点(我这里有几种图形的点)
方案2:使用GS扩充顶点,绘制出正方形面,到FS中去截取想要的形状
这两种方案基本思想都是一样的,我这里提供两种方案是因为我这个点的边框是有要求的,用GS扩线围一圈效果不好
知识扩展:
Geomotry Shader(几何着色器):几何着色器是可选的着色器,它位于顶点和片段着色器之间,它以一个或多个表示为一个单独基本图形(primitive)即图元的顶点作为输入,比如可以是一个点或者三角形,几何着色器在将这些顶点发送到下一个着色阶段之前,可以将这些顶点转变为它认为合适的内容。几何着色器有意思的地方在于它可以把(一个或多个)顶点转变为完全不同的基本图形(primitive),从而生成比原来多得多的顶点。
上面是官方解释,通俗来讲:就是GeometryShader接收的实际上是VS输出的图元,对这些图元进行添加,修改,删除,然后输出新的图元信息。
图片说明:
这也就是人们常见的shader流程图。
具体实现代码:
方案一:
1 Shader "Vector/Point"
2 {
3 Properties
4 {
5 _Color("MianColor",color)=(1,1,1,1)
6 }
7 SubShader
8 {
9 Pass
10 {
11 Tags { "RenderType"="Opaque" }
12 LOD 100
13 Cull Off
14 CGPROGRAM
15 #pragma target 4.0
16 #pragma vertex vert
17 #pragma fragment frag
18 #pragma geometry geom
19 #include "UnityCG.cginc"
20 struct appdata
21 {
22 float4 vertex : POSITION;
23 float2 uv : TEXCOORD0;
24 float3 normal : NORMAL;
25 };
26 struct v2g
27 {
28 float4 vertex : POSITION;
29 float3 nor:NORMAL;
30 };
31 struct g2f
32 {
33 float4 vertex : SV_POSITION;
34 float3 norg:NORMAL;
35 };
36
37 fixed4 _LightColor0;
38 fixed4 _Color;
39 float radius;
40 float initOffsetAngle=0;
41 float verticesNumber=3;
42 float IsEqualPixelPoint=0.0;
43
44 v2g vert(appdata_base v)
45 {
46 v2g o;
47 o.vertex = v.vertex;
48 o.nor=v.normal;
49 return o;
50 }
51
52 void ADD_VERTEX(float3 v,g2f o,inout TriangleStream<g2f> tristream)
53 {
54 o.vertex = UnityObjectToClipPos(v);
55 tristream.Append(o);
56 }
57 void ADD_INFO(float3 p0,float3 p1,float3 p2,g2f o,inout TriangleStream<g2f> tristream)
58 {
59
60 ADD_VERTEX(p0,o,tristream);
61 ADD_VERTEX(p1,o,tristream);
62 ADD_VERTEX(p2,o,tristream);
63 tristream.RestartStrip();
64 }
65
66 // 根据模型坐标获得屏幕坐标
67 float4 GetScreenPos(float4 vertex)
68 {
69 float4 pos = UnityObjectToClipPos(vertex);
70 //return getScreenPosByClipPos(pos);
71
72 pos = ComputeScreenPos(pos);
73 pos.xy = pos.xy / pos.w;
74 pos.xy = pos.xy * _ScreenParams.xy;
75 return pos;
76 }
77
78 //将旋转完的坐标转回剪裁空间下
79 void ADD_VERTEX_Other(float4 v,g2f o,inout TriangleStream<g2f> tristream)
80 {
81 float4 pos=v;
82 pos.xy=v.xy/_ScreenParams.xy;
83 pos.xy=pos.xy * v.w;
84
85 pos.y= (pos.y-(0.5*pos.w))/(_ProjectionParams.x * 0.5);
86 pos.x=(pos.x-(0.5*pos.w))/0.5;
87
88 o.vertex = pos;
89 tristream.Append(o);
90 }
91
92 void ADD_INFO_Other(float4 p0,float4 p1,float4 p2,g2f o,inout TriangleStream<g2f> tristream)
93 {
94 ADD_VERTEX_Other(p0,o,tristream);
95 ADD_VERTEX_Other(p1,o,tristream);
96 ADD_VERTEX_Other(p2,o,tristream);
97 tristream.RestartStrip();
98 }
99
100 [maxvertexcount(60)]
101 void geom(triangle v2g IN[3], inout TriangleStream<g2f> tristream)
102 {
103 g2f o;
104 if(IsEqualPixelPoint==0.0)
105 {
106 float3 p0=float3(0,0,0);
107 float3 dir=normalize( mul(unity_WorldToObject,_WorldSpaceCameraPos)-IN[0].vertex);
108 float3 cy=float3(0,1,0);
109 float3 right=normalize(cross(cy, dir));
110 float3 up=normalize(cross(dir,right));
111 float3 p=cy * radius;
112 //第一个点
113 float3 p1=float3((cos(radians(initOffsetAngle)) * (p).x)-(sin(radians(initOffsetAngle)) * (p).y),(sin(radians(initOffsetAngle)) * (p).x)+(cos(radians(initOffsetAngle)) * (p).y),(p).z);
114 float3 p2=float3(0,0,0);
115 float3 p3=float3(0,0,0);
116 float angle= radians(360/verticesNumber);
117 p2=float3((cos(angle) * (p1).x)-(sin(angle) * (p1).y),(sin(angle) * (p1).x)+(cos(angle) * (p1).y),(p1).z);
118
119 float3 p1p=(p1.x*right+p1.y*up+p1.z*dir);
120 p2=(p2.x*right+p2.y*up+p2.z*dir);
121
122 float3 edgeA = p2 - p1p;
123 float3 edgeB = p3 - p1p;
124 float3 normalFace = normalize(cross(edgeA, edgeB));
125 o.norg=-normalFace;
126
127 ADD_INFO(p0,p1p,p2,o,tristream);
128
129 for (float i=1.0; i<verticesNumber;i+=1.0)
130 {
131 p2=float3((cos(i*angle) * (p1).x)-(sin(i*angle) * (p1).y),(sin(i*angle) * (p1).x) + (cos(i*angle) * (p1).y),(p1).z);
132 p3=float3((cos((i+1)*angle) * (p1).x)-(sin((i+1)*angle) * (p1).y),(sin((i+1) * angle) * (p1).x)+(cos((i+1) * angle) * (p1).y),(p1).z);
133
134 p2=(p2.x*right+p2.y*up+p2.z*dir);
135 p3=(p3.x*right+p3.y*up+p3.z*dir);
136
137 float3 edgeA = p2 - p1;
138 float3 edgeB = p3 - p1;
139 float3 normalFace = normalize(cross(edgeA, edgeB));
140 o.norg=-normalFace;
141
142 ADD_INFO(p0,p2,p3,o,tristream);
143 }
144 }
145 else
146 {
147 //等像素
148 float4 pp0=float4(0,0,0,1);
149 pp0= GetScreenPos(pp0);
150 float2 up=float2(0,1);
151 float2 pp=up * radius;
152 //第一个点
153 float4 pp1=pp0;
154 float4 pp2=pp0;
155 float4 pp3=pp0;
156 pp1.xy= float2((cos(radians(initOffsetAngle)) * (pp).x)-(sin(radians(initOffsetAngle)) * (pp).y),(sin(radians(initOffsetAngle)) * (pp).x)+(cos(radians(initOffsetAngle)) * (pp).y));
157 float angle= radians(360/verticesNumber);
158 pp2.xy=float2((cos(angle) * (pp1).x)-(sin(angle) * (pp1).y),(sin(angle) * (pp1).x)+(cos(angle) * (pp1).y));
159 float3 edgeA = pp2 - pp1;
160 float3 edgeB = pp3 - pp1;
161 float3 normalFace = normalize(cross(edgeA, edgeB));
162 o.norg=-normalFace;
163
164 ADD_INFO_Other(pp0,pp1+float4(pp0.xy,0,0),pp2+float4(pp0.xy,0,0),o,tristream);
165
166 for (float i=1.0; i<verticesNumber;i+=1.0)
167 {
168 pp2=pp0;
169 pp3=pp0;
170 pp2.xy=float2((cos(i*angle) * (pp1).x)-(sin(i*angle) * (pp1).y),(sin(i*angle) * (pp1).x) + (cos(i*angle) * (pp1).y));
171 pp3.xy=float2((cos((i+1)*angle) * (pp1).x)-(sin((i+1)*angle) * (pp1).y),(sin((i+1) * angle) * (pp1).x)+(cos((i+1) * angle) * (pp1).y));
172
173 float3 edgeA = pp2 - pp1;
174 float3 edgeB = pp3 - pp1;
175 float3 normalFace = normalize(cross(edgeA, edgeB));
176 o.norg=-normalFace;
177
178 ADD_INFO_Other(pp0,pp2+float4(pp0.xy,0,0),pp3+float4(pp0.xy,0,0),o,tristream);
179 }
180 }
181 }
182 fixed4 frag (g2f i) : SV_Target
183 {
184 return _Color;
185 }
186 ENDCG
187 }
188 }
189 }
代码分析:
1.从模型坐标-剪裁空间坐标-屏幕空间坐标,如下:
float4 GetScreenPos(float4 vertex)
{
float4 pos = UnityObjectToClipPos(vertex);
//return getScreenPosByClipPos(pos); pos = ComputeScreenPos(pos);
pos.xy = pos.xy / pos.w;
pos.xy = pos.xy * _ScreenParams.xy;
return pos;
}
2.屏幕坐标扩展完坐标转回剪裁空间
//将旋转完的坐标转回剪裁空间下
void ADD_VERTEX_Other(float4 v,g2f o,inout TriangleStream<g2f> tristream)
{
float4 pos=v;
pos.xy=v.xy/_ScreenParams.xy;
pos.xy=pos.xy * v.w; pos.y= (pos.y-(0.5*pos.w))/(_ProjectionParams.x * 0.5);
pos.x=(pos.x-(0.5*pos.w))/0.5; o.vertex = pos;
tristream.Append(o);
}
这个地方就是转屏幕坐标的逆运算,主要注意的是定义位于UnityCG.cginc中的内置方法ComputeScreenPos,它的具体逻辑是这样:
inline float4 ComputeScreenPos (float4 pos)
{
float4 o = pos * 0.5f;
o.xy = float2(o.x, o.y*_ProjectionParams.x) + o.w;
o.zw = pos.zw;
return o;
}
即主要做的是就是这:
o.x = (pos.x * 0.5 + pos.w * 0.5)
o.y = (pos.y * 0.5 * _ProjectionParams.x + pos.w * 0.5)
这一步别忘了逆运算回去。
3.这里的算法逻辑是这样:给我一个中心点坐标,我求出正上方点坐标,根据你是几边形,去旋转(乘以旋转矩阵)得到扩展点。上面矢量点主要问题在于,我构建了本地坐标系,旋转就会有坑,因为我正上方点是通过构建坐标系去求得,然而旋转应该在自身坐标系下,
正上方点就是(0,1,0 )而不是自己构建坐标系下的up,记得转完返回去,所以这是一个坑。
方案二:
1 Shader "MyShader/PointTwo"
2 {
3 Properties
4 {
5 _Color("MianColor",color)=(1,1,1,1)
6 }
7 SubShader
8 {
9
10 Tags { "RenderType"="Opaque" }
11 LOD 100
12 Cull Off
13
14 CGINCLUDE
15
16 #include "UnityCG.cginc"
17
18 struct appdata
19 {
20 float4 vertex : POSITION;
21 float2 uv : TEXCOORD0;
22 float3 normal : NORMAL;
23 fixed4 color : COLOR; //顶点自身的颜色
24 };
25
26 struct v2g
27 {
28 float4 vertex : POSITION;
29 float3 nor:NORMAL;
30 fixed4 color : COLOR; //顶点自身的颜色
31 };
32
33 struct g2f
34 {
35 float4 vertex : SV_POSITION;
36 float3 pos: TEXCOORD0;
37 float3 centerPos: TEXCOORD1;
38 float3 norg:NORMAL;
39 fixed4 color : COLOR; //顶点自身的颜色
40 };
41
42 //点的颜色
43 fixed4 _Color;
44 //边框的颜色
45 fixed4 _LineColor;
46 //点的半径大小(四边形内切圆)
47 float _Radius;
48 //点的线框宽度
49 uniform float _LineWidth=5;
50 //什么图形(-1圆/)
51 float _PointType=-1;
52 //是否是像素点
53 float IsEqualPixelPoint=0.0;
54 //交叉点宽度
55 float _CrossPointWidth;
56
57 //矢量点添加扩展点坐标转换
58 void ADD_VERTEX(float3 v,g2f o,inout TriangleStream<g2f> tristream)
59 {
60 o.vertex = UnityObjectToClipPos(v);
61 o.pos = v;
62 tristream.Append(o);
63 }
64
65 //矢量点添加扩展点面逻辑
66 void ADD_INFO(float3 p0,float3 p1,float3 p2,g2f o,inout TriangleStream<g2f> tristream)
67 {
68 ADD_VERTEX(p0,o,tristream);
69 ADD_VERTEX(p1,o,tristream);
70 ADD_VERTEX(p2,o,tristream);
71 tristream.RestartStrip();
72 }
73
74 // (像素点)根据模型坐标获得屏幕坐标
75 float4 GetScreenPos(float4 vertex)
76 {
77 float4 pos = UnityObjectToClipPos(vertex);
78
79 pos = ComputeScreenPos(pos);
80 pos.xy = pos.xy / pos.w;
81 pos.xy = pos.xy * _ScreenParams.xy;
82 return pos;
83 }
84
85 //(像素点)将旋转完的坐标转回剪裁空间下
86 void ADD_VERT_Other(float4 v,g2f o,inout TriangleStream<g2f> tristream)
87 {
88 float4 pos=v;
89 pos.xy=v.xy/_ScreenParams.xy;
90 pos.xy=pos.xy * v.w;
91
92 pos.y= (pos.y-(0.5*pos.w))/(_ProjectionParams.x * 0.5);
93 pos.x=(pos.x-(0.5*pos.w))/0.5;
94
95 o.vertex = pos;
96 o.pos=v;
97 tristream.Append(o);
98 }
99
100 //像素点添加点
101 void ADD_INFO_Other(float4 p0,float4 p1,float4 p2,g2f o,inout TriangleStream<g2f> tristream)
102 {
103 ADD_VERTEX_Other(p0,o,tristream);
104 ADD_VERTEX_Other(p1,o,tristream);
105 ADD_VERTEX_Other(p2,o,tristream);
106 tristream.RestartStrip();
107 }
108
109 // 判断点是否在三角形内
110 float PointinTriangle(float2 A, float2 B, float2 C, float2 P)
111 {
112 float2 ab=B-A;
113 float2 ac=C-A;
114 float2 ap=P-A;
115
116 float u=(dot(ab,ab) *dot(ap,ac)-dot(ac,ab)* dot(ap,ab)) / (dot(ac,ac) * dot(ab,ab)-dot(ac,ab) * dot(ab,ac));
117 float v=(dot(ac,ac) *dot(ap,ab)-dot(ac,ab)* dot(ap,ac)) / (dot(ac,ac) * dot(ab,ab)-dot(ac,ab) * dot(ab,ac));
118
119 if (u < 0 || u > 1) // if u out of range, return directly
120 {
121 return 2 ;
122 }
123
124 if (v < 0 || v > 1) // if v out of range, return directly
125 {
126 return 2 ;
127 }
128 return u+v;
129 }
130
131 //截圆点
132 void DrawCirclePoint(g2f i,float type)
133 {
134
135 //边框
136 _LineWidth=5;
137
138 float _R = abs(type) < 0.05 ? _Radius : (_Radius - _LineWidth);
139
140 float dis=distance(i.centerPos,i.pos);
141
142 //剔除圆
143 if(dis > _R)
144 {
145 discard;
146 }
147
148 }
149
150 //截正方形点
151 void DrawSquarePoint(g2f i,float type)
152 {
153 //边框
154 _LineWidth=5;
155
156 float _R = abs(type) < 0.05 ? 0.9 * _Radius : (0.9 *_Radius - _LineWidth);
157
158 //计算边缘点
159 float2 leftTop=float2(i.centerPos.x - _R , i.centerPos.y + _R);
160 float2 leftButtom=float2(i.centerPos.x - _R , i.centerPos.y - _R);
161 float2 rightTop=float2(i.centerPos.x + _R , i.centerPos.y + _R);
162 float2 rightButtom=float2(i.centerPos.x + _R , i.centerPos.y - _R);
163
164 //正方形剔除
165 if(i.pos.x < leftTop.x | i.pos.x > rightTop.x | i.pos.y < leftButtom.y | i.pos.y > rightTop.y)
166 {
167 discard;
168 }
176 }
177
178 //截三角形点
179 void DrawTrianglePoint(g2f i,float type)
180 {
181 //边框
182 _LineWidth=5;
183
184 float _R = abs(type) < 0.05 ? _Radius : (_Radius - _LineWidth);
185
186 //计算边缘点
187 float2 leftTop=float2(i.centerPos.x - _R , i.centerPos.y + _R);
188 float2 leftButtom=float2(i.centerPos.x - _R , i.centerPos.y - _R);
189 float2 rightTop=float2(i.centerPos.x + _R , i.centerPos.y + _R);
190 float2 rightButtom=float2(i.centerPos.x + _R , i.centerPos.y - _R);
191
192 //三角形顶点
193 float2 topCenter=(leftTop+rightTop)/2;
194 float2 rightB=float2((i.centerPos.x + 0.707 * _R),i.centerPos.y - 0.5 *_R);
195 float2 leftB=float2((i.centerPos.x - 0.707 * _R),i.centerPos.y - 0.5 *_R);
196
197 if(PointinTriangle(topCenter,rightB, leftB, i.pos.xy)>1)
198 {
199 discard;
200 }
259 }
260
261 //截交叉十字形点
262 void DrawCrossPoint(g2f i,float type)
263 {
264
265 //边框
266 _LineWidth=5;
267
268 _CrossPointWidth=16;
269
270 float _R = abs(type) < 0.05 ? 0.9* _Radius : (0.92 * _Radius - _LineWidth);
271
272 float _InPoint = abs(type) < 0.05 ? _CrossPointWidth / 2 : (_CrossPointWidth - _LineWidth) / 2;
273
274 //计算边缘点
275 float2 leftTop=float2(i.centerPos.x - _R , i.centerPos.y + _R);
276 float2 leftButtom=float2(i.centerPos.x - _R , i.centerPos.y - _R);
277 float2 rightTop=float2(i.centerPos.x + _R , i.centerPos.y + _R);
278 float2 rightButtom=float2(i.centerPos.x + _R , i.centerPos.y - _R);
279
280 //十字架内角点
281 float2 inRightTop=float2(i.centerPos.x + _InPoint , i.centerPos.y + _InPoint);
282 float2 inLeftTop=float2(i.centerPos.x - _InPoint , i.centerPos.y + _InPoint);
283 float2 inRightButtom=float2(i.centerPos.x + _InPoint , i.centerPos.y - _InPoint);
284 float2 inLeftButtom=float2(i.centerPos.x - _InPoint , i.centerPos.y - _InPoint);
285
286 if(((i.pos.x) > (inRightTop.x) & (i.pos.y) > (inRightTop.y)) | ((i.pos.x) < (inLeftTop.x) & (i.pos.y) > (inLeftTop.y)) | ((i.pos.x) > (inRightButtom.x) & (i.pos.y) < (inRightButtom.y)) | ((i.pos.x) < (inLeftButtom.x) & (i.pos.y) < (inLeftButtom.y)) | ((i.pos.x) < (i.centerPos.x - _R) | (i.pos.x) > (i.centerPos.x+ _R)) | ((i.pos.y) < (i.centerPos.y- _R) | (i.pos.y) > (i.centerPos.y+ _R)))
287 {
288 discard;
289 }
298 }
299
300 v2g vert(appdata_full v)
301 {
302 v2g o;
303 o.vertex = v.vertex;
304 o.nor=v.normal;
305 o.color=v.color;
306 return o;
307 }
308
309 [maxvertexcount(12)]
310 void geom(triangle v2g IN[3], inout TriangleStream<g2f> tristream)
311 {
312 g2f o;
313 //固定只扩展4个点,且初始偏转为45
314 //矢量点
315 if(IsEqualPixelPoint==0.0)
316 {
317 //中心点
318 float3 centerPos=float3(0,0,0);
319 o.centerPos=centerPos;
320 o.color=IN[0].color;
321
322 //计算本地坐标系
323 float3 dir=normalize(mul(unity_WorldToObject,_WorldSpaceCameraPos)-IN[0].vertex);
324 float3 worldUp=float3(0,1,0);
325 float3 right=normalize(cross(worldUp, dir));
326 float3 up=normalize(cross(dir,right));
327
328 //正上方点
329 float3 p=worldUp * _Radius * 1.414;
330 float3 p1=centerPos;
331 float3 p2=centerPos;
332 float3 p3=centerPos;
333 float3 p4=centerPos;
334
335 //计算偏移角
336 float angle= radians(360/4);
337
338 //求正方形四顶点
339 p1=float3((cos(radians(45)) * (p).x)-(sin(radians(45)) * (p).y),(sin(radians(45)) * (p).x)+(cos(radians(45)) * (p).y),(p).z);
340 p2=float3((cos(angle) * (p1).x)-(sin(angle) * (p1).y),(sin(angle) * (p1).x)+(cos(angle) * (p1).y),(p1).z);
341 p3=float3((cos(angle * 2) * (p1).x)-(sin(angle * 2) * (p1).y),(sin(angle * 2) * (p1).x)+(cos(angle * 2) * (p1).y),(p1).z);
342 p4=float3((cos(angle * 3) * (p1).x)-(sin(angle * 3) * (p1).y),(sin(angle * 3) * (p1).x)+(cos(angle * 3) * (p1).y),(p1).z);
343 p1=(p1.x * right + p1.y * up + p1.z * dir);
344 p2=(p2.x * right + p2.y * up + p2.z * dir);
345 p3=(p3.x * right + p3.y * up + p3.z * dir);
346 p4=(p4.x * right + p4.y * up + p4.z * dir);
347
348 //计算法线
349 float3 edgeA = p2 - p1;
350 float3 edgeB = p3 - p1;
351 float3 normalFace = normalize(cross(edgeA, edgeB));
352 o.norg=-normalFace;
353
354 ADD_INFO(p1,p2,p3,o,tristream);
355 ADD_INFO(p3,p4,p1,o,tristream);
356 }
357 else
358 {
359 //等像素点
360 float4 centerPos1=float4(0,0,0,1);
361 centerPos1= GetScreenPos(centerPos1);
362 float2 up=float2(0,1);
363 float2 pp=up * _Radius * 1.414;
364 //第一个点
365 float4 pp1=centerPos1;
366 float4 pp2=centerPos1;
367 float4 pp3=centerPos1;
368 float4 pp4=centerPos1;
369
370 //计算偏移角
371 float angle= radians(360/4);
372
373 //求正方形四顶点
374 pp1.xy=float2((cos(radians(45)) * (pp).x)-(sin(radians(45)) * (pp).y),(sin(radians(45)) * (pp).x)+(cos(radians(45)) * (pp).y));
375 pp2.xy=float2((cos(angle) * (pp1).x)-(sin(angle) * (pp1).y),(sin(angle) * (pp1).x)+(cos(angle) * (pp1).y));
376 pp3.xy=float2((cos(2 * angle) * (pp1).x)-(sin(2 * angle) * (pp1).y),(sin(2 * angle) * (pp1).x)+(cos(2 * angle) * (pp1).y));
377 pp4.xy=float2((cos(3 * angle) * (pp1).x)-(sin(3 * angle) * (pp1).y),(sin(3 * angle) * (pp1).x)+(cos(3 * angle) * (pp1).y));
378
379 //计算偏移
380 pp1=pp1+float4(centerPos1.xy,0,0);
381 pp2=pp2+float4(centerPos1.xy,0,0);
382 pp3=pp3+float4(centerPos1.xy,0,0);
383 pp4=pp4+float4(centerPos1.xy,0,0);
384
385 //计算法线
386 float3 edgeA = pp2 - pp1;
387 float3 edgeB = pp3 - pp1;
388 float3 normalFace = normalize(cross(edgeA, edgeB));
389 o.norg=-normalFace;
390
391 o.centerPos=centerPos1;
392 o.color=IN[0].color;
393
394 ADD_INFO_Other(pp1,pp2,pp3,o,tristream);
395 ADD_INFO_Other(pp3,pp4,pp1,o,tristream);
396
397 }
398 }
399
400 fixed4 frag (g2f i) : SV_Target
401 {
402
403 //圆形点
404 if (abs(_PointType)<=0.05)
405 {
406 DrawCirclePoint(i,0.0);
407 }
408
409 //正方形
410 if(abs(_PointType-2)<=0.05)
411 {
412 DrawSquarePoint(i,0.0);
413 }
414
415 //三角形
416 if(abs(_PointType-1)<=0.05)
417 {
418 DrawTrianglePoint(i,0.0);
419 }
420
421 //交叉十字
422 if(abs(_PointType-3)<=0.05)
423 {
424 DrawCrossPoint(i,0.0);
425 }
426
427 return _LineColor;
428 }
429
430
431 fixed4 fragOther (g2f i) : SV_Target
432 {
433 //圆形点
434 if (abs(_PointType)<=0.05)
435 {
436 DrawCirclePoint(i,1.0);
437 }
438
439 //正方形
440 if(abs(_PointType-2)<=0.05)
441 {
442 DrawSquarePoint(i,1.0);
443 }
444
445 //三角形
446 if(abs(_PointType-1)<=0.05)
447 {
448 DrawTrianglePoint(i,1.0);
449 }
450
451 //交叉十字
452 if(abs(_PointType-3)<=0.05)
453 {
454 DrawCrossPoint(i,1.0);
455 }
456
457 return _Color;
458 }
459
460 ENDCG
461
462 Pass
463 {
464 NAME "InitShader"
465
466 Tags { "RenderType"="Opaque" }
467 LOD 100
468 Cull Off
469
470 CGPROGRAM
471
472 #pragma target 4.0
473 #pragma vertex vert
474 #pragma geometry geom
475 #pragma fragment frag
476
477 ENDCG
478 }
479
480 Pass
481 {
482 NAME "LineShader"
483
484 Tags { "RenderType"="Opaque" }
485 LOD 100
486 Cull Off
487
488 CGPROGRAM
489
490 #pragma target 4.0
491 #pragma vertex vert
492 #pragma geometry geom
493 #pragma fragment fragOther
494
495 ENDCG
496 }
497 }
498
499 FallBack "Diffuse"
500 }
代码分析:
这个方案主要是为了边框处理,我在这里画了两次,也可以处理一次,通过条件去改变Color,但是我这里不想过多处理过渡问题,所以采取了两个Pass渲两遍。。
这里附带一个判断点是否在三角形内算法:
对于三角形ABC和一点P,可以有如下的向量表示:
p点在三角形内部的充分必要条件是:1 >= u >= 0, 1 >= v >= 0, u+v <= 1。
已知A,B,C,P四个点的坐标,可以求出u,v,把上面的式子分别点乘向量AC和向量AB
解方程得到:
解出u,v后只需要看他们是否满足“1 >= u >= 0, 1 >= v >= 0, u+v <= 1”,如满足,则,p 在三角形内。
(u = 0时,p在AB上, v = 0时,p在AC上,两者均为0时,p和A重合)
ps:是不是很熟悉,嘿嘿
关于GS:
1.属性语法在着色器定义之前设置最大顶点数:
[maxvertexcount(N)]
N是几何着色器为单个调用输出的顶点的最大数量
GS可以在每次调用时输出的顶点数量是可变的,但不能超过定义的最大值。出于性能考虑,最大顶点数应尽可能小; [NVIDIA08]指出,当GS输出在1到20个标量之间时,可以实现GS的性能峰值,如果GS输出在27-40个标量之间,则性能下降50%。
2.GS需要两个参数:输入参数和输出参数。 (实际上,它可能需要更多,但这是一个特殊的主题;请参见§11.2.4。)输入参数一般是一个定义了图元的顶点数组 — 一个顶点定义一个点,两个定义一条线,三个定义三角形,四个定义邻接线段,六个定义邻接三角形。 输入顶点的顶点类型是顶点着色器返回的顶点类型(例如,VertexOut)。 输入参数必须以原始类型为前缀,描述输入到几何着色器中的图元的类型。这可以是以下任何一种:
1、point:输入图元是点。
2、line:输入图元是线段(lists或strips)。
3、triangle:输入图元是三角形(lists或strips)。
4、lineadj:输入图元是具有邻接(lists或strips)的线段。
5、triangleadj:输入图元是具有邻接(lists或strips)的三角形。
3.几何着色器输出的顶点形成基元; 输出原语的类型由流类型(PointStream,LineStream,TriangleStream)指示。 对于线和三角形,输出原语总是strips。 然而,线和三角形列表可以使用内在的RestartStrip方法进行
关于SubShader使用:
subShaderc 中 选择执行哪个?可根据LOG设置,(从上往下 &从大到小)写)<=LOD值就执行相应的子着色器,它会在子着色器列表中找《=LOD的,但是会找第一个满足条件的,所以从小到大,会只跑第一个最小的了,所以从大到小写(LOD)
最新:
解决问题:
1.面向相机问题(用的是世界下坐标)参考广告牌技术,任何物体的上方就是(0,1,0);无需先构建本地坐标系。
2.解决锯齿问题,使用颜色过渡。
最新代码:
1 Shader "Vector/Point"
2 {
3 Properties
4 {
5 _Color("MianColor",color)=(1,1,1,1)
6 }
7 SubShader
8 {
9
10 Tags { "RenderType"="Transparent" "Queue"="Transparent+1"}
11 LOD 100
12 Cull Off
13
14 CGINCLUDE
15
16 #include "UnityCG.cginc"
17
18 struct appdata
19 {
20 float4 vertex : POSITION;
21 float2 uv : TEXCOORD0;
22 float3 normal : NORMAL;
23 fixed4 color : COLOR; //顶点自身的颜色
24 };
25
26 struct v2g
27 {
28 float4 vertex : POSITION;
29 float3 nor:NORMAL;
30 fixed4 color : COLOR; //顶点自身的颜色
31 };
32
33 struct g2f
34 {
35 float4 vertex : SV_POSITION;
36 float3 pos: TEXCOORD0;
37 float3 centerPos: TEXCOORD1;
38 float3 norg:NORMAL;
39 fixed4 color : COLOR; //顶点自身的颜色
40 };
41
42 //点的颜色
43 fixed4 _Color;
44 //边框的颜色
45 fixed4 _LineColor;
46 //点的半径大小(四边形内切圆)
47 float _Radius;
48 //点的线框宽度
49 uniform float _LineWidth=5;
50 //点类型
51 float _PointType=-1;
52 //是否是像素点
53 float IsEqualPixelPoint=0.0;
54 //交叉点宽度
55 float _CrossPointWidth;
56
57 //矢量点添加扩展点坐标转换
58 void ADD_VERT(float3 v,g2f o,inout TriangleStream<g2f> tristream)
59 {
60 o.vertex = UnityObjectToClipPos(v);
61 o.pos = v;
62 tristream.Append(o);
63 }
64
65 //矢量点添加扩展点面逻辑
66 void ADD_TRI(float3 p0,float3 p1,float3 p2,g2f o,inout TriangleStream<g2f> tristream)
67 {
68 ADD_VERT(p0,o,tristream);
69 ADD_VERT(p1,o,tristream);
70 ADD_VERT(p2,o,tristream);
71 tristream.RestartStrip();
72 }
73
74 // (像素点)根据模型坐标获得屏幕坐标
75 float4 GetScreenPos(float4 vertex)
76 {
77 float4 pos = UnityObjectToClipPos(vertex);
78
79 pos = ComputeScreenPos(pos);
80 pos.xy = pos.xy / pos.w;
81 pos.xy = pos.xy * _ScreenParams.xy;
82 return pos;
83 }
84
85 //(像素点)将旋转完的坐标转回剪裁空间下
86 void ADD_VERT_Other(float4 v,g2f o,inout TriangleStream<g2f> tristream)
87 {
88 float4 pos=v;
89 pos.xy=v.xy/_ScreenParams.xy;
90 pos.xy=pos.xy * v.w;
91
92 pos.y= (pos.y-(0.5*pos.w))/(_ProjectionParams.x * 0.5);
93 pos.x=(pos.x-(0.5*pos.w))/0.5;
94
95 o.vertex = pos;
96 o.pos=v;
97 tristream.Append(o);
98 }
99
100 //像素点添加点
101 void ADD_TRI_Other(float4 p0,float4 p1,float4 p2,g2f o,inout TriangleStream<g2f> tristream)
102 {
103 ADD_VERT_Other(p0,o,tristream);
104 ADD_VERT_Other(p1,o,tristream);
105 ADD_VERT_Other(p2,o,tristream);
106 tristream.RestartStrip();
107 }
108
109 // 判断点是否在三角形内
110 float PointinTriangle(float2 A, float2 B, float2 C, float2 P)
111 {
112 float2 ab=B-A;
113 float2 ac=C-A;
114 float2 ap=P-A;
115
116 float u=(dot(ab,ab) *dot(ap,ac)-dot(ac,ab)* dot(ap,ab)) / (dot(ac,ac) * dot(ab,ab)-dot(ac,ab) * dot(ab,ac));
117 float v=(dot(ac,ac) *dot(ap,ab)-dot(ac,ab)* dot(ap,ac)) / (dot(ac,ac) * dot(ab,ab)-dot(ac,ab) * dot(ab,ac));
118
119 if (u < 0 || u > 1) // if u out of range, return directly
120 {
121 return 2 ;
122 }
123
124 if (v < 0 || v > 1) // if v out of range, return directly
125 {
126 return 2 ;
127 }
128 return u+v;
129 }
130
131 //截圆点
132 void DrawCirclePoint(g2f i,float type)
133 {
134
135 float _R = abs(type) < 0.05 ? _Radius +0.5 : (_Radius - _LineWidth +0.5);
136
137 float dis=distance(i.centerPos,i.pos);
138
139 if(abs(type) <= 1.05 ){
140 //剔除圆
141 if(dis > _R)
142 {
143 discard;
144 }
145 }
146 }
147
148 //截正方形点
149 void DrawSquarePoint(g2f i,float type)
150 {
151
152 float _R = abs(type) < 0.05 ? 0.92 * _Radius : (0.92 *_Radius - _LineWidth);
153
154 //计算边缘点
155 float2 leftTop=float2(i.centerPos.x - _R , i.centerPos.y + _R);
156 float2 leftButtom=float2(i.centerPos.x - _R , i.centerPos.y - _R);
157 float2 rightTop=float2(i.centerPos.x + _R , i.centerPos.y + _R);
158 float2 rightButtom=float2(i.centerPos.x + _R , i.centerPos.y - _R);
159
160 //正方形剔除
161 if(i.pos.x < leftTop.x | i.pos.x > rightTop.x | i.pos.y < leftButtom.y | i.pos.y > rightTop.y)
162 {
163 discard;
164 }
165 }
166
167 //截三角形点
168 fixed4 DrawTrianglePoint(g2f i,float type)
169 {
170
171 float _R = abs(type) < 0.05 ? _Radius * 0.92 : (_Radius * 0.92 );
172
173 //计算边缘点
174 float2 leftTop=float2(i.centerPos.x - _R , i.centerPos.y + _R);
175 float2 leftButtom=float2(i.centerPos.x - _R , i.centerPos.y - _R);
176 float2 rightTop=float2(i.centerPos.x + _R , i.centerPos.y + _R);
177 float2 rightButtom=float2(i.centerPos.x + _R , i.centerPos.y - _R);
178
179 //三角形顶点
180 float2 topCenter=float2(i.centerPos.x , i.centerPos.y + (sin(radians(60))*2-1) * _R);
181 float2 rightB = rightButtom;
182 float2 leftB = leftButtom;
183 if(abs(type-1) < 0.05)
184 {
185 float2 center=float2(0,0);
186 center=(topCenter+rightB+leftB) / 3;
187 topCenter=topCenter + normalize(center-topCenter) * 2 * _LineWidth ;
188 rightB = rightButtom + normalize(center-rightButtom) * 2 * _LineWidth ;
189 leftB = leftButtom + normalize(center-leftButtom) * 2 * _LineWidth ;
190
191 }
192
193 if(PointinTriangle(topCenter,rightB, leftB, i.pos.xy)>1)
194 {
195 discard;
196 }
197
198 float2 right_center=(topCenter+rightB)/2;
199 float2 buttom_center=(leftB+rightB)/2;
200 float2 left_center=(topCenter+leftB)/2;
201
202 //在右三角形内
203 if(PointinTriangle(topCenter,i.centerPos, rightB, i.pos.xy)<=1)
204 {
205 float2 right_center_o=(right_center-i.centerPos);
206 float2 P_o=(i.pos-i.centerPos);
207 float l1= length(right_center_o-i.centerPos);
208 float dis= dot(right_center_o,P_o)/l1;
209
210 float delta =l1-0.5;
211 float edge = smoothstep(delta, delta+0.5, dis);
212 if(abs(type-1) < 0.05){
213 fixed3 col = lerp( _Color,_LineColor, edge);
214 return fixed4(col, 1.0);
215
216 }
217 else
218 {
219 fixed4 target=fixed4(_LineColor.rbg,0);
220 fixed4 col = lerp(_LineColor, target ,edge);
221 return col;
222 }
223 }
224 else if(PointinTriangle(topCenter,i.centerPos, leftB, i.pos.xy)<=1)
225 {
226 //左三角形内
227 float2 left_center_o=(left_center-i.centerPos);
228 float2 P_o=(i.pos-i.centerPos);
229 float l1= length(left_center_o-i.centerPos);
230 float dis= dot(left_center_o,P_o)/l1;
231
232 float delta =l1-0.5;
233 float edge = smoothstep(delta, delta+0.5, dis);
234 if(abs(type-1) < 0.05){
235 fixed3 col = lerp( _Color,_LineColor, edge);
236 return fixed4(col, 1.0);
237
238 }
239 else
240 {
241 fixed4 target=fixed4(_LineColor.rbg,0);
242 fixed4 col = lerp(_LineColor, target ,edge);
243 return col;
244 }
245 }
246 else
247 {
248 //下三角型内
249 float2 buttom_center_o=(buttom_center-i.centerPos);
250 float2 P_o=(i.pos-i.centerPos);
251 float l1= length(buttom_center_o-i.centerPos);
252 float dis= dot(buttom_center_o,P_o)/l1;
253
254 float delta =l1-0.5;
255 float edge = smoothstep(delta, delta+0.5, dis);
256 if(abs(type-1) < 0.05){
257 fixed3 col = lerp( _Color,_LineColor, edge);
258 return fixed4(col, 1.0);
259 }
260 else
261 {
262 fixed4 target=fixed4(_LineColor.rbg,0);
263 fixed4 col = lerp(_LineColor, target ,edge);
264 return col;
265 }
266 }
267 }
268
269 //截交叉十字形点
270 void DrawCrossPoint(g2f i,float type)
271 {
272
273 float _R = abs(type) < 0.05 ? 0.92 * _Radius : (0.92 * _Radius - _LineWidth);
274
275 //宽度
276 _CrossPointWidth=_R/3;
277
278 float _InPoint = abs(type) < 0.05 ? _CrossPointWidth / 2 : (_CrossPointWidth - _LineWidth) / 2;
279
280 //计算边缘点
281 float2 leftTop=float2(i.centerPos.x - _R , i.centerPos.y + _R);
282 float2 leftButtom=float2(i.centerPos.x - _R , i.centerPos.y - _R);
283 float2 rightTop=float2(i.centerPos.x + _R , i.centerPos.y + _R);
284 float2 rightButtom=float2(i.centerPos.x + _R , i.centerPos.y - _R);
285
286 //十字架内角点
287 float2 inRightTop=float2(i.centerPos.x + _InPoint , i.centerPos.y + _InPoint);
288 float2 inLeftTop=float2(i.centerPos.x - _InPoint , i.centerPos.y + _InPoint);
289 float2 inRightButtom=float2(i.centerPos.x + _InPoint , i.centerPos.y - _InPoint);
290 float2 inLeftButtom=float2(i.centerPos.x - _InPoint , i.centerPos.y - _InPoint);
291
292 if(((i.pos.x) > (inRightTop.x) & (i.pos.y) > (inRightTop.y)) | ((i.pos.x) < (inLeftTop.x) & (i.pos.y) > (inLeftTop.y)) | ((i.pos.x) > (inRightButtom.x) & (i.pos.y) < (inRightButtom.y)) | ((i.pos.x) < (inLeftButtom.x) & (i.pos.y) < (inLeftButtom.y)) | ((i.pos.x) <= (i.centerPos.x - _R) | (i.pos.x) >= (i.centerPos.x+ _R)) | ((i.pos.y) <= (i.centerPos.y- _R) | (i.pos.y) >= (i.centerPos.y+ _R)))
293 {
294 discard;
295 }
296 }
297
298 v2g vert(appdata_full v)
299 {
300 v2g o;
301 o.vertex = v.vertex;
302 o.nor=v.normal;
303 o.color=v.color;
304 return o;
305 }
306
307 float3 _CenterOffset=float3(0,0,0);
308 float3 GetTowardsCamera(float3 objectPos, float3 normal, float3 upDir, float3 rightDir)
309 {
310 objectPos -= _CenterOffset.xyz;
311
312 float3 localPos = _CenterOffset.xyz + rightDir * objectPos.x + upDir * objectPos.y + normal * objectPos.z;
313
314 return localPos;
315 }
316
317 [maxvertexcount(12)]
318 void geom(triangle v2g IN[3], inout TriangleStream<g2f> tristream)
319 {
320 g2f o;
321 //固定只扩展4个点,且初始偏转为45
322 //矢量点
323 if(IsEqualPixelPoint==0.0)
324 {
325 //中心点
326 //矢量点
327 float3 centerPos=float3(0,0,0);
328 o.centerPos=centerPos;
329 o.color=IN[0].color;
330
331 //正上方点
332 float3 worldUp=float3(0,1,0);
333 float3 p=worldUp * _Radius * 1.414;
334 float3 p1=centerPos;
335 float3 p2=centerPos;
336 float3 p3=centerPos;
337 float3 p4=centerPos;
338
339 //计算偏移角
340 float angle= radians(360/4);
341
342 //求正方形四顶点
343 p1=float3((cos(radians(45)) * (p).x)-(sin(radians(45)) * (p).y),(sin(radians(45)) * (p).x)+(cos(radians(45)) * (p).y),(p).z);
344 p2=float3((cos(angle) * (p1).x)-(sin(angle) * (p1).y),(sin(angle) * (p1).x)+(cos(angle) * (p1).y),(p1).z);
345 p3=float3((cos(angle * 2) * (p1).x)-(sin(angle * 2) * (p1).y),(sin(angle * 2) * (p1).x)+(cos(angle * 2) * (p1).y),(p1).z);
346 p4=float3((cos(angle * 3) * (p1).x)-(sin(angle * 3) * (p1).y),(sin(angle * 3) * (p1).x)+(cos(angle * 3) * (p1).y),(p1).z);
347
348 float3 normal = mul((float3x3)UNITY_MATRIX_I_V, float3(0,0,-1));
349 float3 upDir = abs(normal.y) > 0.999 ? float3(0,0,1) : float3(0,1,0);
350 float3 rightDir = normalize(cross(upDir, normal));
351 upDir = normalize(cross(normal, rightDir));
352
353 p1=GetTowardsCamera(p1, normal, upDir, rightDir);
354 p2=GetTowardsCamera(p2, normal, upDir, rightDir);
355 p3=GetTowardsCamera(p3, normal, upDir, rightDir);
356 p4=GetTowardsCamera(p4, normal, upDir, rightDir);
357
358 //计算法线
359 float3 edgeA = p2 - p1;
360 float3 edgeB = p3 - p1;
361 float3 normalFace = normalize(cross(edgeA, edgeB));
362 o.norg=-normalFace;
363
364 ADD_TRI(p1,p2,p3,o,tristream);
365
366 ADD_TRI(p3,p4,p1,o,tristream);
367
368 }
369 else
370 {
371 //等像素点
372 float4 centerPos1=float4(0,0,0,1);
373 centerPos1= GetScreenPos(centerPos1);
374 float2 up=float2(0,1);
375 float2 pp=up * _Radius * 1.414;
376 //第一个点
377 float4 pp1=centerPos1;
378 float4 pp2=centerPos1;
379 float4 pp3=centerPos1;
380 float4 pp4=centerPos1;
381
382 //计算偏移角
383 float angle= radians(360/4);
384
385 //求正方形四顶点
386 pp1.xy=float2((cos(radians(45)) * (pp).x)-(sin(radians(45)) * (pp).y),(sin(radians(45)) * (pp).x)+(cos(radians(45)) * (pp).y));
387 pp2.xy=float2((cos(angle) * (pp1).x)-(sin(angle) * (pp1).y),(sin(angle) * (pp1).x)+(cos(angle) * (pp1).y));
388 pp3.xy=float2((cos(2 * angle) * (pp1).x)-(sin(2 * angle) * (pp1).y),(sin(2 * angle) * (pp1).x)+(cos(2 * angle) * (pp1).y));
389 pp4.xy=float2((cos(3 * angle) * (pp1).x)-(sin(3 * angle) * (pp1).y),(sin(3 * angle) * (pp1).x)+(cos(3 * angle) * (pp1).y));
390
391 //计算偏移
392 pp1=pp1+float4(centerPos1.xy,0,0);
393 pp2=pp2+float4(centerPos1.xy,0,0);
394 pp3=pp3+float4(centerPos1.xy,0,0);
395 pp4=pp4+float4(centerPos1.xy,0,0);
396
397 //计算法线
398 float3 edgeA = pp2 - pp1;
399 float3 edgeB = pp3 - pp1;
400 float3 normalFace = normalize(cross(edgeA, edgeB));
401 o.norg=-normalFace;
402
403 o.centerPos=centerPos1;
404 o.color=IN[0].color;
405
406 ADD_TRI_Other(pp1,pp2,pp3,o,tristream);
407 ADD_TRI_Other(pp3,pp4,pp1,o,tristream);
408
409 }
410 }
411
412 fixed4 frag (g2f i) : SV_Target
413 {
414
415 //圆形点
416 if (abs(_PointType)<=0.05)
417 {
418 DrawCirclePoint(i,0.0);
419 float dis= distance(i.pos,i.centerPos);
420 float delta = _Radius-0.5;
421 float edge = smoothstep(delta, delta + 0.5, dis );
422 fixed4 target= fixed4(_LineColor.rbg,0);
423 fixed4 col = lerp( _LineColor, target, edge);
424 return col;
425 }
426
427 //正方形
428 if(abs(_PointType-2)<=0.05)
429 {
430 DrawSquarePoint(i,0.0);
431 float _distance=0.9*_Radius;
432 float2 centerTop_center=((float2(i.centerPos.x,i.centerPos.y+_distance))-i.centerPos);
433 float2 pos_center=(i.pos-i.centerPos);
434 float pos_center_dis= distance(i.pos,i.centerPos);
435 float dis= dot(pos_center,centerTop_center)/_distance;
436
437 float delta = _distance-0.5;
438 float edge = smoothstep(delta, delta + 0.5, dis );
439 fixed4 target= fixed4(_LineColor.rbg,0);
440 fixed4 col = lerp( _LineColor, target, edge);
441 return col;
442
443
444 }
445
446 //三角形
447 if(abs(_PointType-1)<=0.05)
448 {
449 DrawTrianglePoint(i,0.0);
450 }
451
452 //交叉十字
453 if(abs(_PointType-3)<=0.05)
454 {
455 DrawCrossPoint(i,0.0);
456 }
457
458 return _LineColor;
459 }
460
461
462 fixed4 fragOther (g2f i) : SV_Target
463 {
464 //圆形点
465 if (abs(_PointType)<=0.05)
466 {
467 DrawCirclePoint(i,1.0);
468 float dis= distance(i.pos,i.centerPos);
469 float delta = _Radius-_LineWidth;
470 float edge = smoothstep(delta-0.5, delta + 0.5, dis );
471 fixed3 col = lerp( _Color, _LineColor, edge);
472 return fixed4(col, 1.0);
473 }
474
475 //正方形
476 if(abs(_PointType-2)<=0.05)
477 {
478 DrawSquarePoint(i,1.0);
479 float _distance=0.9*_Radius-_LineWidth;
480 float2 centerTop_center=((float2(i.centerPos.x,i.centerPos.y+_distance))-i.centerPos);
481 float2 pos_center=(i.pos-i.centerPos);
482 float pos_center_dis= distance(i.pos,i.centerPos);
483 float dis= (dot(pos_center,centerTop_center)/_distance);
484
485 float delta = _distance-0.5;
486 float edge = smoothstep(delta, delta + 0.5, dis );
487 fixed3 col = lerp( _Color, _LineColor, edge);
488 return fixed4(col, 1.0);
489 }
490
491 //三角形
492 if(abs(_PointType-1)<=0.05)
493 {
494 DrawTrianglePoint(i,1.0);
495 }
496
497 //交叉十字
498 if(abs(_PointType-3)<=0.05)
499 {
500 DrawCrossPoint(i,1.0);
501 }
502
503 return _Color;
504 }
505
506 ENDCG
507
508 Pass
509 {
510 NAME "InitShader"
511
512 Cull Off
513 ZTest Off
514 Blend SrcAlpha OneMinusSrcAlpha
515
516 CGPROGRAM
517
518 #pragma target 4.0
519 #pragma vertex vert
520 #pragma geometry geom
521 #pragma fragment frag
522
523 ENDCG
524 }
525
526 Pass
527 {
528 NAME "LineShader"
529 ZTest Off
530 Cull Off
531
532 CGPROGRAM
533
534 #pragma target 4.0
535 #pragma vertex vert
536 #pragma geometry geom
537 #pragma fragment fragOther
538
539 ENDCG
540 }
541
542 }
543
544 FallBack "Diffuse"
545 }
Unity 中使用Geomotry Shader(几何着色器)扩展点创建其他图形(并实现处理锯齿)的更多相关文章
- Unity 几何着色器
Unity 几何着色器 shaderGeometry Shader几何着色器 Unity 几何着色器 如果学习不能带来价值,那将毫无意义 简介 在顶点和片段着色器之间有一个可选的着色器,叫做几 ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十二章:几何着色器(The Geometry Shader)
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十二章:几何着色器(The Geometry Shader) 代码工 ...
- DirectX11 With Windows SDK--17 利用几何着色器实现公告板效果
前言 上一章我们知道了如何使用几何着色器将顶点通过流输出阶段输出到绑定的顶点缓冲区.接下来我们继续利用它来实现一些新的效果,在这一章,你将了解: 实现公告板效果 Alpha-To-Coverage 对 ...
- 翻译:探索GLSL-用几何着色器(着色器库)实现法线可视化
翻译:探索GLSL-用几何着色器(着色器库)实现法线可视化 翻译自: Exploring GLSL – Normal Visualizer with Geometry Shaders (Shader ...
- Initialize the shader 初始化着色器
目录 Loads the shader files and makes it usable to DirectX and the GPU 加载着色器文件并使其可用于DirectX和GPU Compil ...
- DirectX11 With Windows SDK--15 几何着色器初探
前言 从这一部分开始,感觉就像是踏入了无人深空一样,在之前初学DX11的时候,这部分内容都是基本上跳过的,现在打算重新认真地把它给拾回来. DirectX11 With Windows SDK完整目录 ...
- 【原创翻译】初识Unity中的Compute Shader
一直以来都想试着自己翻译一些东西,现在发现翻译真的很不容易,如果你直接把作者的原文按照英文的思维翻译过来,你会发现中国人读起来很是别扭,但是如果你想完全利用中国人的语言方式来翻译,又怕自己理解的不到位 ...
- 【Unity Shaders】Lighting Models —— 衣服着色器
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- GDC2017【神秘海域 4】中所使用的顶点着色器技术
原文链接 http://game.watch.impress.co.jp/docs/news/1047802.html 会場:San Francisco Moscone Convention Ce ...
- 在pixi中使用你的自定义着色器
通过几天的学习,对openGL.shader有了一个大致的了解. 回到学习的初衷吧,在基于pixi.js重构D3项目的时候,因为精灵层级的问题,我得按照一定的先后顺序将不同类别的精灵添加到场景中去. ...
随机推荐
- python教程1.2:变量+数据类型+运算符
一.变量 程序是从上到下依次逐⾏执⾏的,所以变量必须先定义,后调⽤, 否则会报错 变量定义规范 二.数据类型 1.数字类型 可⽤ type() ⽅法来查看数据类型 2.字符串 多引号 多引号什么作 ...
- C++ placement new学习
通常创建对象使用new操作,但这样无法指定在具体某一块内存开辟空间创建对象.而如果 可以指定开辟空间的内存位置,我们可以编写内存池高效的复用同一个内存位置,这样可以避免系统频繁申请可用内存 所占用的时 ...
- PPO-KL散度近端策略优化玩cartpole游戏
其实KL散度在这个游戏里的作用不大,游戏的action比较简单,不像LM里的action是一个很大的向量,可以直接用surr1,最大化surr1,实验测试确实是这样,而且KL的系数不能给太大,否则惩罚 ...
- jupyter notebook无法找到自己的虚拟环境
1:打开cmd/Anaconda Prompt/Anaconda Powershell Prompt 2:进入虚拟环境conda activate 环境名 3:conda list查看有无ipyker ...
- Vue 3 组件基础与模板语法详解
title: Vue 3 组件基础与模板语法详解 date: 2024/5/24 16:31:13 updated: 2024/5/24 16:31:13 categories: 前端开发 tags: ...
- 三:nacos的配置中心
配置中心的使用: 编辑当前项目的pom.xml,加入必要的依赖配置 <!-- spring-cloud-alibaba-dependencies 依赖同注册中心 --> <depen ...
- 解决idea 控制台输出乱码问题:
解决idea 控制台输出乱码问题[IntelliJ IDEA 2022.1.3 (Ultimate Edition)]: 将两个地方文件编码设置成GBK 参考文档:https://blog.c ...
- weinre 远程实时调试手机上的Web页面 JAVASCRIPT远程调试
版权归作者所有,任何形式转载请联系作者.作者:U_U(来自豆瓣)来源:https://www.douban.com/note/289846168/ 调试前端页面我一直使用着神器Chrome开发人员工具 ...
- 在Windows上运行Rainbond,10分钟快速安装
前言 Windows 桌面运行 Rainbond,Windows 开发者的新选择. 经过适配Mac以后,Windows的适配也是成为了近期的小目标,经过不断地测试,不断地研究.最后也是达成了完美运行的 ...
- 「C++」论高精度
大家好,我是Charzie.在编程领域,高精度计算是一个常见的问题.当标准的整型或浮点型无法满足我们的计算需求时,高精度计算就显得尤为重要.在C++中,虽然标准库没有直接提供高精度数据类型,但我们可以 ...