Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么赢了';我的法线在顶点之间插值,从而创建一个平面着色效果?_C++_Opengl_Glsl_Glm Math_Phong - Fatal编程技术网

C++ 为什么赢了';我的法线在顶点之间插值,从而创建一个平面着色效果?

C++ 为什么赢了';我的法线在顶点之间插值,从而创建一个平面着色效果?,c++,opengl,glsl,glm-math,phong,C++,Opengl,Glsl,Glm Math,Phong,我的Phong着色算法有点问题。看起来法线是关闭的,我总是得到一个平坦的着色表面 我正在实现延迟渲染,因此在几何体过程中,我将顶点的位置和法线存储在纹理中。在照明过程中,我将法线输出为颜色,以检查其“值”。 编辑1我的Gbuffer使用两种纹理来存储位置和法线。两种纹理都使用GL_RGB16F格式 编辑5,如图所示 我没有优雅的颜色过渡。左边的头部是我的引擎的结果,在右边你可以在Blender中看到相同的模型。在Blender中,法线(蓝色)看起来是正确的(没有重复,等等),但在我的引擎中,它们

我的Phong着色算法有点问题。看起来法线是关闭的,我总是得到一个平坦的着色表面

我正在实现延迟渲染,因此在几何体过程中,我将顶点的位置和法线存储在纹理中。在照明过程中,我将法线输出为颜色,以检查其“值”。
编辑1我的Gbuffer使用两种纹理来存储位置和法线。两种纹理都使用GL_RGB16F格式

编辑5,如图所示 我没有优雅的颜色过渡。左边的头部是我的引擎的结果,在右边你可以在Blender中看到相同的模型。在Blender中,法线(蓝色)看起来是正确的(没有重复,等等),但在我的引擎中,它们的行为类似于面法线(每4个显示在同一方向)。 我使用Assimp加载模型,并在导入模型时包含
aiProcess\u GenSmoothNormals
标志

几何体通过顶点着色器:

#版本440核心
vec4位置的布局(位置=0);
vec3法线中的布局(位置=1);
vec2 uv中的布局(位置=2);
输出顶点数据
{
vec3定位vs;
vec3-NormalVS;
vec2紫外线;
}vs_out;
一致mat3矩阵;
统一mat4模型视图矩阵;
结构摄像机
{
mat4视图矩阵;
mat4程序矩阵;
};
布局(std140,绑定=0)统一摄像块
{
摄像机;
};
void main()
{
vec4位置vs=模型视图矩阵*位置;
vs_out.PositionVS=位置vs.xyz;
vs_out.NormalVS=normalViewMatrix*normalOS;
vs_out.UV=紫外线;
gl_位置=cam.projMatrix*位置vs;
}
几何体过程片段着色器:

#版本440核心
布局(位置=0)输出vec3位置vs;
布局(位置=1)输出vec3 NormalVS;
在顶点数据中
{
vec3定位vs;
vec3-NormalVS;
vec2紫外线;
}vs_in;
void main()
{
位置vs=vs_in.PositionVS;
NormalVS=标准化(vs_in.NormalVS);
}
编辑4从Assimp(aiMesh)读取顶点值

void-MeshLoader::prepareMesh(const-aiMesh&mesh)
{
{//顶点
对于(int i=0;i
我想找到解决这一混乱局面的办法。我知道法线是个问题,但我不知道为什么。
编辑2根据球体的外观,它似乎是一个插值问题,因此上面的着色器代码。如果着色器正确,则可能是导入器类导致了此问题?

编辑3我还实现了正向渲染版本,并将法线显示为颜色,但我得到的结果与延迟版本相同。

由于您处理的是延迟渲染,我的建议是确保屏幕空间法线纹理确实正确保存法线值。首先,你为普通纹理分配了多少空间?GL_RGBA16纹理应该可以完成这项工作

您必须注意的第二件事是,在glsl中,当写入纹理缓冲区时,负颜色值将被剪切,因为纹理缓冲区是无符号的。尝试使用某种转换器方法将颜色数据转换为矢量数据,反之亦然。方法

vec4 toCoord(vec4 color) {
    return vec4(2.0 * color.xyz - vec3(1, 1, 1), color.w);
}

vec4 toColor(vec4 coord) {
    return vec4(0.5 * coord.xyz + vec3(0.5, 0.5, 0.5), coord.w);
}
这应该很好。 如果你还没有做这两件事中的一件,试试看:)

如果它不起作用,则在片段着色器中写入和读取纹理缓冲区中的法线数据的方式中,一些内部消息将非常有用:)

我使用Assimp加载模型,并在导入模型时包含
aiProcess\u GenSmoothNormals
标志

从:

如果在计算该标志时法线已经存在,则忽略该标记。模型导入器尝试从源文件加载它们,因此它们通常已经存在

因此,如果导出具有平坦法线的模型,此标志将不起任何作用。所以你有两个选择:

  • 导出具有正确平滑法线的模型。(更好的选择,因为这样可以完全控制法线,保留所需的硬边等。必要时还可以减少计算量。)
  • 强制assimp重新计算法线。查看
    aiProcess\u RemoveComponent
    标志: 如果要强制Assimp重新计算法线或切线,此步骤也很有用。如果相应的步骤已经存在(从源资产加载),则不会重新计算它们。通过使用此步骤,您可以确保它们不在那里


  • 导出或加载模型时可能出现问题。根据提供的代码,我们两者都不能帮上忙。@PeterWishart的可能副本我已经读过那篇文章,并试图用blender和analyz解决这个问题