问题汇总

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. numpy数组及处理:效率对比

    def Sum(n): #定义一个函数(注意:格式对齐,否则会出错) a=list(range(n)) b=list(range(0,50000*n,5)) c=[] for i in range(l ...

  2. Write CSV file for a dataset

    import numpy as np import cv2 as cv2 import os import csv dataste_path = 'datasets/pascal-parts/pasc ...

  3. apex透视自瞄无后子弹追踪飞天加速辅助

    apex透视自瞄无后子弹追踪飞天加速辅助apex透视自瞄无后子弹追踪飞天加速辅助apex透视自瞄无后子弹追踪飞天加速辅助apex透视自瞄无后子弹追踪飞天加速辅助apex透视自瞄无后子弹追踪飞天加速辅助 ...

  4. 60行python代码分析2018互联网大事件

    2018年是改革开放四十周年,也是互联网发展的重要一年.经历了区块链,人工智能潮的互联网行业逐渐迎来了冬天.这一年里有无数的事件发生着,正好学了python数据处理相关,那么就用python对18年的 ...

  5. eclipse 项目中嵌入jetty

    Jetty是一个提供HHTP服务器.HTTP客户端和javax.servlet容器的开源项目,Jetty 目前的是一个比较被看好的 Servlet 引擎,它的架构比较简单,也是一个可扩展性和非常灵活的 ...

  6. code about led_shake

    //write by:cyt //Project Name:Led on/off //Time:2017-2-10 #include<reg51.h> void delay(int c) ...

  7. Mybatis-基于配置文件的配置(——纪念这个即将被抛弃的孩子)

    虽然内心相信Mybatis基于配置文件的配置早已经在实战之中被注解所遗忘,但是我相信还是会有一小部分人还是需要这种技术去维护原有使用这种方式去搭建的项目. 废话不多说首先使用框架包是不能少的了.导入M ...

  8. echarts 自定义主题

    https://blog.csdn.net/flitrue/article/details/52841338 import $echarts from 'echarts' import  'echar ...

  9. idea【快捷键】

    ctrl+shift+a:全局搜索 IDEA 的操作和设置 shift+f6:重命名 ctrl+alt+m:提取方法 ctrl+alt+l:格式化代码 ctrl+alt+o:优化导入类和包 ctrl+ ...

  10. 【Java】关于项目启动大请求量高负载时如何确保db等资源不出错的问题

      如果一个项目启动时(单机), 瞬间来了1000个访问, 如何确保db等资源不会压垮呢? 现在想想我当时回答的并不好, 而现在看公司框架才发现其实有针对于这一块做过专门的优化的.下面就来分享下公司关 ...