我试图用点精灵重现这种效果(给定顶点有位置和法线)。
基本上丢弃点精灵的碎片,取决于该点的法线,以产生与点法线相切的椭圆形状(基本上近似于3D圆的正投影到2D椭圆)。
从等式中我发现d = - (nx / nz)* x-(ny / nz)* y,其中如果从点中心到点(x,y,d)的世界空间距离,则丢弃片段)大于磁盘半径(如图像上方的文字所示)。
我正在尝试使用点精灵在我的GLSL顶点和片段着色器中找到正确的方法。
在我的着色器中我正在做这样的事情,这是行不通的:
//vertex shader
#version 400
layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec3 VertexNormal;
out vec3 Color;
flat out vec3 PtPosition;
flat out vec3 PtNormal;
out vec3 FragPosition;
uniform mat4 MVP;
uniform float heightMin;
uniform float heightMax;
uniform bool invertGrad = false;
uniform mat4 MV;
uniform float pointSize;
uniform float viewportDim;
float perspPtSize(vec3 ptPos, mat4 mv, float ptWorldSize, float viewportDim)
{
vec3 posEye = vec3(mv * vec4(ptPos, 1.0));
return ptWorldSize * (viewportDim / length(posEye));
}
void main()
{
Color = vec3(1.0,1.0,1.0);
PtPosition = vec3(MV * vec4(VertexPosition,1.0));
FragPosition = PtPosition;
PtNormal = vec3(MV * vec4(VertexNormal,1.0));
gl_Position = MVP * vec4(VertexPosition,1.0);
gl_PointSize = perspPtSize(VertexPosition.xyz,MV,pointSize,viewportDim);
}
//fragment shader
#version 400
layout( location = 0 ) out vec4 FragColor;
in vec3 Color;
flat in vec3 PtPosition;
flat in vec3 PtNormal;
void main()
{
vec2 ptC = gl_PointCoord- vec2(0.5);
float depth = -PtNormal.x/PtNormal.z*ptC.x -
PtNormal.y/PtNormal.z*ptC.y;
float sqrMag = ptC.x*ptC.x + ptC.y*ptC.y + depth*depth;
if(sqrMag > 0.25)
{ discard; }
else
{ fragColor = vec4(color, 1.0); }
}
有没有人成功实现过这样的效果?我尝试在世界空间中这样做但最终得到的结果不正确,我想如果我把它全部留在点精灵表示的空间中它可能会更容易。
我认为我遗漏了一些基本概念,这有什么建议吗?
答案 0 :(得分:0)
顺便说一下,gl_PointCoord
在屏幕空间中,你的法线在视图空间中是(某种)(所以并非所有内容都在“gl_PointCoord
表示的空间”中完成。) / p>
我建议您使用普通矩阵(MV
的左上角3x3子矩阵的转置反转)来转换法线而不是ModelView矩阵,否则它们将无法正确旋转。如果MV
矩阵中存在任何缩放,您还需要在执行此操作后重新规范化法线。
在这方面,如果您打算将法线乘以4x4矩阵,无论出于何种原因,请不要将W
坐标设置为 1.0 。 W = 1.0 用于空间向量(例如 平移 实际上有意义的向量),而法线是定向的;请改用 0.0 。
答案 1 :(得分:0)
尝试将一个减号更改为加号,如:
float depth = -PtNormal.x/PtNormal.z*ptC.x + PtNormal.y/PtNormal.z*ptC.y;
似乎有一个( - )太多了。希望有所帮助
(我正在读这本书并遇到同样的问题......迟到总比我想的要好;-))