博客
关于我
关于GLSL的gl_FragCoord、gl_FragDepth以及深度计算
阅读量:496 次
发布时间:2019-03-07

本文共 1535 字,大约阅读时间需要 5 分钟。

gl_FragCoord和gl_FragDepth分别是片元着色器的输入和输出变量。

gl_FragCoord是个vec4,四个分量分别对应x, y, z和1/w。其中,x和y是当前片元的窗口相对坐标,不过它们不是整数,小数部分恒为0.5。x - 0.5和y - 0.5分别位于[0, windowWidth - 1]和[0, windowHeight - 1]内。windowWidth和windowHeight都以像素为单位,亦即用glViewPort指定的宽高。w即为乘过了投影矩阵之后点坐标的w,用于perspective divide的那个值。gl_FragCoord.z / gl_FragCoord.w可以得到当前片元和camera之间的距离。参见。

gl_FragCoord.z是固定管线计算出的当前片元的深度。它已经考虑了多边形偏移,并经过了投影变换。它位于[0.0, 1.0]之间。如果用gl_FragColor = vec4(vec3(gl_FragCoord.z), 1.0)将其可视化,多半会看到一片白。这是由于变换的非线性,大多数点的深度都非常接近于1。用gl_FragColor = vec4(vec3(pow(gl_FragColor.z, exp)), 1.0)并将exp取为合适的值,就能看到从黑到白的深度变化了。距离观察者近的颜色深,接近0.0;距离观察者远的颜色浅,接近1.0;这说明一直以来的右手坐标系在投影变换后变成了左手坐标系。关于深度的变换和精确性参见。

根据GLSLangSpec.Full.1.30.08(p61),gl_FragCoord.z是固定功能计算所得的结果。如果片元着色器不写gl_FragDepth,那么这个值将用在后续处理中。提到(p104),即使将gl_FragCoord.z赋值给gl_FragDepth也不能保证产生和固定功能完全相同的值。但是,可以保证相对正确。加之片元着色器一旦写入gl_FragDepth,就必须保证在每个分支都有写入。因此,如果一个着色器需要在某些条件下自己计算深度,其它条件下的正确做法就是gl_FragDepth = gl_FragCoord.z。

在OpenGL的固定管线中,深度坐标是在视口变换期间变换到glDepthRange指定的范围之内(OpenGL编程指南-原书第五版,88页)。视口变换也就是光栅化(Rasterization),在进行到片元着色器的时候自然已经编码完毕了。

自行计算片元深度可以用下面的方法(参考):

 

[cpp]  

  1. // Vertex Shader  
  2. varying vec4 position;  
  3. void main(void)  
  4. {  
  5.     position = gl_ModelViewMatrix * gl_Vertex;  
  6.     gl_Position = ftransform();  
  7. }  
  8. // Fragment Shader  
  9. uniform float zFar;  
  10. uniform float zNear;  
  11. varying vec4 position;  
  12. void main()  
  13. {  
  14.     float zDiff = zFar - zNear;  
  15.     float interpolatedDepth = (position.w / position.z) * zFar * zNear / zDiff + 0.5 * (zFar + zNear) / zDiff + 0.5;  
  16.     gl_FragColor = vec4(vec3(pow(interpolatedDepth, 15.0)), 1.0);  
  17. }  

 

这样计算出的深度与gl_FragCoord.z基本一致。

转载地址:http://gsedz.baihongyu.com/

你可能感兴趣的文章
mysql批量修改字段名(列名)
查看>>
MySQL批量插入数据遇到错误1213的解决方法
查看>>
mysql技能梳理
查看>>
MySQL报Got an error reading communication packets错
查看>>
Mysql报错Can‘t create/write to file ‘/tmp/#sql_3a8_0.MYD‘ (Errcode: 28 - No space left on device)
查看>>
MySql报错Deadlock found when trying to get lock; try restarting transaction 的问题解决
查看>>
MySQL报错ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘
查看>>
Mysql报错Packet for query is too large问题解决
查看>>
mysql报错级别_更改MySQL日志错误级别记录非法登陆(Access denied)
查看>>
Mysql报错:too many connections
查看>>
MySQL报错:无法启动MySQL服务
查看>>
mysql授权用户,创建用户名密码,授权单个数据库,授权多个数据库
查看>>
mysql排序查询
查看>>
MySQL排序的艺术:你真的懂 Order By吗?
查看>>
MySQL排序的艺术:你真的懂 Order By吗?
查看>>
Mysql推荐书籍
查看>>
Mysql插入数据从指定选项中随机选择、插入时间从指定范围随机生成、Navicat使用存储过程模拟插入测试数据
查看>>
MYSQL搜索引擎
查看>>
mysql操作数据表的命令_MySQL数据表操作命令
查看>>
mysql操作日志记录查询_如何使用SpringBoot AOP 记录操作日志、异常日志?
查看>>