OpenGL着色器,类似于MeshLab的可视化器来着色每个面

问题描述 投票:2回答:2

我具有非常基础的OpenGL知识,但是我正在尝试复制MeshLab的可视化器具有的阴影效果。

如果在MeshLab中加载网格,您将意识到,如果一个面向相机的面完全照亮了,并且在旋转模型时,光照会随着面向相机的面的变化而改变。我在MeshLab中加载了一个带有12个面的简单单位立方体,并捕获了以下屏幕截图,以使我的观点更加清楚:

  • 模型已加载(注意面部如何完全变灰):Loaded up

  • 模型略微旋转(请注意,脸部有些暗):Rotated

  • 更多旋转(注意现在所有面孔都变黑了):Rotated

从我的头顶上,我认为它的工作方式是通过某种方式在着色器中为每个面分配颜色。如果脸部法线与相机之间的角度为零,则脸部将完全照亮(根据脸部的颜色),否则,其照亮与法向矢量和相机矢量之间的点积成比例。

我已经有了用着色器/ VBO绘制网格的代码。我什至可以分配每个顶点的颜色。但是,我不知道如何实现类似的效果。据我所知,片段着色器可以在顶点上工作。快速搜索发现了this之类的问题。但是当答案涉及重复顶点时,我感到困惑。

如果有任何不同,在我的应用程序中,我加载*.ply文件,其中包含顶点位置,三角形索引和每个顶点的颜色。

[C0之后的结果]

我创建了重复的顶点数组,并使用以下着色器获得所需的照明效果。从发布的屏幕截图中可以看出,相似之处是不可思议的:)

顶点着色器:

the answer by @DietrichEpp

片段着色器:

#version 330 core

uniform mat4 projection_matrix;
uniform mat4 model_matrix;
uniform mat4 view_matrix;

in vec3 in_position;    // The vertex position
in vec3 in_normal;      // The computed vertex normal
in vec4 in_color;       // The vertex color

out vec4 color;     // The vertex color (pass-through)

void main(void)
{
    gl_Position = projection_matrix * view_matrix * model_matrix * vec4(in_position, 1);

    // Compute the vertex's normal in camera space
    vec3 normal_cameraspace = normalize(( view_matrix * model_matrix * vec4(in_normal,0)).xyz); 
    // Vector from the vertex (in camera space) to the camera (which is at the origin)
    vec3 cameraVector = normalize(vec3(0, 0, 0) - (view_matrix * model_matrix * vec4(in_position, 1)).xyz);

    // Compute the angle between the two vectors
    float cosTheta = clamp( dot( normal_cameraspace, cameraVector ), 0,1 );

    // The coefficient will create a nice looking shining effect.
    // Also, we shouldn't modify the alpha channel value.
    color = vec4(0.3 * in_color.rgb + cosTheta * in_color.rgb, in_color.a);
}

使用单位立方体的不可思议的结果:

#version 330 core in vec4 color; out vec4 out_frag_color; void main(void) { out_frag_color = color; }

Result 1

opengl glsl shader
2个回答
3
投票

看起来该效果是具有按面法线的简单照明效果。有几种方法可以实现按面法线:

  • 您可以创建一个具有法线属性的VBO,然后为法线不相同的面复制顶点位置数据。例如,一个立方体将具有24个顶点而不是8个顶点,因为“重复项”将具有不同的法线。

  • 您可以使用几何着色器来计算每面法线。

  • 您可以在片段着色器中使用Result 2dFdx()来近似法线。

我推荐第一种方法,因为它很简单。您可以只在程序中提前计算法线,然后使用它们在顶点着色器中计算面部颜色。


0
投票

这是简单的平面阴影,您可以使用此GLSL代码段来评估每个面法线,而不是使用每个顶点法线:

dFdy()

然后使用vec3 x = dFdx(FragPos); vec3 y = dFdy(FragPos); vec3 normal = cross(x, y); vec3 norm = normalize(normal); 施加一些漫射照明:

norm
© www.soinside.com 2019 - 2024. All rights reserved.