Java NASA Worldwind 多边形与内部边界
Posted
技术标签:
【中文标题】Java NASA Worldwind 多边形与内部边界【英文标题】:Java NASA Worldwind Polygon with Internal Border 【发布时间】:2018-02-01 06:19:32 【问题描述】:所以我的目标是创建一个系统,您可以在其中绘制一个曲面多边形,并且它基本上在多边形周围制作一个虚线边框。问题是我希望这个边框是一个固定大小,这意味着每个破折号应该是多边形周围的一个固定大小。我也在努力弄清楚如何制作它,这样如果你增加表面多边形的边框大小,它就不会向外扩展,只会向内扩展,这样尺寸就会倾斜。
长话短说,我基本上开始计算自己的虚线边框并手工绘制每个虚线。问题出现在它们相遇的角度上,当破折号延伸到多边形之外时,会切断额外的长度。所附图片显示了我到目前为止所拥有的以及它本质上应该是什么样子。我也有点想保持多边形上的正常边框与图片中的一样,但这不是强制性的。
我想我只是很惊讶这在 NASA Worldwind 中很难做到,而在 directX 中大约有 20 行。这让我觉得我走错了路。
就像一个注释。我研究过使用模板缓冲区,但事实证明这几乎是浪费时间来开始工作并在世界风中正确运行。我认为我没有足够的把握来正确地做到这一点。
附:我开始使用的所有东西都不是一成不变的。我只需要最终结果是正确的。感谢您的帮助。
TLDR:需要绘制具有设定宽度的内部边框的多边形。
【问题讨论】:
您当然可以在几何着色器中执行此操作,同时吐出三角形本身和粗线边框。但是,这是相当先进的。所有的线图库都必须在连接处考虑斜接、圆形、斜角等。这是一个不平凡的话题。 SO 可能回答的太多了。 您能否指出我可以找到有关几何着色器的更多信息的方向?我很惊讶制作一个简单的边框是如此之难。 那里有很多 tuts。谷歌搜索“几何着色器+opengl”,也许还有“几何着色器+粗线+opengl”。 目前我正在使用内置的曲面多边形并为其提供点列表。用户当前只是点击点。它们是多边形。所以它可能是一个凸多边形,也可能是一个三角形,这取决于你如何绘制它。 【参考方案1】:我建议先绘制(绿色)区域,然后绘制虚线(白色)。 绘制线条时,Geometry Shader 可用于将线段转换为四边形(具有 4 个点的三角形条纹),以给定的线条粗细包围薄区域,该区域将由实线填充。片段着色器最终必须划线(切割线的一部分)。最后Fragment Shader 必须生成虚线(从线中切出部分)。
要画线,必须使用Primitive 类型GL_LINE_STRIP_ADJACENCY
(参见GLSL Tutorial - Primitive Assembly),因为每个线段都必须知道它的前任和后继,才能计算角度角平分线。如果多边形由线列表定义,则可以轻松完成。列表的最后一个点必须添加到点列表的开头,列表的第一个点必须添加到点列表的末尾。
例如如果一个多边形由点A、B、C和D组成,那么GL_LINE_STRIP_ADJACENCY
将是 D、A、B、C、D 和一个。这将给出以下 4 个线段:
Vertex Shader 只需通过多边形的角点:
#version 400
layout (location = 0) in vec3 inPos;
out TVertexData
out vec3 pos;
outData;
void main()
outData.pos = inPos;
gl_Position = vec4( inPos, 1.0 );
Geometry Shader计算每条线段的起点和终点的角平分线,并根据线的粗细生成一个四边形。 由于片段着色器还需要生成虚线,所以计算出线的长度和线的中心,并传递给片段着色器。
#version 400
layout( lines_adjacency ) in;
layout( triangle_strip, max_vertices = 4 ) out;
in TVertexData
vec3 pos;
inData[];
out TGeometryData
vec3 linePos;
vec3 lineMidPoint;
float lineLen;
outData;
uniform float u_thickness;
void main()
if ( gl_InvocationID != 0 )
return;
vec3 pos0 = inData[1].pos;
vec3 pos1 = inData[2].pos;
vec3 dirPred = normalize( inData[0].pos - pos0 );
vec3 dirSucc = normalize( inData[3].pos - pos1 );
vec3 dirLine = normalize( pos1 - pos0 );
vec3 dirNorm = normalize( dirPred - dirLine * dot(dirLine, dirPred) );
dirSucc = faceforward( dirSucc, -dirNorm, dirSucc );
vec3 dir0 = abs( dot(dirPred, dirLine) ) > 0.99 ? dirNorm : normalize( dirPred + dirLine );
vec3 dir1 = abs( dot(dirSucc, dirLine) ) > 0.99 ? dirNorm : normalize( dirSucc - dirLine );
vec3 pos01 = pos0 + dir0 * u_thickness / dot(dir0, dirNorm);
vec3 pos11 = pos1 + dir1 * u_thickness / dot(dir1, dirNorm);
vec3 lineMidPoint0 = (pos0 + pos1) * 0.5;
vec3 lineMidPoint1 = lineMidPoint0 + dirNorm * u_thickness;
outData.lineLen = length( pos1 - pos0 );
outData.lineMidPoint = lineMidPoint0;
outData.linePos = pos0;
gl_Position = vec4(pos0, 1.0); EmitVertex();
outData.linePos = pos1;
gl_Position = vec4(pos1, 1.0); EmitVertex();
outData. lineMidPoint = lineMidPoint1;
outData.linePos = pos01;
gl_Position = vec4(pos01, 1.0); EmitVertex();
outData.linePos = pos11;
gl_Position = vec4(pos11, 1.0); EmitVertex();
EndPrimitive();
最后Fragment Shader 通过丢弃间隙中的片段生成虚线。
#version 400
in TGeometryData
vec3 linePos;
vec3 lineMidPoint;
float lineLen;
inData;
out vec4 fragColor;
uniform float u_dashLen;
uniform float u_gapLen;
uniform vec4 u_color;
void main()
float midDist = length( inData.linePos - inData.lineMidPoint );
float modDist = mod( midDist + u_dashLen * 0.5, u_dashLen + u_gapLen );
float onDash = max( step( modDist, u_dashLen ),
step( inData.lineLen * 0.5 - u_dashLen, midDist ) );
if ( onDash < 0.5 )
discard;
fragColor = u_color * onDash;
注意,这个Fragment Shader 使用discard
关键字来丢弃虚线间隙中的片段。如果使用Blending,则可以省略(if ( onDash < 0.5 ) discard;
),因为间隙中的片段将使用alpha通道0绘制。
如果先绘制填充的(绿色)多边形,然后绘制虚线(白色),则结果可能如下所示:
【讨论】:
这太棒了。非常感谢。甚至不想问,但你能补充一下你是如何从 NASA 世界风中调用这些的吗?表示如何将着色器应用于 Gl 对象。 所以我一直在现有代码中进行设置。我激活了着色器,但它搞砸了 Globe,因为它似乎被应用于所有东西。如何将着色器应用于某个可渲染对象?以上是关于Java NASA Worldwind 多边形与内部边界的主要内容,如果未能解决你的问题,请参考以下文章
在Eclipse配置并编译worldwind java2.1.0源码,选中Src目录下gov.nasa.worldwindx.examples包下ApplicationTemplate.java类文件