2D lighting with shaders - light radius affected by window size
我有一个着色器,用于向其他2D场景添加光照(光照略高于2D平面)。在片段着色器中,我遍历每盏灯以通过将正交矩阵应用于灯的位置来计算方向和距离。
问题在于,灯光的"半径"受窗口尺寸和纵横比的影响。我认为使用正交矩阵平移坐标将确保屏幕大小无关紧要,但是宽的窗口会产生椭圆形的光,较小的窗口会产生比较大的窗口小的椭圆形。我应该使用其他某种矩阵吗?
此处有完整的着色器(更改窗口大小以查看不想要的效果):http://glsl.heroku.com/e#14464.0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | uniform vec2 resolution; void main(void) { //orthographic matrix mat4 ortho_matrix = mat4( 2.0/resolution.x, 0, 0, 0, 0, 2.0/-resolution.y, 0, 0, 0, 0, -1, 0, -1, 1, 0, 1 ); //surface normal of the 2D plane (looking straight down) vec3 surface_normal = vec3(0.0, 0.0, 1.0); //screen position of the light vec2 light_screen_pos = vec2(650, 150); //translate light's position to normalized coordinates //the z value makes sure it is slightly above the 2D plane vec4 light_ortho_pos = ortho_matrix * vec4(light_screen_pos, -0.03, 1.0); //calculate the light for this fragment vec3 light_direction = light_ortho_pos.xyz - vec3(gl_FragCoord.x / resolution.x, gl_FragCoord.y / resolution.y, 0); float dist = length(light_direction); light_direction = normalize(light_direction); vec3 light = clamp(dot(surface_normal, light_direction), 0.0, 1.0) * vec3(0.5, 0.5, 0.5); vec3 cel_light = step(0.15, (light.r + light.g + light.b) / 3.0) * light; gl_FragColor = vec4(pow(light + cel_light, vec3(0.4545)), 1.0); } |
注意:我知道对每个光源,每个像素进行此计算不是最佳方法-我应该以另一种统一的方式传递光源的位置。
需要根据屏幕分辨率缩放光的方向。我最终添加了以下代码以使其正常工作,并具有5??00左右的任意亮度:
1 | light_direction *= vec3(resolution.x / brightness, resolution.y / brightness, 1.0); |