翻阅了很多资料,也做了不少笔记,决定还是对渲染进行一个总结,以巩固所学的东西。

《Real-Time Rendering, Third Edition》   (PDF的配图链接)将一个渲染流程分为三个阶段:

应用阶段(PApplication Stage)、几何阶段(Geometry Stage)、光栅化阶段(Rasterizer Stage)

我借用《Unity Shader入门精要》的网页贴图来说明

颜色表示了不同阶段的可配置性或可编程性:绿色表示该流水线阶段是完全可编程控制的,黄色表示该流水线阶段可以配置但不是可编程的,蓝色表示该流水线阶段是由GPU固定实现的,开发者没有任何控制权。实线表示该shader必须由开发者编程实现,虚线表示该Shader是可选的。

顶点着色器(Vertex Shader)、片元着色器(Fragment Shader)是我们编写 Shader最常用的二个。另外二个曲面细分着色器(Tessellation Shader)、几何着色器(Geometry Shader)都是可选着色器。

既然提到了着色器(Shader),那什么是Shader呢

A shader is a piece of code, that is executed on the GPU. The engine feeds it with 3d model vertices, textures and other information, and gets back from it pixel colours.
-- from What is a Shader?

翻译过来:Shader 就是运行在GPU上的一段代码,引擎提供给它3D的模型顶点、纹理和其它信息,并获取返回的像素颜色。

Draw Call又是什么呢

A draw call is a command to render one mesh. It is given by the CPU. It is received by the GPU. The command only points to a mesh which shall be rendered and doesn’t contain any material information since these are already defined via the render state. The mesh resides at this point in the memory of your graphic card (VRAM).

-- from renderhell-book1

有兴趣可以观看下面这个视频,很形象和生动。

视频地址:

https://data.simonschreibt.de/gat049/cpu_calls_gpu.webm

https://data.simonschreibt.de/gat049/commandbuffer_communication_chunk.webm

实际上,Draw Call就是一个命令,它的发起方是CPU,接收方是GPU。这个命令仅仅会指向一个需要被渲染的图元(primitives)列表,而不会再包含任何材质信息(这些信息已经在渲染状态中被定义了),此时网格是驻留在显存(Video Random Access Memory)中的。

当给定了一个Draw Call时,GPU就会根据渲染状态(例如材质、纹理、着色器等)和所有输入的顶点数据来进行计算,最终输出成屏幕上所显示的那些像素。

只看文字不免过于抽象,我之前在网上看到一张图,描述的挺不错。

而实际的工作比这个要复杂很多,包括:坐标转换、透视、裁剪等一系列操作。

所上图所示,需要历经:坐标转换(模型空间 –> 齐次裁剪空间),逐顶点光照,透视除法(归一化的设备坐标 —— Normalized Device Coordinates, NDC),裁剪,屏幕映射。

这里再多解释一下,何为齐次裁剪空间。齐次裁剪空间是一个中心点是坐标原点的立方体,xyz取值范围是[-1, 1]。使用一个4x4的齐次变换矩阵将点从摄像机坐标空间变换到齐次裁剪空间,将顶点的深度值z保存在顶点经过变换得到的齐次坐标的w分量中。最后,把顶点在齐次空间中的坐标通过将x,y,z分量除以w分量的方式,将齐次坐标转为NDC。

为什么需要使用NDC呢?为了适配屏幕的多分辨率问题。

归一化坐标中,两个轴其中一个轴的范围是由0至1(但不能两个都是0~1),而且能轻易缩放至不同分辨率下的像素单位。假设把y轴的范围设置为0.0 ~ 1.0,当使用4:3长宽比时,x轴的范围就是0.0至1.333(=4/3),而16:9时x轴的范围则是0.0 ~ 1.777(=16/9),这样就不会出现拉伸了。

接下来就进入光栅化阶段了。

接收顶点信息,进行适当的转换后,对顶点进行插值处理,然后对三角形进行遍历,检查每个网格是否被三角形覆盖,如果被覆盖就会生成一个片元。之后交给片元着色器(在DirectX中,也称为像素着色器 Pixel Shader)。

经过片元着色器(Fragment Shader)处理后,得到一个或者多个颜色值(如下图所示)。

之后进入逐片元操作(Per-Fragment Operations),会经过模板测试(Stencil Test)、深度测试(Depth Test)、混合(Blend)等一系列操作,最后得到的结果(一系列颜色值)存放到帧缓冲区,供GPU进行屏幕的更新。

大体的渲染过程就如上所述。中间忽略了不少信息,如坐标转换(主要使用矩阵、四元数,矩阵就是映射),还有投影(正交/平行投影、透视投影),以及光照模型(各种贴图和法线、切线等)。整个过程中裁剪不仅仅只发生在应用阶段,背面剔除、遮挡剔除(光栅化阶段)都使用了裁剪。也没有提及为什么是减少Draw Call,以及如何优化。

先大体理解整个脉络,中间每一个点都可以单独写很多内容,但是总的流程是这样的。对整个渲染流程,时刻要在脑海中有一个比较清晰的认识和了解,不然很容易被各种转换和模型给搞晕,不知道当前处于什么阶段,输入是什么,输出又是什么,接下来要怎么走。

Shader、Draw Call和渲染管线(Rendering Pipeline)的更多相关文章

  1. DirectX 11游戏编程学习笔记之6: 第5章The Rendering Pipeline(渲染管线)

            本文由哈利_蜘蛛侠原创,转载请注明出处.有问题欢迎联系2024958085@qq.com         注:我给的电子版是700多页,而实体书是800多页,所以我在提到相关概念的时候 ...

  2. Real-Rime Rendering (1) - 渲染管线(Rendering Pipeline)

    提要 渲染管线是实时渲染中最重要的部分,它的最主要的任务就是在给定一个虚拟的场景,包括相机,object,灯光,纹理等等,生成一副2D的图像. 最基础的渲染管线如下图所示: 主要的阶段包括三个:App ...

  3. 高屋建瓴 cocos2d-x-3.0架构设计 Cocos2d (v.3.0) rendering pipeline roadmap(原文)

    Cocos2d (v.3.0) rendering pipeline roadmap Why (the vision) The way currently Cocos2d does rendering ...

  4. Rendering pipeline overview(读书笔记1 --- Real-Time rendering)

    1. Rendering pipeline的作用就是在给定的虚拟相机.三维物体.光源.着色方程式.纹理等的条件下产生(渲染)二维图像 2. pipeline包含很多个stage,其效率由最慢的stag ...

  5. OpenGL渲染管线(rendering pipeline)

    OpenGL中的渲染管线包括:顶点着色器(vertex shader).细分着色器(里面包含两种:细分控制着色器和细分控制着色器)(tessellation shader).几何着色器.光栅化及片元着 ...

  6. graphic rendering pipeline

    整理下管线 此时一定要有这张图 注意表中的数据流向 强调几个细节 之前对次序理解有点乱 rasterizer之前 管线里是只有逐顶点信息的 IA里面会setup primitive  通过Primit ...

  7. Geometry Stage in Rendering pipeline (读书笔记2 --- Real-Time rendering)

    Geometry Stage一般包含下面几个阶段 1. Model & View Transform(模型和视图变换) --- 模型空间--> 世界空间 模型变换:每个模型经过模型变换来 ...

  8. 现代OpenGL渲染管线介绍

    原文摘选自 现代OpenGL渲染管线介绍 此文对最新的OpenGL做一个简单的介绍,如有理解错误,敬请指正.英文原文: https://glumpy.github.io/modern-gl.html ...

  9. [OpenGL红宝书]第一章 OpenGL概述

    第一章 OpenGL概述 标签(空格分隔): OpenGL 第一章 OpenGL概述 1 什么是OpenGL 2 初识OpenGL程序 3 OpenGL语法 4 OpenGL渲染管线 41 准备向Op ...

随机推荐

  1. Ubuntu16.04下的modules模块编译加载

    一.首先编写对应的驱动程序的相关内容:(最简单的hello.c程序) #include<linux/init.h> #include<linux/module.h> MODUL ...

  2. vue的中vuex为何需要mutation更新状态,vue-router的路由的理解

    ); ); ); history.back(); history.forward(); // 修改历史,包括二个方法pushState.replaceState二个方法(objState,title, ...

  3. JAVA首次课堂测试总结

    暑期生活已经结束,新的学期也已经开始,而暑期放假之前约定的JAVA首次课堂测试也如期的到来,本次测试真的可以学到和多东西,也有很多感想. 首先体会最深的就是系主任所说的软件工程不是那么好学的,真的需要 ...

  4. 【LeetCode算法-20】Valid Parentheses

    LeetCode第20题 Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determin ...

  5. HDU-2177 取(2堆)石子游戏 (威佐夫博奕)

    Problem Description 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同 ...

  6. HDU 2242 考研路茫茫—空调教室 (边双连通+树形DP)

    <题目链接> 题目大意: 给定一个连通图,每个点有点权,现在需要删除一条边,使得整张图分成两个连通块,问你删除这条边后,两联通块点权值和差值最小是多少. 解题分析: 删除一条边,使原连通图 ...

  7. Flutter - Migrate to AndroidX

    一段时间没玩Flutter,今天打开一个项目编译了一下,突然发现不能编译了,出现 Launching lib\main.dart on Nokia X6 in debug mode... FAILUR ...

  8. IDEA快速入门(Mac版)

    [持续更新]一篇今年年头的老文章顺道发布了,大家有任何问题可以留言沟通.当时刚刚加入团团,愿大家有机会还是购买一台MAC,确实能给大家的效率赋能,虽然在一开始会有一些艰难!⛽️ 望借着换工作的东风,好 ...

  9. shell 运算符

    shell的逻辑运算符 涉及有以下几种类型,因此只要适当选择,可以解决我们很多复杂的判断,达到事半功倍效果. 一.逻辑运算符 逻辑卷标 表示意思 1. 关于档案与目录的侦测逻辑卷标! -f 常用!侦测 ...

  10. 如何删除pagefile.sys

    经常使用电脑的用户就会发现系统自带了虚拟内存文件pagefile.sys,若是电脑出现内存不足情况,其就会调用虚拟内存来执行程序,以防止系统内存崩溃.不过,虚拟内存没有真实的内存读取速度快,而且会占用 ...