我在阅读一些教程后尝试实现最简单的漫反射光照,但却失败了。
我从Wavefront obj文件加载3d网格,如果我不应用光照,它看起来很好。但是,当我使用照明时,动物看起来像棋盘,立方体更加混乱:
animal comparison (with normals)
cube comparison (with normals)
这是顶点着色器:
#version 400
layout (location = 0) in vec4 a_position;
layout (location = 1) in vec3 a_texCoords;
layout (location = 2) in vec3 a_normal;
uniform mat4 u_viewProjection;
uniform mat4 u_model;
out vec3 v_fragPos;
out vec3 v_fragNormal;
void main() {
v_fragPos = a_position.xyz;
v_fragNormal = a_normal;
gl_Position = u_viewProjection * a_position;
}
我将片段位置和法线按原样传递给片段着色器,因为我没有应用任何模型变换,我只是假设模型在从文件加载后已经具有世界坐标(忘记u_model制服,它&& #39;现在不用了。)
然后,片段着色器:
#version 400
uniform vec3 u_lightPos;
uniform vec3 u_lightColor;
uniform vec3 u_diffuseColor;
uniform vec3 u_specularColor;
uniform vec3 u_ambientColor;
in vec3 v_fragPos;
in vec3 v_fragNormal;
out vec4 o_fragColor;
void main() {
vec3 lightDir = u_lightPos - v_fragPos;
float cosTheta = max(dot(normalize(v_fragNormal), normalize(lightDir)), 0.0);
vec3 diffuseContribution = cosTheta * u_lightColor;
o_fragColor = vec4(u_diffuseColor * diffuseContribution, 1.0);
}
没有使用模型或普通矩阵,因为现在没有对模型应用旋转(或缩放)。
我想到了不正常的法线,但至少一个简单的立方体应该有正确的,对吧?
另外,也许我应该提一下,我在MacOS下使用NSOpenGLView。
任何帮助将不胜感激。 谢谢!
更新
添加VBO设置。
这是单个顶点的样子:
struct Vertex1P1N1UV {
glm::vec4 mPosition;
glm::vec3 mTextureCoords;
glm::vec3 mNormal;
Vertex1P1N1UV();
Vertex1P1N1UV(glm::vec4 position, glm::vec3 texcoords, glm::vec3 normal);
};
我像这样初始化我的VAO
auto* VAO = new GLVertexArray<Vertex1P1N1UV>();
VAO->initialize(subMesh.vertices(), GLVertexArrayLayoutDescription({
static_cast<int>(glm::vec4::length() * sizeof(GLfloat)),
static_cast<int>(glm::vec3::length() * sizeof(GLfloat)),
static_cast<int>(glm::vec3::length() * sizeof(GLfloat)) }));
VAO初始化方法
void initialize(const std::vector<Vertex>& vertices, const GLVertexArrayLayoutDescription& layoutDescription) {
bind();
mVertexBuffer.initialize(vertices);
GLuint offset = 0;
for (GLuint location = 0; location < layoutDescription.getAttributeSizes().size(); location++) {
glEnableVertexAttribArray(location);
GLsizei attributeSize = layoutDescription.getAttributeSizes()[location];
glVertexAttribPointer(location, attributeSize / sizeof(GLfloat), GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void *>(offset));
offset += attributeSize;
}
}
缓冲区初始化方法
void initialize(const std::vector<Vertex>& data) override {
bind();
glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(Vertex), data.data(), GL_STATIC_DRAW);
}
在这种情况下,顶点将变为Vertex1P1N1UV
更新
实现了正常的可视化(重新上传的屏幕截图,滚动到顶部)。 困扰我的是我可以通过网格看到法线,尽管它是透明的,尽管颜色不透明。这是深度测试问题吗?
答案 0 :(得分:0)