gpt4 book ai didi

iPad GLSL。从片段着色器中如何获得表面(而不是顶点)法线

转载 作者:行者123 更新时间:2023-12-02 02:51:55 25 4
gpt4 key购买 nike

是否可以从片段着色器内访问表面法线(与片段平面相关的法线)?或者也许这可以在顶点着色器中完成?

当我们沿着着色器管道走下去时,相关几何体的所有知识是否都会丢失,或者是否有一些巧妙的方法可以在片段着色器的顶点中恢复该信息?

提前致谢。

干杯,
道格
推特:@dugla

最佳答案

表面法线向量可以通过片段着色器中 View 空间位置的偏导数来近似计算。偏导数可以通过函数 dFdx and dFdy 得到。为此,需要 OpenGL es 3.0 或 OES_standard_derivatives扩展名:

in vec3 view_position;

void main()
{
vec3 normalvector = cross(dFdx(view_position), dFdy(view_position));
nv = normalize(normalvector * sign(normalvector.z));

.....
}
<小时/>

通常,可以在几何着色器中计算表面的法线向量(自 OpenGL ES 3.2 起)。例如,如果您绘制三角形,您将在几何着色器中获得所有三个点。三个点定义一个平面,可以从该平面计算法向量。您只需小心这些点是顺时针还是逆时针排列即可。

三角形的法向量是定义的 2 个向量的归​​一化叉积由三角形的角点。请参阅以下逆时针三角形示例:

顶点着色器

#version 400

layout (location = 0) in vec3 inPos;

out vec3 vertPos;

uniform mat4 u_projectionMat44;
uniform mat4 u_modelViewMat44;

void main()
{
vec4 viewPos = u_modelViewMat44 * vec4( inPos, 1.0 );
vertPos = viewPos.xyz;
gl_Position = u_projectionMat44 * viewPos;
}

几何着色器

#version 400

layout( triangles ) in;
layout( triangle_strip, max_vertices = 3 ) out;

in vec3 vertPos[];

out vec3 geoPos;
out vec3 geoNV;

void main()
{
vec3 leg1 = vertPos[1] - vertPos[0];
vec3 leg2 = vertPos[2] - vertPos[0];
geoNV = normalize( cross( leg1, leg2 ) );

geoPos = vertPos[0];
EmitVertex();
geoPos = vertPos[1];
EmitVertex();
geoPos = vertPos[2];
EmitVertex();
EndPrimitive();
}

片段着色器

#version 400

in vec3 geoPos;
in vec3 geoNV;

void main()
{
// ...
}

当然,您也可以在曲面分割着色器中计算法线向量(自 OpenGL ES 3.2 起)。但只有当您出于其他原因需要曲面分割着色器并另外计算时,这才有意义脸部的法线向量:

顶点着色器

顶点着色器与上面相同。

曲面分割控制着色器

#version 400

layout( vertices=3 ) out;

in vec3 vertPos[];
out vec3 tctrlPos[];

void main()
{
tctrlPos[gl_InvocationID] = vertPos[gl_InvocationID];

if ( gl_InvocationID == 0 )
{
gl_TessLevelOuter[0] = ;
gl_TessLevelOuter[1] = ;
gl_TessLevelOuter[2] = ;
gl_TessLevelInner[0] = ;
}
}

曲面分割评估着色器

#version 400

layout(triangles, ccw) in;

in vec3 tctrlPos[];

out vec3 tevalPos;
out vec3 tevalNV;

void main()
{
vec3 leg1 = tctrlPos[1] - tctrlPos[0];
vec3 leg2 = tctrlPos[2] - tctrlPos[0];
tevalNV = normalize( cross( leg1, leg2 ) );

tevalPos = tctrlPos[0] * gl_TessCoord.x + tctrlPos[1] * gl_TessCoord.y + tctrlPos[2] * gl_TessCoord.z;
}

片段着色器

#version 400

in vec3 tevalPos;
in vec3 tevalNV;

void main()
{
// ...
}

关于iPad GLSL。从片段着色器中如何获得表面(而不是顶点)法线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2523439/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com