opengl - 为什么此Phong着色器起作用?

标签 opengl glsl shader

我最近在GLSL中编写了Phong着色器,作为学校作业的一部分。我从教程开始,然后玩弄代码,直到我开始工作。据我所知,它工作得很好,但是我写的特别是一行,我不明白为什么可以使发挥作用。

顶点着色器:

#version 330

layout (location = 0) in vec3 Position;    // Vertex position
layout (location = 1) in vec3 Normal;      // Vertex normal

out vec3 Norm;
out vec3 Pos;
out vec3 LightDir;

uniform mat3 NormalMatrix;      // ModelView matrix without the translation component, and inverted
uniform mat4 MVP;               // ModelViewProjection Matrix
uniform mat4 ModelView;         // ModelView matrix
uniform vec3 light_pos;         // Position of the light

void main()
{
    Norm = normalize(NormalMatrix * Normal);
    Pos = Position;
    LightDir = NormalMatrix * (light_pos - Position);

    gl_Position = MVP * vec4(Position, 1.0);
}

片段着色器:
#version 330

in vec3 Norm;
in vec3 Pos;
in vec3 LightDir;

layout (location = 0) out vec4 FragColor;

uniform mat3 NormalMatrix;
uniform mat4 ModelView;

void main()
{
    vec3 normalDirCameraCoords = normalize(Norm);
    vec3 vertexPosLocalCoords = normalize(Pos);
    vec3 lightDirCameraCoords = normalize(LightDir);

    float dist = max(length(LightDir), 1.0);

    float intensity = max(dot(normalDirCameraCoords, lightDirCameraCoords), 0.0) / pow(dist, 1.001);

    vec3 h = normalize(lightDirCameraCoords - vertexPosLocalCoords);
    float intSpec = max(dot(h, normalDirCameraCoords), 0.0);
    vec4 spec = vec4(0.9, 0.9, 0.9, 1.0) * (pow(intSpec, 100) / pow(dist, 1.2));

    FragColor = max((intensity * vec4(0.7, 0.7, 0.7, 1.0)) + spec, vec4(0.07, 0.07, 0.07, 1.0));
}

因此,我正在执行一种方法,其中您计算光矢量和相机矢量之间的半矢量,然后用法线将其点起来。很好但是,我做的两件事很奇怪。
  • 通常,一切都在眼坐标中完成。但是,位置(我从顶点着色器传递到片段着色器)位于局部坐标中。
  • 这是令我困惑的部分。在vec3 h = normalize(lightDirCameraCoords - vertexPosLocalCoords);行上,我将相机坐标中的光矢量与本地坐标中的顶点位置相减。这似乎是完全错误的。

  • 简而言之,我了解了此代码应该做什么以及phong着色的半向量方法是如何工作的。

    但是为什么此代码有效?

    编辑:我们提供的入门代码是开源的,因此您可以download the completed project并直接查看。该项目适用于Windows上的VS 2012(您需要设置GLEW,GLM和freeGLUT),并且应该在GCC上工作且无需更改代码(可能对Makefile库路径进行了一两次更改)。

    请注意,在源文件中,“light_pos”称为“gem_pos”,因为我们的光源是您随WSADXC一起移动的小 gem 。按M键可让Phong带有多个指示灯。

    最佳答案

    起作用的原因是偶然的,但是有趣的是为什么它仍然起作用。

    Phong着色是中的三种技术

    使用phong阴影时,我们有三个术语:“镜面反射”,“漫反射”和“环境”;这三个术语代表在phong着色中使用的三种技术。

    这些术语都不严格要求向量空间。只要您保持一致,就可以在世界,本地或摄影机空间中使用phong着色。眼部空间通常用于照明,因为它更易于使用且转换也很简单。

    但是,如果您是原籍怎么办?现在您乘以零;很容易看出,原点的任何向量空间之间都没有差异。碰巧的是,从根本上讲,您位于哪个向量空间都无关紧要;会的。

    vec3 h = normalize(lightDirCameraCoords - vertexPosLocalCoords);
    

    请注意,它基本上是减去0。这是唯一一次使用本地方法,并且在可能造成最小损害的地方使用它。由于对象位于原点,因此其所有顶点也应位于原点或非常接近原点。在原点,近似值是精确的;所有向量空间都收敛。非常接近原点,非常接近精确;即使我们使用精确实数,也会有很小的差异,但是我们不使用精确实数,而是使用浮点数,这使问题更加复杂。

    基本上,您很幸运;如果对象不是原点,这将不起作用。尝试移动它看看!

    另外,您没有使用Phong shading;您正在使用Blinn-Phong shading(这是用半个向量替换reflect()的名称,仅供引用)。

    关于opengl - 为什么此Phong着色器起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22411998/

    相关文章:

    opengl - 使用 OpenGL 从 spritesheet 渲染 sprite?

    c - linux 和 windows 速度不匹配

    c++ - gl_FragCoord 的范围是多少

    three.js - 从three.js r.58 中的置换贴图计算法线?

    opengl-es - 在不同的程序中使用相同的顶点着色器时,统一位置是否保持不变

    c++ - 交叉编译时GL_GENERATE_MIPMAP不存在

    c++ - OpenGL 渲染限制在屏幕的左下四分之一

    c++ - 如何在 C++ 编译器不智能的情况下实现 GLSL vec* 构造语法?

    android - 函数在 GLSL 中有性能损失吗?

    opengl - GLSL 在程序之间共享制服 #130