我的 Phong 着色算法遇到了一些问题。似乎法线关闭了,我总是得到一个平坦的阴影表面。
我正在实现延迟渲染,所以在我的几何传递中,我将顶点的位置和法线存储在纹理中。在光照过程中,我将法线输出为颜色以检查它们的“值”。
编辑 1我的 Gbuffer 使用两个纹理来存储位置和法线。两种纹理都使用 GL_RGB16F 格式。
编辑 5正如你在这张图片中看到的,
我没有得到优雅的颜色过渡。左边的头像是我的引擎的结果,右边你可以在 Blender 中看到相同的模型。在 Blender 中,法线(蓝色)看起来是正确的(没有重复等),但在我的引擎中,它们的行为就像一个面法线(每 4 个显示在同一方向上)。我正在使用 Assimp 加载模型,并
aiProcess_GenSmoothNormals
在导入它们时包含标志。
几何传递顶点着色器:
#version 440 core
layout (location = 0) in vec4 positionOS;
layout (location = 1) in vec3 normalOS;
layout (location = 2) in vec2 uv;
out VertexData
{
vec3 PositionVS;
vec3 NormalVS;
vec2 UV;
} vs_out;
uniform mat3 normalViewMatrix;
uniform mat4 modelViewMatrix;
struct Camera
{
mat4 viewMatrix;
mat4 projMatrix;
};
layout(std140, binding = 0) uniform CameraBlock
{
Camera cam;
};
void main()
{
vec4 positionVS = modelViewMatrix * positionOS;
vs_out.PositionVS = positionVS.xyz;
vs_out.NormalVS = normalViewMatrix * normalOS;
vs_out.UV = uv;
gl_Position = cam.projMatrix * positionVS;
}
几何通道片段着色器:
#version 440 core
layout (location = 0) out vec3 PositionVS;
layout (location = 1) out vec3 NormalVS;
in VertexData
{
vec3 PositionVS;
vec3 NormalVS;
vec2 UV;
} vs_in;
void main()
{
PositionVS = vs_in.PositionVS;
NormalVS = normalize(vs_in.NormalVS);
}
编辑 4从 Assimp (aiMesh) 读取顶点值
void MeshLoader::prepareMesh(const aiMesh & mesh)
{
{ // vertices
for (int i = 0; i < mesh.mNumVertices; i++) {
if (mesh.HasPositions()) {
glm::vec3 position = glm::vec3(mesh.mVertices[i].x, mesh.mVertices[i].y, mesh.mVertices[i].z);
positions.emplace_back(position.x, position.y, position.z, 1);
}
if (mesh.HasNormals()) {
normals.emplace_back(mesh.mNormals[i].x, mesh.mNormals[i].y, mesh.mNormals[i].z);
}
if (mesh.HasTangentsAndBitangents()) {
tangents.emplace_back(mesh.mTangents[i].x, mesh.mTangents[i].y, mesh.mTangents[i].z);
bitangents.emplace_back(mesh.mBitangents[i].x, mesh.mBitangents[i].y, mesh.mBitangents[i].z);
}
if (mesh.HasTextureCoords(0)) {
uvs.emplace_back(mesh.mTextureCoords[0][i].x, mesh.mTextureCoords[0][i].y);
}
}
}
{ // polygons
numFaces = mesh.mNumFaces;
for (int i = 0; i < numFaces; i++) {
indices.push_back(mesh.mFaces[i].mIndices[0]);
indices.push_back(mesh.mFaces[i].mIndices[1]);
indices.push_back(mesh.mFaces[i].mIndices[2]);
}
}
}
我想找到解决这个烂摊子的办法。我知道法线是问题,但我不知道为什么。
编辑 2从球体的外观来看,这似乎是一个插值问题,因此上面的着色器代码。如果着色器是正确的,那么可能是导入器类导致了这个问题?
编辑 3我还实现了前向渲染版本并将法线显示为颜色,但我得到与延迟版本相同的结果。