- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在我的 CAD 查看器中需要一定粗细的线条,我发现我应该使用几何着色器来完成它。
然后我继续寻找一个几何着色器的演示代码,该着色器以给定的粗细创建线条。
此处:https://github.com/paulhoux/Cinder-Samples/blob/master/GeometryShader/assets/shaders/lines1.geom
在这里讨论:https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader
此着色器是用 OpenGL 编写的,但我将其转换为 DirectX。
我现在遇到的问题是着色器生成的面孔忽略了我的 Z 缓冲区(深度缓冲区),我是否错过了一些非常重要的事情?
我的完整着色器代码:
//Input for the vertex shader
struct VS_IN
{
float4 pos : POSITION;
float4 col : COLOR;
};
//Input for the geometry shader, as provided by the vertex shader
struct GS_IN
{
float4 pos : SV_POSITION;
float4 col : COLOR;
};
//Input for the pixel shader, as provided by the geometry shader
struct PS_IN
{
float4 pos : SV_POSITION;
float4 col : COLOR;
};
//Only used in the vertex shader, to give the vertex its final position on screen
cbuffer viewProj : register (b0)
{
matrix viewProj;
}
//The vertex shader
GS_IN VS(VS_IN input)
{
GS_IN output = (GS_IN)0;
//Should multiply it by a world matrix of identity, so the input vertices should be using world coordinates...
output.pos = mul(input.pos, viewProj);
output.col = input.col;
return output;
};
//The geometry shader
cbuffer windowSize : register (b1)
{
float2 WIN_SCALE;
}
float MITER_LIMIT = -1;
float THICKNESS = 10;
float2 screen_space(float4 vertex)
{
return float2(vertex.xy / vertex.w) * WIN_SCALE;
}
[maxvertexcount(7)]
void GS(lineadj GS_IN input[4], inout TriangleStream<PS_IN> OutputStream)
{
// get the four vertices passed to the shader:
float2 p0 = screen_space(input[0].pos); // start of previous segment
float2 p1 = screen_space(input[1].pos); // end of previous segment, start of current segment
float2 p2 = screen_space(input[2].pos); // end of current segment, start of next segment
float2 p3 = screen_space(input[3].pos); // end of next segment
// perform naive culling
/*
float2 area = WIN_SCALE * 1.2;
if (p1.x < -area.x || p1.x > area.x) return;
if (p1.y < -area.y || p1.y > area.y) return;
if (p2.x < -area.x || p2.x > area.x) return;
if (p2.y < -area.y || p2.y > area.y) return;
*/
// determine the direction of each of the 3 segments (previous, current, next)
float2 v0 = normalize(p1 - p0);
float2 v1 = normalize(p2 - p1);
float2 v2 = normalize(p3 - p2);
// determine the normal of each of the 3 segments (previous, current, next)
float2 n0 = float2(-v0.y, v0.x);
float2 n1 = float2(-v1.y, v1.x);
float2 n2 = float2(-v2.y, v2.x);
// determine miter lines by averaging the normals of the 2 segments
float2 miter_a = normalize(n0 + n1); // miter at start of current segment
float2 miter_b = normalize(n1 + n2); // miter at end of current segment
// determine the length of the miter by projecting it onto normal and then inverse it
float length_a = THICKNESS / dot(miter_a, n1);
float length_b = THICKNESS / dot(miter_b, n1);
PS_IN output = (PS_IN)0;
if (dot(v0, v1) < -MITER_LIMIT) {
miter_a = n1;
length_a = THICKNESS;
// close the gap
if (dot(v0, n1) > 0) {
output.col = input[1].col;
output.pos = float4((p1 + THICKNESS * n0) / WIN_SCALE, 0.0, 1.0);
OutputStream.Append(output);
output.col = input[1].col;
output.pos = float4((p1 + THICKNESS * n1) / WIN_SCALE, 0.0, 1.0);
OutputStream.Append(output);
output.col = input[1].col;
output.pos = float4(p1 / WIN_SCALE, 0.0, 1.0);
OutputStream.Append(output);
}
else {
output.col = input[1].col;
output.pos = float4((p1 - THICKNESS * n1) / WIN_SCALE, 0.0, 1.0);
OutputStream.Append(output);
output.col = input[1].col;
output.pos = float4((p1 - THICKNESS * n0) / WIN_SCALE, 0.0, 1.0);
OutputStream.Append(output);
output.col = input[1].col;
output.pos = float4(p1 / WIN_SCALE, 0.0, 1.0);
OutputStream.Append(output);
}
}
if (dot(v1, v2) < -MITER_LIMIT) {
miter_b = n1;
length_b = THICKNESS;
}
// generate the triangle strip
output.col = input[1].col;
output.pos = float4((p1 + length_a * miter_a) / WIN_SCALE, 0.0, 1.0);
OutputStream.Append(output);
output.col = input[1].col;
output.pos = float4((p1 - length_a * miter_a) / WIN_SCALE, 0.0, 1.0);
OutputStream.Append(output);
output.col = input[2].col;
output.pos = float4((p2 + length_b * miter_b) / WIN_SCALE, 0.0, 1.0);
OutputStream.Append(output);
output.col = input[2].col;
output.pos = float4((p2 - length_b * miter_b) / WIN_SCALE, 0.0, 1.0);
OutputStream.Append(output);
};
//The pixel shader
float4 PS(PS_IN input) : SV_Target
{
return input.col;
};
technique10 Render
{
pass P0
{
SetVertexShader(CompileShader(vs_4_0, VS()));
SetGeometryShader(CompileShader(gs_4_0, GS()));
SetPixelShader(CompileShader(ps_4_0, PS()));
}
}
如果我禁用几何着色器,我会得到:
如果我启用几何着色器,我会得到:
如您所见,粗线突然出现在其他所有内容的前面。
这可以修复吗?我应该使用不同的方法吗?几何着色器真的是解决方案吗?
编辑 1: 我发现它并没有忽略 Z 缓冲区,而是用尽可能接近的深度值填充它(调试时为黑色)。为什么会这样?
最佳答案
我认为几何缓冲区对于您的情况来说是一个很好且快速的解决方案。
您的错误发生是因为您的几何缓冲区将所有 z 值设置为 0.0,因此任何深度信息都将被丢弃。输出的三角形都在屏幕空间的同一深度平面上。要解决此问题,它们应该继承原始线条的深度值。
请记住,这可能会导致交集问题,例如如果你的线靠近地面,膨胀的线会穿透地面并且看起来比其他线更细。
关于c++ - 几何着色器输出可能用最接近的值填充 Z-Buffer? (DirectX),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28437949/
我想创建一个返回值的方法(我们称之为“z”)。它的值由另一个值决定(我们称之为“y”)。基本上我想要的是满足以下条件: 当 x 接近 0 时,z 接近 100。 当 x 接近无穷大时,z 接近 0。
我正在尝试使用 Java 中的PreparedStatement 执行查询。 当我尝试执行查询时,收到错误号 1064(语法错误)。 我已经在 MySQL 查询浏览器中使用替换值对此进行了测试,效果很
我正在开发一个应用程序来解析 Scala 中的命令。命令的一个例子是: todo get milk for friday 所以计划是让一个非常智能的解析器将行分开并识别命令部分以及字符串中有时间引用的
来自 http://directwebremoting.org/dwr/reverse-ajax/index.html ,它表示它支持轮询、 cometd 、搭载。这是否意味着当我们实现这种方法时,我
我开始研究一个概念,该概念要求我找到一种方法,以给定的速度将矩形移向给定的点。我正在为 Android 开发,所以这对速度非常关键(它也将针对可能的数百个对象计算每一帧。) 我能想到的解决方案如下:
我正在处理一个处理“门票”的表(状态=“开放”或状态=“关闭”)。当票证关闭时,相关系统不会更改状态,而是会创建一个具有“已关闭”状态的重复条目。 对于“ticket_number”关键字段,如果存在
我正在尝试在 python 中执行一些 n-gram 计数,我想我可以使用 MySQL(MySQLdb 模块)来组织我的文本数据。 我有一个很大的表,大约有 1000 万条记录,代表由唯一数字 ID(
我正在尝试将数据添加到 mariadb 表中。我想将 val0 到 val5 作为查询的值传递。但我收到错误 OperationalError: close "%": 语法错误代码 list_Valu
我正在使用 (Py)OpenGL 显示 256 色索引图像。我将着色器与包含调色板的一维纹理一起使用。这是片段着色器代码: #version 330 uniform sampler2D texture
对于我的元素 areallybigpage.com (*),我想看看我们能用 CSS 的 transform: scale(...) 走多远。 这有效并以正常大小显示文本: #id1 { positi
我有两列带有数字数据的 Pandas 表(dtype flaot64)。 我将每列四舍五入到小数点后有 2 位数字,然后使用函数将其四舍五入到接近 0.5,但由于某种原因,只有一列四舍五入为 0.05
我正在构建一个由用户登录和注册组成的应用程序,但每次我在模拟器上测试它时,我都会收到强制关闭。以下是我在日志猫中收到的错误: 08-14 14:06:28.853: D/dalvikvm(828):
我正在尝试在 Python 中实现 Strassen 矩阵乘法。我已经让它发挥了一些作用。这是我的代码: a = [[1,1,1,1],[2,2,2,2],[3,3,3,3],[4,4,4,4]] b
为什么这不起作用?这与 = 附近的命令字符串语法有关,但我似乎无法弄清楚,在线示例似乎完全相同。编辑: Activated In 是一列。 示例来自 How to select data from d
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求提供代码的问题必须表现出对所解决问题的最低限度理解。包括尝试过的解决方案、为什么它们不起作用,以及
我有一个测试区,它是来自数据库的动态文本,可能有数千个单词。我希望它中断并在每段中用句号将近 100 个(任意长度)单词作为一个段落。我能够在 100 个单词后中断,但不能完全停止。为了在 100 个
我是 hadoop 和 hive 的新手。我正在尝试将数据加载到配置单元表中,但遇到以下错误。 另一方面,我尝试使用语句 stmt.execute("INSERT INTO employee VALU
这是来自一个统计项目。我定义了下面的函数,但是当n接近400时,第二个方法很慢。第一个方法很好(这里有人帮助了我in this question) import Math.Combinatorics.
我正在尝试创建一个 css 侧边菜单,但是当我关闭菜单并将 div 容器宽度设置为 0 时,链接仍然可见。 这是 jsfiddle - https://jsfiddle.net/atLvp6k7/ 有
我对 MySQL 还很陌生。我必须使用输出参数调用存储过程。我在互联网上搜索了很多,但没有找到解决我的问题的正确方法。如果我使用 @outputParamName 调用存储过程,它会说我在 NULL
我是一名优秀的程序员,十分优秀!