当前位置: 首页 > 知识库问答 >
问题:

漫射照明伪像 (OpenGL 4)

哈朗
2023-03-14

在阅读了一些教程后,我正在尝试实现最简单的漫射照明,但惨遭失败。

我从 Wavefront obj 文件加载 3d 网格,如果我不应用照明,它看起来很好。但是,当我应用照明时,动物看起来像一个棋盘,立方体更加混乱:

动物比较(与法线)

立方体比较(带法线)

下面是顶点着色器:

#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统一,暂时不使用)。

然后,片段着色器:

#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);
}

在这种情况下,顶点将变为顶点1P1N1UV

更新:

实现了正常可视化(重新上传屏幕截图,滚动到顶部)。令我困扰的是,我可以通过网格看到法线,就像尽管颜色不透明,但它是透明的。这是一个深度测试问题吗?

共有1个答案

武骁
2023-03-14

经过2天的挣扎,我发现了问题所在。我没有在NSOpenGLView上启用深度缓冲区。这是一行代码。如果有人偶然发现这一点,他可以在这里查看OpenGL GL_DEPTH_TEST无法解决问题。

 类似资料:
  • 基于图像的光照(Image based lighting, IBL)是一类光照技术的集合。其光源不是如前一节教程中描述的可分解的直接光源,而是将周围环境整体视为一个大光源。IBL 通常使用(取自现实世界或从3D场景生成的)环境立方体贴图 (Cubemap) ,我们可以将立方体贴图的每个像素视为光源,在渲染方程中直接使用它。这种方式可以有效地捕捉环境的全局光照和氛围,使物体更好地融入其环境。 由于基

  • 我正在尝试实现Phong照明。在一些教程中,镜面反射照明添加到环境光和漫反射照明中,然后总照明乘以纹理颜色。我还看到了一个教程,其中在添加环境光和漫反射光后,分别添加了镜面反射照明和纹理颜色。 这是一个片段着色器,既有选项,也有屏幕截图。 > 选项1。镜面反射将添加到环境光和漫反射 选择2。镜面反射是单独添加的。 在这些截图中,shineDump值为32.0f,镜面强度为0.5f。 哪一个看起来正

  • 我是修改Minecraft的初学者,希望修改最新版本的Minecraft锻造版(v1.17.1)。我知道如何为1.16.5设置gradle项目,并且在很大程度上可以为1.17.1设置gradle项目。问题是我不知道Forge 1.17.1的模糊映射是什么。我需要知道,以便为构建的第34行设置正确的映射。格拉德尔:

  • 我正在为体素游戏开发一个3通道延迟照明系统,但是我在像素化照明和环境遮挡方面有问题。 第一阶段将屏幕上每个像素的颜色、位置和法线渲染成单独的纹理。这部分工作正常: 第二个着色器为屏幕上的每个像素计算环境光遮挡值,并将其渲染为纹理。此部分工作不正常,已像素化: 原始遮挡数据: 第三个着色器使用颜色、位置、法线和遮挡纹理将游戏场景渲染到屏幕上。这一阶段的照明也是像素化的: SSAO(第二遍)片段着色器

  • 漫反射颜色和透明度 一个具有默认参数并且未分配值和纹理的标准着色器材质。参数『漫反射颜色』被突出显示。 漫反射参数控制表面的基准颜色(底色)。 漫反射颜色从黑到白。 译注:Brushed Metal 拉丝金属,Brick 砖块,Rock 岩石,Satin 绸缎,Ceramic 陶瓷。 有些情况下,为漫反射指定一个颜色值是有用的,但是,更常见的情况是,为漫反射参数指定一张纹理贴图。漫反射应该表示物体

  • 本章介绍如何使用JOGL将光照效果应用于对象。 要设置光照,最初使用glEnable()方法启用光照。 然后使用GLLightingFunc接口的GLLightingFunc glLightfv(int light, int pname, float[] params, int params_offset)方法为GLLightingFunc 。 该方法有四个参数。 下表描述了gllightfv()

  • 问题内容: 我目前正在为一个大学课程从事小组项目,但是遇到了一些绊脚石。我们已决定要实现的程序是一个具有中央服务器的对等聊天客户端,该服务器用于存储和共享用户名等。我已被分配去做GUI。 一位朋友开玩笑地建议我加入“火红的背景!” 因此,我决定这样做,但是要有一个用户选择的背景图像。照原样,只有一点点背景图像可见,所有组件都位于其上方,因此我决定尝试实现半透明。 这是我的问题所在: 从输入框向聊天

  • 环境光和漫反射光的主要不同是,漫反射光的计算需要依靠光线方向而环境光完全忽略了它!当只有环境光时整个场景被均等照亮,漫反射光会使物体面对光的部分比背对光的部分更加明亮。 此外漫反射光还增加了一些新的计算,光线的入射角决定了表面的亮度。通过下面的图片来演示这个概念: 让我们假设两条光线的强度是一样的,而唯一不一样的是它们入射的方向。在漫反射光照模型中,左边物体的表面比右边亮,因为左边的表面相比右边的