问题汇总

1.Light support for Editor
编辑器加入了灯光工具, 可以添加和修改灯光.

问题1. light object的用户互交.
point light可以把对应的volume (wireframe sphere/cone)画出来用于用户选中, 但是光源太多的时候, 球就有点凌乱了. 所以使用了HUD, 只要选中HUD就会选中灯光, 只有灯光被选中的时候才显示volume. 另外, 编辑器里面的很多"不可见"的逻辑对象都有这种需求, 虽然现在还没有. 另外, 可以直接拿deferred shading中的geometry复用, 来显示bounding volume helper, 对于方向光, 需要额外加一个箭头作为helper.

问题2: HUD的picking. 之前的物体picking, 是用3D方法, 拿screen sapce的x,y, 取任意的z(不同的z都投影到x,y), unproject到world space, 再拿world sapce的相机坐标, 构建一个ray (这个ray上的所有点投影到屏幕上都是x,y), 然后用3D空间算法拾取bounding box.
而HUD比较特殊, 如果复用之前的3D方法, 反而很麻烦. 需要根据screen rect反算bounding box, 而且world bounding并不能完全紧凑包围screen rect, 需要使用view space的bounding, 用view sapce ray计算.

考虑之后选择直接在screen space做picking, 这样做的结果是多加了一两个接口, 但是实现起来变得很轻松. 需要注意的是, screen space的z也需要保留, 用来排序出最靠前的对象.

问题3: HUD的icon, 直接使用的是编辑器的资源(64x64 png), 并没有离线压缩, 而是实时压缩为BC3 (DXT5). 另外这个icon需要背景, 用美术资源重复合成的话冗余太多, 同时又不想把贴图个数写死(必须是2?), 所以加了一个新的senmatic来获取texture的个数, 这样在shader里面就可以迭代采样了.

void BladeFSMain(
in float4 pos : POSITION,
in float2 uv : TEXCOORD0,
uniform float4 texutreCount : SAMPLER_COUNT,
uniform sampler2D hudDiffuse[MAX_DYNAMIC_TEXTURE_COUNT], out float4 outColor : COLOR0
)
{
outColor = float4(,,,);
for(int i = ; i < texutreCount.x; ++i)
{
float4 color = tex2D(hudDiffuse[i],uv.xy);
outColor = lerp(outColor, color, color.a);
}
}

2: View Distance v.s. View Depth 
(view distance v.s. view space Z)

View space Z 就是camera distance吗? 两者很多时候可以几乎视为等价, 但并不相同.

首先两者都是线性的, 不同的是, distance相同的点构成了一个球面, 而Z相同的点构成了一个与view dir垂直的plane.

由于view space Z由于是z值, 所以可以用于Z buffering(depth write/test), 即可以写入depth stencil; 而view distance不能用于depth test.

Normalized Linear Depth  Can Be Used As ZBuffer(Depth Testing) Geometry Points of  The Same Value
view Distance  NO sphere
view space Z YES plane

而之前的计划为了节省GBuffer, 是准备用INTZ写入深度, 并作为GBufer的depth来采样, 所以Blade使用的View space Z.

然而, deferred shading 里面:

pos = eye_pos + dir * "depth", 实际上这里的depth是viewDist, 即

pos = eye_pos + dir * viewDistance.

对于直接读取depthstencil来说, 拿到的是view Z而不是view Dist. 这个问题之前没有发现, 因为只实现了方向光, 没有用到position.

简单分析可以得出|viewDistance| = |ViewZ| / cos(θ) = |viewZ| / dot(viewDir, dir).

Construct position In View space:
right handed: viewDir = (0,0,-1) 
viewZ = tex2D(depthINTZ, uv).r; //normalized linear depth
viewPos = viewDir * (viewZ * farClipDist) / -viewDir.z ;

Construct position In World space:
viewZ = tex2D(depthINTZ, uv).r;
worldPos = worldEyePos + worldDir * (viewZ*farClipDist) / dot( worldLookatDir, worldDir);

这样就可以使用depthstencil作为Gbuffer的depth了. 既可以做depth test, 又能用来构建顶点位置坐标. 这样就不用把normal和depth压缩后挤在同一个buffer,

甚至在使用24位normal时, 还空出一个通道. 目前这个通道用来保存specular的power.

目前Blade的GBuffer如下:

Component Format Attachment Usage
Color A8R8G8B8 MRT color 0 Diffuse:rgb, SpecularLevel:a
Normal A8R8G8B8  MRT color 1 WorldNormal:rgb, Specular exponent:a
Depth INTZ  depthstencil normalized View space Z ZBuffer depth, converted to view space

Blade 一开始在pixel shader里将normalized view space z输出, 后来因为效率不高, 所以改成了vertex shader里输出常规的z, 然后在deffered shading里根据zbuffer解算view sapce z:

viewZ = convertDepthToViewSpace( tex2D(depthINTZ, uv).r );
worldPos = worldEyePos + worldDir * viewZ* / dot( worldLookatDir, worldDir);

关于convertDepthToViewSpace的计算:

前面已经记录了一个链接, 这里简单记录一下思路. 根据projection matrix
projectedZ = f(viewZ) (linear conversion to [0, zfar] )
projectedW = -viewZ (right handed)

在perspective divide (z/w) 以后:
NDCz = -f(viewZ)/viewZ    ranges [-1,1] (OGL) or [0,1] (D3D)

即NDCz = g(z) = a/z + b  (non-linear)

其中b = prjoectionMatrix33 = projectionMatrix[2][2], a = projectMatrix34 = projectionMatrix[3][2]

如果忽略viewport 的depth range, 可以认为最终depth buffer里面存储的是NDC space的z,

现在带入projection matrix的参数, 反向计算viewZ = g-1(zbuffer) = a / (zbuffer + b)

只要在CPU端计算好a,b, 在shader里面计算出view space Z,就可以了. 也可以使用invertedProjectionMatrix来直接求出viewSpaceZ.

目前只是尝试阶段, 还没有发现问题, 比如可能的精度不够等等的可能情况(之前使用linear depth就是为了精度问题), 后面再继续完善.

如果精度不够用的话, 可能就需要将view distance直接渲染到MRT里, 不采样depthstencil了.

需要注意的是, 并不是所有SM3.0都支持INTZ, 只有G80以上才支持. 为了简化管线, 在不支持INTZ的显卡上, 直接使用forward shading.

目前Blade支持的shader model有2_0, 2_x, 3_0. 在shader model为3.0的时候, 检测INTZ的支持, 如果不支持,则设置为2_x, 这个细节备忘下, 后面再完善.

其他问题

Light Volume: Calculate Screen UV in Vertex Shader:

只有方向光的quad比较特殊, 可以这么做, shpere和cone是不行的.尝试过了不对. 详细见这里: http://gamedev.stackexchange.com/questions/63870/computing-pixels-screen-position-in-a-vertex-shader-right-or-wrong

UV scale

由于默认backbuffer是desktop的大小, 所以depthstencil创建时也是这么大. 然而使用时是实际窗口的大小, 需要根据viewport的pixel size(或window size)和depthstencil的size, 计算UV的scale, 只采样部分区域, 同时apply half pixel offset, 这个UV的scale和offset在CPU计算并传入pxiel shader.

后面准备完善spot light, 并加上stencil mask.

引擎设计跟踪(九.14.3.1) deferred shading: Depthstencil as GBuffer depth的更多相关文章

  1. 引擎设计跟踪(九.14.3.2) Deferred shading的后续实现和优化

    最近完成了deferred shading和spot light的支持, 并作了一部分优化. 之前forward shading也只支持方向光, 现在也支持了点光源和探照光. 对于forward sh ...

  2. 引擎设计跟踪(九.14.3.3) Deferred shading的一些小细节

    1.ambient light 之前的shader里面, 方向光会加上ambient 的计算. 但是如果没有方向光, 就没有ambient. 这是把全局方向光改为点光源之后发现的, 因为透明物体的fo ...

  3. 引擎设计跟踪(九.14.2a) 导出插件问题修复和 Tangent Space 裂缝修复

    由于工作很忙, 近半年的业余时间没空搞了, 不过工作马上忙完了, 趁十一有时间修了一些小问题. 这次更新跟骨骼动画无关, 修复了一个之前的, 关于tangent space裂缝的问题: 引擎设计跟踪( ...

  4. 引擎设计跟踪(九.14.3) deferred shading 准备

    目前做的一些准备工作 1.depth prepass for forward shading. 做depth prepass的原因是为了完善渲染流程, 虽然架构上支持多个pass, 但实际上从来没有测 ...

  5. 引擎设计跟踪(九.14.2 final) Inverse Kinematics: CCD 在Blade中的实现

    因为工作忙, 好久没有记笔记了, 但是有时候发现还得翻以前的笔记去看, 所以还是尽量记下来备忘. 关于IK, 读了一些paper, 觉得之前翻译的那篇, welman的paper (http://gr ...

  6. 引擎设计跟踪(九.14.2i) Android GLES 3.0 完善

    最近把渲染设备对应的GLES的API填上了. 主要有IRenderDevice/IShader/ITexture/IGraphicsResourceManager/IIndexBuffer/IVert ...

  7. 引擎设计跟踪(九.14.2g) 将GNUMake集成到Visual Studio

    最近在做纹理压缩工具, 以及数据包的生成. shader编译已经在vs工程里面了, 使用custom build tool, build命令是调用BladeShaderComplier, 并且每个文件 ...

  8. 引擎设计跟踪(九.14.2f) 最近更新: OpenGL ES & tools

    之前骨骼动画的IK暂时放一放, 最近在搞GLES的实现. 之前除了GLES没有实现, Android的代码移植已经完毕: [原]跨平台编程注意事项(三): window 到 android 的 移植 ...

  9. 引擎设计跟踪(九.14.2d) [翻译] shader的跨平台方案之2014

    Origin: http://aras-p.info/blog/2014/03/28/cross-platform-shaders-in-2014/ 简译 translation: 作者在2012年写 ...

随机推荐

  1. java导出Excel定义导出模板

    在很多系统功能中都会有Excel导入导出功能,小编采用JXLS工具,简单.灵活. JXLS是基于 Jakarta POI API 的Excel报表生成工具,它采用标签的方式,类似于jsp页面的EL表达 ...

  2. Spring事务操作介绍

    Spring的特色之一,简单而强大的事务管理功能,包括编程式事务和声明式事务. 1. Spring中涉及到事务管理的API有100多个,核心的只有三个: TransactionDefinition.P ...

  3. 实训任务04 MapReduce编程入门

    实训任务04 MapReduce编程入门 1.实训1:画图mapReduce处理过程 使用有短句“A friend in need is a friend in deed”,画出使用MapReduce ...

  4. js初学

    1.学习一门编程语言需要记住知识点:          1.关键字.     2.标识符.     3.注释.     4.运算符.     5.常量和变量 .     6.语句.     7.函数 ...

  5. DevExpress v18.2新版亮点——Reporting篇(二)

    行业领先的.NET界面控件——DevExpress v18.2日前正式发布,本站将以连载的形式为大家介绍新版本新功能.本文将介绍了DevExpress Reporting v18.2 的新功能,新版3 ...

  6. JavaScript 获得客户端IP

    Below are all the free active IP lookup services I could find and the information they return. If yo ...

  7. list练习

    usernames = ['cwl','pn','gxn','hyp']passwords = ['123456','abc123','324234','23423']#pn#sdfsdf #需要校验 ...

  8. 使用RevoUninstaller Pro卸载

    使用RevoUninstaller Pro卸载opera浏览器,操作过的注册表 HKEY_CURRENT_USER\SOFTWARE\CLASSES\Local Settings\Mircrosoft ...

  9. swift4.0 数据转模型

    swift 4.0时代的到来,说明了swift已经趋于稳定了,已经完全可以入坑了. 下面就拿最简单的数据转模型来说说,实战一下. 接口使用:  http://116.211.167.106/api/l ...

  10. zabbix AGENTS 在WINDOWS的安装

    1.下载 https://assets.zabbix.com/downloads/3.4.0/zabbix_agents_3.4.0.win.zip 解压 zabbix_agents_3.4.0.wi ...