围绕选定的对象创建一个高光晕

我正在寻找围绕我的游戏画面中选定的对象创建光环高光。 主要的平台是android,但我也写了一个iOS版本,每当我成功添加下一个function时更新它。

我试图确保游戏能够在OpenGLES 1和2中工作,但我当然希望v2最终能够产生更多的效果。

我想达到的效果是在所选对象边缘有一个光环(我相信暗黑破坏神II做了类似的事情)。 理论上我的想法是渲染场景,当选定的对象被渲染时启用模板操作,然后启用模板testing,禁用深度并设置正交投影,并在对象的X和Y维度中的每一个中绘制大5像素的晕轮颜色以0.2阿尔法为中心,然后再次抽取,减小尺寸和混合。

使用这种方法,我也需要找出确定对象中心和范围的最有效的方法。

编辑:另一个技术,我只是想过后发布是,模具运行渲染后,呈现一个彩色正交矩形通过模具纹理,然后收缩和重新放大的图像模糊边缘,然后渲染合成纹理回到顶部现场,在模板区周围

  1. 这些都是达到效果的好方法吗? 有没有更好/更快/更有效率/更常见的做法?
  2. 我是否应该为v1做这个工作,并使之成为v2唯一的效果?
  3. 如果我想要这些效果,我应该打扰v1吗?

你在用3D吗? 然后,你可以添加轻微缩放版本的相同的对象,这是在你的光环颜色着色,并有0.2阿尔法。 然后在所有这些光晕对象之后渲染真实的对象

这个想法是,你沿着它们的法线挤压物体顶点。

首先渲染高亮:

  • 渲染禁用z写入的对象,但启用ztesting。
  • 顶点着色器:在传递它之前,给每个顶点添加正常的*高亮大小
  • 片段着色器:仅渲染颜色,不应用照明

然后渲染对象:

  • 使用z写入和ztesting启用渲染。
  • 用正常的着色器渲染。
  • 对象将在高亮处呈现,只留下边缘突出显示。

下面是Unity3D完美的教程video,着色器源代码: https : //www.youtube.com/watch?v = 00qMZlacZQo

它呈现出鲜明的亮点,我不知道如何有效地模糊它们。 也许从顶点到片段,您可以传递实际的顶点位置,并使用距离来更改alpha。 但是这样做也无济于事,因为这个位置也会被内插。 也许使用单通线框渲染的概念。

由于Aeroson的回答(上面/下面/相邻/ 围绕着这个问题),这个问题突然出现了,并且认为如果对某人有用,我会回答这个问题 。

下面的着色器是这样做的:

在这里输入图像描述

缺点:

  • 而不是一个移动友好的着色器,由于使用模板缓冲区和渲染对象两次(取决于有问题的设备的function,这可能是可以接受的)。
  • 需要向前照明(在延迟渲染path中呈现的对象的模板function在某种程度上是有限的,因为在基础通过和照明过程中,模板缓冲区被用于其他目的)。
  • 不会渲染对象本身(尽管可能通过调整几何输出来修复)。

我意识到这个问题具体要求移动解决scheme,但是更一般的“围绕对象绘制轮廓”问题是非常普遍的,我花了好几个小时寻找一个好的解决scheme,结果不得不手写这个着色器,因为常见的解决scheme不足以满足我的需求

Shader "Stencil/Outline" { Properties { _Color("Color", Color) = (1,0,0,1) _Thickness("Thickness", float) = 4 } 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; }; 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 return 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; 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.uv = v.texcoord; OUT.normals = v.normal; OUT.viewT = ObjSpaceViewDir(v.vertex); return OUT; } void geom2(v2g start, v2g end, inout TriangleStream<g2f> triStream) { float thisWidth = _Thickness/100; float4 parallel = end.pos-start.pos; normalize(parallel); parallel *= thisWidth; float4 perpendicular = float4(parallel.y,-parallel.x, 0, 0); perpendicular = normalize(perpendicular) * thisWidth; float4 v1 = start.pos-parallel; float4 v2 = end.pos+parallel; g2f OUT; OUT.pos = v1-perpendicular; OUT.uv = start.uv; OUT.viewT = start.viewT; OUT.normals = start.normals; triStream.Append(OUT); OUT.pos = v1+perpendicular; triStream.Append(OUT); OUT.pos = v2-perpendicular; OUT.uv = end.uv; OUT.viewT = end.viewT; OUT.normals = end.normals; triStream.Append(OUT); OUT.pos = v2+perpendicular; OUT.uv = end.uv; OUT.viewT = end.viewT; OUT.normals = end.normals; triStream.Append(OUT); } [maxvertexcount(12)] void geom(triangle v2g IN[3], inout TriangleStream<g2f> triStream) { geom2(IN[0],IN[1],triStream); geom2(IN[1],IN[2],triStream); geom2(IN[2],IN[0],triStream); } half4 frag(g2f IN) : COLOR { _Color.a = 1; return _Color; } ENDCG } } FallBack "Diffuse" }