可编程管线分析(草案)

时间:2021-01-31 04:05:23

基本流水线


可编程管线分析(草案)


上图是基本的渲染流水线。

[留坑待续]


ADS基本光照模型

ADS光照模型是最常用模型,它根据光照的性质将顶点或者像素在光照下的颜色分解为

  • 环境(Ambient)
  • 漫反射(Diffuse)
  • 高光(Specular)
  • 自发光(Emission)

几个分量的和。如下面诸图例所示表现形式和计算公式:

可编程管线分析(草案)

可编程管线分析(草案)

可编程管线分析(草案)

在公式中,Ambient和Diffuse叫做Lambert光照模型。对高光Specular成分来说,有Phong和Blinn-Phong两种计算方式,后者用一个H向量简化了计算。

以前的硬件设备通常使用顶点光照(VertexLit),即将光源和顶点位置、法线、材质,根据ADS模型计算得到颜色值存放在顶点上,然后在三角形光栅化阶段根据三个顶点的颜色,对三角形内部的像素颜色进行插值计算。顶点光照也叫做Gouraud Shading。

因为已经普及了shader,现代硬件设备则使用Phong Shading——不再用顶点和光源计算颜色,而是取像素的法线。要么在光栅化阶段对三个顶点的法线进行插值,要么访问一张法线贴图。然后在Pixel Shader中根据ADS模型用该法线处理光照,也就是逐像素光照,效果有很大提升。

另外,除了ADS 模型,还有各向异性光照模型,以及现在非常流行的PBR(Physically-Based Rendering)光照模型(PBR用BRDF公式来替换Diffuse和Specular分量模型)等等。


[留坑待续]


Shader效果文件

现在的shader编写一般采用单独的效果文件来进行。每一个效果被编写进一个单独的文件里,每一个文件有多个该效果的不同实现,每一个实现可能会通过一个到多个pass。比如DX的HLSL效果文件是这样的:

// effect.txt
technique T0
{
     // first and only pass for this technique
     pass P0
     {
          ...[specify pass device states, shaders, samplers, etc.]
     }
}

technique T1
{
     // first pass
     pass P0
     {
          ...[specify pass device states, shaders, samplers, etc.]
     } 
     // second pass
     pass P1
     {
          ...[specify pass device states, shaders, samplers, etc.]
     }
}

类似地,一个Unity3D的效果文件是这样的:


Shader "MyShader" {
    Properties {
        _MyTexture ("My Texture", 2D) = "white" { }
        // Place other properties like colors or vectors here as well
    }
    SubShader {
        // here goes your
        // - Surface Shader or
        // - Vertex and Fragment Shader or
        // - Fixed Function Shader

pass{...}

pass{...}

    }
    SubShader {

pass{...}

pass{...}

    }

    // Place a simpler "fallback" version of the SubShader above
    // that can run on older graphics cards here
}

每一次pass渲染该对象一次到当前缓冲区里面(比如一个RTT的FBO)。而pass之间会使用一些预先设定好的检测和逻辑计算合并相同位置的颜色,一般默认都是后面的颜色直接替换之前的颜色。

[留坑待续]

关于OpenGL的一些常识

OpenGL中的FBO是application-created framebuffer,而窗口系统默认生成并管理的叫做window-system-provided framebuffer,二者结构类似。一个FBO会提供多个attachment points,比如color1, depth, stencil等等挂接点。每点可挂接两种framebuffer-attachable image(texture和renderbuffer)中的一种。使用texture叫做“render to texture(RTT)”,用glFramebufferTexture2D()挂接;使用renderbuffer叫做“offscreen rendering”,用glFramebufferRenderbuffer() 挂接。另外,显卡一般允许FBO有多个color挂接点,若程序中通过glDrawBuffer()给FBO的多个color点进行挂接,则可以结合glsl实施MRT。

当一个OpenGL函数调用完毕,它并不会马上执行产生的命令。而是将它们存在CPU端的device command queue中。OGL driver可能会在多帧之后执行这些command,取决于GPU的工作效率和driver的当前配置。这种异步延迟对整体性能是有益的,因为实际上是对application隐藏了driver和GPU交互过程中的latency。

正因为OGL application thread和driver thread的异步处理,application对于一个VBO的修改(比如通过glBufferSubData()方法),可能因为driver正对该VBO的渲染而被driver阻塞,直到完成其渲染。这样的一个阻塞叫做implicit synchronization(隐式同步)。消除这种同步对OGL application深度优化很重要。


[留坑待续]