Elm*_*lmi 1 opengl lighting glsl light opengl-3
目前,我的OpenGL场景不使用任何灯光,它仅使用具有固定颜色的线框-对我来说效果很好。
现在,我想添加第二种模式,其中线框显示为(半)实体模型。为此,我需要一些照明。照明应该非常容易,只需一些具有固定颜色和方向的全局定向光即可。
有两个问题:据我了解,我可以完全在片段着色器中执行此操作-这正确吗?
并且:我当前的片段着色器非常简单:
#version 130
uniform vec4 inputColor;
out vec4 FragColor;
void main()
{
FragColor=inputColor;
}
Run Code Online (Sandbox Code Playgroud)
在这里必须添加什么以使全局几何光源(而不是其他一些点光源)为我的几何图形照明?
要计算漫射光或什至镜面高光,您必须知道曲面和片段的法线向量。漫射光的辐射度取决于入射光的方向-请参阅此伪造的光如何在气扭中起作用?。镜面高光还取决于视角的方向。
如果没有法线向量,则可以通过片段着色器中视图空间位置的偏导数近似计算表面法线向量。偏导数可以通过函数dFdx和dFdy获得。
使用此法向矢量,您可以计算出质量非常低的漫射光。表面看起来是平坦的,并且光线似乎是通过面法线向量而不是平滑的顶点法线向量计算的。但是可以通过稍后使用“真实”法向矢量来实现基本的光照模型并对其进行改进。
参见示例。在这种情况下,假设光源位于视角,因为相对于光(L)的视角空间方向为vec3(0.0, 0.0, 1.0):
顶点着色器
out vec4 v_clip_pos;
main()
{
.....
gl_Positon = .....;
v_clip_pos = gl_Positon;
}
Run Code Online (Sandbox Code Playgroud)
片段着色器
#version 130
in vec4 v_clip_pos; // same as gl_Position
out vec4 FragColor;
uniform vec4 inputColor;
void main()
{
vec3 ndc_pos = v_clip_pos.xyz / v_clip_pos.w;
vec3 dx = dFdx( ndc_pos );
vec3 dy = dFdy( ndc_pos );
vec3 N = normalize(cross(dx, dy));
N *= sign(N.z);
vec3 L = vec3(0.0, 0.0, 1.0); // direction to the light source
float NdotL = dot(N, L);
vec3 diffuse_color = inputColor.rgb * NdotL;
FragColor = vec4(diffuse_color.rgb, 1.0);
}
Run Code Online (Sandbox Code Playgroud)
请参见演示灯光模型的示例。当然,该示例是在WebGL中而不是在OpenGL中实现的,但是片段着色器非常相似:
out vec4 v_clip_pos;
main()
{
.....
gl_Positon = .....;
v_clip_pos = gl_Positon;
}
Run Code Online (Sandbox Code Playgroud)
#version 130
in vec4 v_clip_pos; // same as gl_Position
out vec4 FragColor;
uniform vec4 inputColor;
void main()
{
vec3 ndc_pos = v_clip_pos.xyz / v_clip_pos.w;
vec3 dx = dFdx( ndc_pos );
vec3 dy = dFdy( ndc_pos );
vec3 N = normalize(cross(dx, dy));
N *= sign(N.z);
vec3 L = vec3(0.0, 0.0, 1.0); // direction to the light source
float NdotL = dot(N, L);
vec3 diffuse_color = inputColor.rgb * NdotL;
FragColor = vec4(diffuse_color.rgb, 1.0);
}
Run Code Online (Sandbox Code Playgroud)