zoukankan      html  css  js  c++  java
  • 第57天shader基本结构、渲染队列、裁剪、深度写入

    GPU

    显卡的处理器

    CPU和GPU的区别

    CPU是针对串行的指令设计的,GPU针对大规模的并行计算设计的

    CPU的多核并行是针对指令的并行,GPU针对数据与计算的并行

    渲染管线

    渲染流水线

    简单理解:CPU从内存准备数据,传递到GPU,GPU通过一系列的计算最终得到一个二维的图像的过程就是渲染管线

    CPU准备数据

    顶点坐标(相对于模型本身的物体的坐标系的坐标,模型空间的坐标):模型的顶点

    法线信息(模型空间下的)

    切线信息(模型空间下的)

    纹理坐标(也叫UV坐标)

    顶点颜色

    主要分为三个阶段

    应用程序阶段(CPU)

    CPU和内存通信,从内存中取出模型上相关顶点坐标、法线、切线、纹理坐标等,将其组成一个图元发送给GPU

    几何阶段(GPU)

    变换坐标

    将CPU传递来的顶点坐标,转换到裁剪与屏幕空间

    四个坐标空间

    模型坐标空间(数据顶点坐标、法线、切线都是模型空间下的)

    世界坐标空间:绝对的

    观察坐标空间:相对于摄像机的,以摄像机为原点

    裁剪与屏幕坐标空间

    三次转换使用的是矩阵来进行转换的

    将变换后的坐标传递到光栅化阶段

    转换坐标的作用:

    CPU取出的顶点数据都是相对于模型本身的,也就是相对于模块空间的

    将顶点坐标从object space转换到world Space判断当前的顶点在世界中哪个位置

    将world space的顶点位置转换到eye space判断顶点相对于摄像机的位置

    将eye space的顶点坐标转换到clip and project space 裁剪到摄像机视锥体外部顶点,并且将视锥体内的顶点投影降维映射到屏幕坐标上

    顶点函数在几何阶段

    光栅化阶段(GPU)

    使用上一个阶段的数据,计算屏幕像素的颜色,渲染出二维的图像

    片元函数在光栅化阶段

    Shader

    着色器,用来实现图像渲染的可编辑程序

    在Unity中Shader通过Material作用到物体上的

    着色器语言

    HLSL

    针对于Direct3D

    High Level Shader Language

    GLSL

    针对于OpenGL

    OpenGL Shading Language

    Cg

    同时支持Direct3D与OpenGL

    NVIDIA公司出的

    C for Graphics

    图像编程接口

    Direct3D

    微软出的

    OpenGL

    多个公司组成的OpenGL架构评审委员会制定的

    Unity着色器分类

    固定函数着色器

    最简单的着色器

    使用Unity提供固有的函数来完成渲染

    Shader Lab命令来完成

    顶点/片元着色器

    效果最丰富的,但是复杂度最高的着色器

    Unity中使用Cg语言或HLSL语言完成

    组成

    顶点函数

    片元函数

    表面着色器

    Unity独有的

    对Cg进行了一层封装,比顶点/片元简单,但是灵活度没有顶点/片元高

    Shader的基本结构

    Shader名字

    Shader名字,支持层级结构

    Properties 属性

    属性类型

    Color:颜色

    float:常数

    Vector:四维向量

    Range:范围,最大值与最小值,还是一个数,只是规定的了最大值与最小值

    2D:普通纹理贴图

    Cube:立方体贴图, 应用在天空盒的

    SubShader

    包含渲染的计算过程

    可以有多个SubShader

    Pass

    在SubShader中的结构,可以有多个

    多个Pass情况下,所有的Pass都会执行,每执行一个Pass增加一个DrawCall

    顶点片元着色器或固定函数着色器写在Pass结构中

    FallBack(备用shader)

    指定备用Shader,当所有的SubShader失效时,执行FallBack指定的Shader

    固定函数着色器

    Lighting

    Lighting off : 关闭灯光影响

    Lighting on : 开启灯光影响

    Color

    显示颜色

    Color(r,g,b,a)

    Color[属性名]

    Material

    灯光影响的命令需要放在Material中

    Diffuse

    漫反射命令

    Diffuse[颜色属性] : 漫反射的颜色

    颜色的数学运算

    颜色的加法使颜色变亮

    (r1,g1,b1,a1) + (r2,g2,b2,a2) = (r1 + r2, g1 + g2, b1 + b2, a1 + a2)

    颜色的乘法使颜色变暗(颜色叠加指的是颜色相乘)

    (r1,g1,b1,a1) * (r2,g2,b2,a2) = (r1 * r2, g1 * g2, b1 * b2, a1 * a2)

    渲染队列(Render Queue)

    渲染队列在Shader中实际是一个数值

    渲染队列值决定对象物体的渲染顺序,渲染队列值越小的越先渲染,渲染队列值越大的越后渲染

    渲染队列只决定渲染的先后顺序,最终在屏幕上的显示不是完全由渲染队列决定,还与深度比较与深度写入相关

    语法

    Tags{"Queue"="渲染队列名称"}

    渲染队列名称

    Background

    天空盒:1000

    Geometry

    不透明的物体:2000

    AlphaTest

    有透明通道,使用AlphaTest命令:2450

    Transparent

    半透明物体,使用Blend命令进行混合:3000

    Overlay

    镜头特效:4000

    裁剪命令(Cull)

    关闭裁剪

    Cull Off:正面与反面都显示

    裁剪正面

    Cull Front:只显示反面,不显示正面

    裁剪反面

    Cull Back:只显示正面,不显示反面

    正面与反面

    法线的方向就是正面

    反之就是反面

    深度测试与深度写入

    深度

    简单理解为游戏物体距离摄像机的距离

    深度越大证明距离摄像机越远,天空盒深度可以认为无限大的

    深度缓冲区

    在图形设备的内存中,存在一块存储区存储的是每个像素的深度值。通过深度缓冲区进行深度测试,从而确定遮挡关系,保证渲染正确

    颜色缓冲区

    图形设备的内存中,存在一块存储区存储的是每个像素的颜色。最终像素显示的颜色就是颜色缓冲区的颜色

    深度测试

    当前游戏物体的深度与深度缓冲区的深度的比较过程叫做深度测试

    命令

    ZTest Less:小于比较

    ZTest Greater:大于比较

    ZTest LEqual:小于等于比较

    ZTest GEqual:大于等于比较

    ZTest Equal:是否等于

    ZTest NotEqual:不等于

    ZTest Always:将比较关闭,直接认为比较成功

    深度写入

    将当前物体的深度写入到深度缓冲区的过程就是深度写入

    命令

    ZWrite On:开启深度写入

    ZWrite Off:关闭深度写入

    总结

    深度测试成功,深度写入开启,颜色写入缓冲区,深度写入缓冲区

    深度测试成功,深度写入关闭,颜色写入缓冲区,深度不写入缓冲区

    深度测试失败,深度写入开启,颜色不写入缓冲区,深度不写入缓冲区

    深度测试失败,深度写入关闭,颜色不写入缓冲区,深度不写入缓冲区

    深度测试关闭,深度写入开启,颜色写入缓冲区,深度写入缓冲区

    实例1:渲染遮挡关系判断机制

     

    深度:天空盒(∞),YellowCube(a), GreenCube(b)

    中心像素点的判断: 天空盒, Yellow Cube,Green Cube

    渲染队列: 天空盒(1000), YellowCube(2000), GreenCube(2000)

    深度测试:天空盒(<),YellowCube(<),GreenCube(<)

    深度写入:都是开启

    开始比较过程

    颜色缓中区

    深度缓中区

     

     

    第一比较:深度测试渲染队列最小的,天空盒的深度与深刻缓冲区的深度进行小于比较

           此时深度缓冲区无深度,认为比较成功,将天空盒的颜色写入到颜色缓冲区中,将天空盒的深度写入到深度缓冲区中。

    颜色缓中区

    深度缓中区

    天空盒颜色

    第二比较:深度测试渲染队列比天空盒大的(Yellow 与 Green随机一个),Green的深度(b)与深度缓冲区的深度(∞)进行小于比较

             b < ∞ 比较成功, 将Green的颜色写入颜色缓冲区,将Green的深度写入深度缓冲区。

    颜色缓中区

    深度缓中区

    绿色

    b

    第三比较:深度测试Yellow(a)与深度缓冲区的深度(b)进行小于比较

             a < b 比较成功,将Yellow的颜色写入到颜色缓冲区,将Yellow的深度写入到深度写入到深度缓冲区。

    颜色缓中区

    深度缓中区

    黄色

    a

    判断到已经没有其他物体,深度测试全部完成,最终中心像素点显示的颜色就是颜色缓冲区的颜色,黄色

    第2种方式开始比较过程

    颜色缓中区

    深度缓中区

     

     

    第一比较:深度测试渲染队列最小的,天空盒的深度与深刻缓冲区的深度进行小于比较

           此时深度缓冲区无深度,认为比较成功,将天空盒的颜色写入到颜色缓冲区中,将天空盒的深度写入到深度缓冲区中。

    颜色缓中区

    深度缓中区

    天空盒颜色

    第二比较:深度测试渲染队列比天空盒大的(Yellow 与 Green随机一个),Yellow的深度(a)与深度缓冲区的深度(∞)进行小于比较

             a < ∞ 比较成功, 将Yellow的颜色写入颜色缓冲区,将Yellow的深度写入深度缓冲区。

    颜色缓中区

    深度缓中区

    黄色

    a

    第三比较:深度测试Green(b)与深度缓冲区的深度(a)进行小于比较

             a < b 比较失败,颜色不写颜色缓冲区,深度不写入深度缓冲区

    颜色缓中区

    深度缓中区

    黄色

    a

    判断到已经没有其他物体,深度测试全部完成,最终中心像素点显示的颜色就是颜色缓冲区的颜色,黄色

     实例2:复杂渲染遮挡关系

      


    渲染队列:天空盒(1000),Green(2500),Blue(3000),Red(3500) 

    深度:天空盒(∞),Green(G),Blue(B),Red(R)

    深度测试:天空盒(小于),Green(小于),Blue(大于),Red(大于)

    深度写入:天空盒(开启),Green(开启),Blue(关闭),Red(开启)

    开始比较过程

    比较顺序:天空盒 –> Green -> Blue -> Red

    颜色缓冲区

    深度缓冲区

     

     

    第一次比较:天空盒的深度(∞)与深度缓冲区的深度(无)进行比较

           比较成功,深度写入开启,颜色写入缓冲区,深度写入缓冲区

    颜色缓冲区

    深度缓冲区

    天空盒颜色

    第二次比较:Green的深度(G)与深度缓冲区的深度(∞)进行小于比较

           G < ∞:比较成功,深度写入开启,颜色写入缓冲区,深度写入缓冲区

    颜色缓冲区

    深度缓冲区

    绿色

    G

    第三次比较:Blue的深度(B)与深度缓冲区的深度(G)进行大于比较

           B > G:比较成功,深度写入关闭,颜色写入缓冲区,深度不写入缓冲区

    颜色缓冲区

    深度缓冲区

    蓝色

    G

    第四次比较:Rad的深度(R)与深度缓冲区的深度(G)进行大于比较

           R > G:比较失败,颜色不写入,深度不写入

    颜色缓冲区

    深度缓冲区

    蓝色

    G

  • 相关阅读:
    ORM框架
    优酷项目1
    新年第一天
    前端第十天
    前端第九天
    前端第八天
    前端第七天
    前端第六天
    前端第五天
    月亮与六便士
  • 原文地址:https://www.cnblogs.com/yifengs/p/14570764.html
Copyright © 2011-2022 走看看