龙书11_chapter_6 一:一般绘制流程

先看BoxDemo的前几节,

1.vertex input  Layout

2.vertexBuffer

3.IndexBuffer

4.vertexShader

5.constant Buffer

6.pixelShader

7.renderState

8.effect

1.vertex input  Layout

Once we have defined a vertex structure, we need to provide Direct3D with a description of our vertex structure so that
it knows what to do with each component. This description is provided to Direct3D in the form of an input layout
(ID3D11InputLayout).

创建vertexStruct后,需要提供具体数据描述,告知渲染管线数据是啥。

1. SemanticName: A string to associate with the element. This can be any valid variable name. Semantics are used
to map elements in the vertex structure to elements in the vertex shader input signature

顶点结构每个语义和shader里参数的语义进行匹配。

当然了,vertexShader里不同语义的顺序并不是问题,比如说把

struct VertexIn
{
 float4 Color : COLOR;
 float3 PosL : POSITION;                 切换成Position在前,Color在后,也是可正确绘制出box的,实际上是每个语以对应一个寄存器,但需要注意标记同语义的顺序;};

void BoxApp::BuildVertexLayout()
{
    // Create the vertex input layout.
    D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
    {
        {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
        {"COLOR",    0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}
    };
    // Create the input layout//1. pInputElementDescs: An array of D3D11_INPUT_ELEMENT_DESC elements describing the vertex structure.

2. NumElements: The number of elements in the D3D11_INPUT_ELEMENT_DESC elements array.
3. pShaderBytecodeWithInputSignature: A pointer to the shader byte-code of the input signature of the
vertex shader.
4. BytecodeLength: The byte size of the vertex shader signature data passed into the previous parameter.
5. ppInputLayout: Returns a pointer to the created input layout

    D3DX11_PASS_DESC passDesc;
    mTech->GetPassByIndex(0)->GetDesc(&passDesc);//1.描述vertex struct的数组 2.数组元素 3.对应的shader内参数指针 4.size 5.获取layout
    HR(md3dDevice->CreateInputLayout(vertexDesc, 2, passDesc.pIAInputSignature,
        passDesc.IAInputSignatureSize, &mInputLayout));
}

After an input layout has been created, it is still not bound to the device yet. The last step is to bind the input layout
you want to use to the device as the following code shows:

md3dImmediateContext->IASetInputLayout(mInputLayout);

2.vertexBuffer

Direct3D buffers not only store data, but also describe how
the data will be accessed and where it will be bound to the rendering pipeline.

buffer不仅存数据,还描述了获取数据的方式和绑定到渲染管线的哪里

第四章已经描述过针对buffer的usage的四种类别

Usage:

1.default,GPU读和写,CPU可使用UpdateSubSource(不理解...待解释)

2.immuate:GPU只读, 本次boxDemo中,vertex和index都是使用的此usage,因为并没有改变vertexBuffer内的值

3.dynamic :CPU可写,GPU读,用于每帧app修改数据

4.staging : CPU可从GPU中Copy数据进行读写。

CPUAccessFlags:

If the CPU needs to read from the buffer, specify D3D11_CPU_ACCESS_READ. A buffer with read access must
have usage D3D11_USAGE_STAGING.

In general, the CPU reading
from a Direct3D resource is slow (GPUs are optimized to pump data through the pipeline, but not read back) and
can cause the GPU to stall (the GPU may need to wait for the resource being read from to finish before it can
continue its work). The CPU writing to a resource is faster, but there is still the overhead of having to transfer the
updated data back to video memory. It is best to not specify any of these flags (if possible), and let the resource sit
in video memory where only the GPU writes and reads to it.

就是说CPU读GPU数据可能会造成GPU的延迟,

    D3D11_BUFFER_DESC vbd;
    vbd.Usage = D3D11_USAGE_IMMUTABLE;
    vbd.ByteWidth = sizeof(Vertex) * 8;
    vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vbd.CPUAccessFlags = 0;
    vbd.MiscFlags = 0;
    vbd.StructureByteStride = 0;
    D3D11_SUBRESOURCE_DATA vinitData;
    vinitData.pSysMem = vertices;
    HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &mBoxVB));

创建vertexBuffer后,为了输入到具体的pipeline,需要绑定buffer给设备:

    md3dImmediateContext->IASetVertexBuffers(0,1,&mBoxVB,&stride,&offset);

3.index和indexBuffer

Note that DXGI_FORMAT_R16_UINT and
DXGI_FORMAT_R32_UINT are the only formats supported for index buffers.

4.VertexShader

If there is no geometry shader, then the vertex shader must at least do the projection transformation because
this is the space the hardware expects the vertices to be in when leaving the vertex shader (if there is
no geometry shader). If there is a geometry shader, the job of projection can be deferred to the
geometry shader.

A vertex shader (or geometry shader) does not do the perspective divide; it just does the projection matrix part.
The perspective divide will be done later by the hardware.

VS没有进行坐标归一化,只转换到齐次坐标系,硬件做了除w操作,到NDC空间。

6.Pixel shader

occluded by another pixel
fragment with a smaller depth value, or the pixel fragment may be discarded by a later pipeline test like the stencil
buffer test. Therefore, a pixel on the back buffer may have several pixel fragment candidates; this is the distinction
between what is meant by “pixel fragment” and “pixel,” although sometimes the terms are used interchangeably, but
context usually makes it clear what is meant.

(区分pixel和psF,一个pixel可能包括几个pixel fragment,然后进行fragment的筛选)

sv_target:指出PS的返回值类型要和renderTarget类型一致

7.renderState

D3D是典型的状态机。  状态一直保持不变,直到进行更新。inputLayout,vertex/index Buffer,

8.Effects

1. technique11: A technique consists of one or more passes which are used to create a specific rendering
technique. For each pass, the geometry is rendered in a different way, and the results of each pass are combined
in some way to achieve the desired result. For example, a terrain rendering technique may use a multi-pass
texturing technique. Note that multi-pass techniques are usually expensive because the geometry is redrawn for
each pass; however, multi-pass techniques are required to implement some rendering techniques.
2. pass: A pass consists of a vertex shader, optional geometry shader, optional tessellation related shaders, a pixel
shader, and render states. These components indicate how to process and shade the geometry for this pass. We
note that a pixel shader can be optional as well (rarely). For instance, we may just want to render to the depth
buffer and not the back buffer; in this case we do not need to shade any pixels with a pixel shader.

Creating Direct3D resources is expensive and should always be done at initialization time, and never at
runtime. That means creating input layouts, buffers, render state objects, and effects should always be
done at initialization time.

就是说 创建工作要在initialization时候。

    mTech = mFX->GetTechniqueByName("ColorTech");
    mfxWorldViewProj= mFX->GetVariableByName("gWorldViewProj")->AsMatrix();

Note that these calls update an internal cache in the effect object, and are not transferred over to GPU memory
until we apply the rendering pass . This ensures one update to GPU memory instead of many small updates,
which would be inefficient.

数据的更新是在Effect调用pass后,一次性进行的。instead of many small updates

    mfxWorldViewProj->SetMatrix(reinterpret_cast<float*>(&worldViewProj));

    D3DX11_TECHNIQUE_DESC techDesc;
    mTech->GetDesc( &techDesc );
  for(UINT p = 0; p < techDesc.Passes; ++p)
  {
        mTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
        // 36 indices for the box.
        md3dImmediateContext->DrawIndexed(36, 0, 0);
  }

When the geometry is drawn in a pass, it will be drawn with the shaders and render states set by that pass. The
ID3DX11EffectTechnique::GetPassByIndex method returns a pointer to an ID3DX11EffectPass
interface, which represents the pass with the specified index. The Apply method updates the constant buffers stored in
GPU memory, binds the shader programs to the pipeline, and applies any render states the pass sets. In the current
version of Direct3D 11, the first parameter of ID3DX11EffectPass::Apply is unused, and zero should be
specified; the second parameter is a pointer to the device context the pass will use.

GetPassByIndex 获取pass的index,Apply更新GPU中的constantBuffer,绑定shader程序到管线,应用renderState

书中有趣的还是shader中不同条件的pass选取

#define low 0

#define mid 1(...high..)

float4 PS(IN_P pin,unsigned int Quality)

{

if(Quality==low){...}

else if(Quality==mid){...}

}

techique11 te

{

pass0

{

SetPixelShader(compilerShader(PS_5_0,PS(low)))

}

}

....

这种方式可以提高代码的利用率,同时编译时,根据PS的参数不同选择编译代码,不编译条件不满足的部分。也许相当于预编译把。

时间: 2024-08-25 13:04:55

龙书11_chapter_6 一:一般绘制流程的相关文章

龙书11_chapter_6 二:HillsDemo解析

书中HillsDemo 关键是类的结构,GeometryGenerator的组成和应用: MeshData的构成,来存储Mesh的vertex和index数据: class GeometryGenerator { public: struct Vertex { Vertex(){} Vertex(const XMFLOAT3& p):Position(p){} Vertex(float px,float py,float pz):Position(px,py,pz){} XMFLOAT3 Pos

龙书学习笔记(三)

在将第五章每个示例代码过了一遍之后,大致明白了光照这一章的内容,主要分为四点: 一.光照的类型分为三种,并且均通过结构D3DCOLORVALUE或D3DXCOLOR来表示光线的颜色 环境光(Ambient Light)经其它表面反射到达物体表面,并照亮整个场景,通常用做较低代价的粗略模拟. 漫射光(Diffuse Light)沿着特定的方向传播,到达某个表面后将沿着各个方向均匀反射,因此从各个方向观察物体表面亮度均相同. 镜面光(Specular Light)沿着特定的方向传播,到达一表面后将沿

龙书学习笔记(二)

补线代之余抽空把第四章上色学了,之所以说之余,是因为这一章内容确实不怎么多,不过为了巩固知识,便结合刚学的上色又做了一个小程序. 首先进行回顾,这一章学到的一共有四点: 一.Direct3D中颜色用RGB(Red.Green.Blue)三元组表示,用两种结构来保存 D3DCOLOR,即unsigned long,共32位,分成4个8位项,分别保存Alpha(这玩意的作用会在第七章学到).红.绿.蓝,均在0x00~0xff之间取值(就是0~255) 通过结构体来保存(D3DXCOLOR和D3DCO

深入理解 Android 之 View 的绘制流程

概述 本篇文章会从源码(基于Android 6.0)角度分析Android中View的绘制流程,侧重于对整体流程的分析,对一些难以理解的点加以重点阐述,目的是把View绘制的整个流程把握好,而对于特定实现细节则可以日后再对相应源码进行研读.在进行实际的分析之前,我们先来看下面这张图: 我们来对上图做出简单解释:DecorView是一个应用窗口的根容器,它本质上是一个FrameLayout.DecorView有唯一一个子View,它是一个垂直LinearLayout,包含两个子元素,一个是Titl

Android学习笔记&mdash;&mdash;OpenGL ES的基本用法、绘制流程与着色器编译

首先声明下,本文为笔者学习<OpenGL ES应用开发实践指南(Android卷)>的笔记,涉及的代码均出自原书,如有需要,请到原书指定源码地址下载. 在Android.iOS等移动平台上,开发者可以使用跨平台应用编程接口创建二维或者三维图形,或进行图像处理和计算机视觉应用,结合两者将能构建丰富有趣的交互体验.前者称为OpenGL,后者称为OpenCV,不过本文主要介绍前者,OpenCV在后续文章中涉及.OpenGL应用于桌面系统的历史已经很长了,但考虑到移动平台的特点(计算能力.性能等),将

Android View 绘制流程(Draw) 完全解析

前言 前几篇文章,笔者分别讲述了DecorView,measure,layout流程等,接下来将详细分析三大工作流程的最后一个流程--绘制流程.测量流程决定了View的大小,布局流程决定了View的位置,那么绘制流程将决定View的样子,一个View该显示什么由绘制流程完成.以下源码均取自Android API 21. 从performDraw说起 前面几篇文章提到,三大工作流程始于ViewRootImpl#performTraversals,在这个方法内部会分别调用performMeasure

【龙书笔记】用Python实现一个简单数学表达式从中缀到后缀语法的翻译器(采用递归下降分析法)

上篇笔记介绍了语法分析相关的一些基础概念,本篇笔记根据龙书第2.5节的内容实现一个针对简单表达式的后缀式语法翻译器Demo. 备注:原书中的demo是java实例,我给出的将是逻辑一致的Python版本的实现. 在简单后缀翻译器代码实现之前,还需要介绍几个基本概念. 1. 自顶向下分析法(top-down parsing) 顾名思义,top-down分析法的思路是推导产生式时,以产生式开始符号作为root节点,从上至下依次构建其子节点,最终构造出语法分析树.在具体实现时,它会把输入字符串从左到右

[HLSL]HLSL 入门参考 (dx11龙书附录B译文)

原文:[HLSL]HLSL 入门参考 (dx11龙书附录B译文) HLSL 高级着色语言 参考文档 龙书DirectX12现已推出中文版,其附录B的高级着色器语言参考的翻译质量比本文更高,有条件的读者可以去支持一下. 目录 文章目录 目录 变量类型 标量类型 矢量类型 Swizzles 矩阵类型 数组 结构体 typedef 关键字 变量前缀 类型转换 (Casting) 关键字 和 (运)算符 关键字 (运)算符 流程语句 函数 自定义函数 内建函数 译注 变量类型 标量类型 bool: 值为

Android中View绘制流程以及invalidate()等相关方法分析

前言: 本文是我读<Android内核剖析>第13章----View工作原理总结而成的,在此膜拜下作者 .同时真挚地向渴望了解 Android 框架层的网友,推荐这本书,希望你们能够在Android开发里学到更多的知识 . 整个View树的绘图流程是在ViewRoot.java类的performTraversals()函数展开的,该函数做的执行过程可简单概况为 根据之前设置的状态,判断是否需要重新计算视图大小(measure).是否重新需要安置视图的位置(layout).以及是否需要重绘 (d