- 博客(67)
- 资源 (2)
- 收藏
- 关注
原创 Effective C++学习笔记(十六)
一旦程序员领悟了pass-by-value(传值)的效率牵连层面,往往变成十字军战士,一心一意根除pass-by-value带来的种种邪恶。在坚定追求pass-by-reference的纯度中,他们一定会犯下一个致命错误:开始传递一些references指向其实并不存在的对象,这可不是件好事。考虑一个用以表现有理数的class,内含一个函数用来计算两个有理数的乘积:class Ration
2016-11-27 22:03:08 243
原创 Effective C++ 学习笔记(十五)
缺省情况下C++以by value方式(一个继承自C的方式)传递对象至(或来自)函数。除非你另外指定,否则函数参数都是以实际实参的复件(副本)为初值,而调用端所获得的亦是函数返回值的一个复件。这些复件(副本)系由对象的copy构造函数产出,这可能使pass-by-value成为昂贵(费时的)操作。class Person{ public: Person(); vi
2016-11-27 21:04:48 226
原创 Effective C++ 学习笔记(十四)
开发一个“容易被正确使用,不容易被误用”的接口,首先必须考虑客户可能做出什么样的错误。假设你为一个用来表现日期的class设计构造函数:class Date{ public: Date(int month,int day,int year);};但它的客户很容易犯至少两个错误,第一,它们会以错误的次序传递参数:Date d(30,3,1995);(键
2016-11-26 22:36:55 302
原创 相交---光线与球
光线与球之间的相交很容易计算。如果光线的两端分别是(x1,y1,z1)和(x2,y2,z2),则第一步是将光线参数化: x=x1+(x2-x1)t=x1+it y=y1+(y2-y1)t=y1+jt z=z1+(z2-z1)t=z1+kt其中 0中
2016-11-26 17:37:47 1570
原创 经典的光照模型
原理的阐述的过程难免是枯燥的,我们会尽量在逻辑安排和讲解方式上减轻这种感觉。环境光:从物体表面所产生的反射光的统一照明,称为环境光或背景光。通常我们认为理想的环境光有如下特性: 没有空间或方向性,在所以方向上和物体表面投射的环境光强度是统一的恒定值。由于环境光给予物体各个点的明暗程度均一样,因此,只有环境光是不能产生具有真实感的图形效果。
2016-11-23 19:52:53 2432
原创 GPU待解决的问题
首先需要知道“我们想让着色语言提供那些特性”,首先,希望着色语言可以做到方便进行通用计算编程,而不被数据之间的独立性所限制,其次,我们希望在着色语言方面有所加强,此外,着色语言还需要引入继承机制,让其面向对象的特性更加明显,要加强调试功能,可以对程序执行过程进行调试(现阶段好像比较困难),如果没有很好的调试功能,也希望可以有一个比较通用的IDE提供给编程者。此外,未来的可编程图形硬件的顶点处理
2016-11-23 06:02:07 268
原创 STL之map实现(五)
接下来,实现插入函数void SortedMap::insert(const pair& thePair){ //找到你插入的位置 pairNode* p =firstNode ,*tp=NULL; //不能存在重复的key,如果出现重复的key后面的会覆盖掉前面的 while(p!=NULL&& p->element.first t
2016-11-22 06:50:17 484 1
原创 STL之map实现(四)
首先,实现是否为空,比如你在学校运动会,想知道跑多少圈,可以引入计数。protected: int dSize;//计数------统计数对个数 pairNode * firstNode;在构造函数初始化成员SortMap(){ firstNode=NULL; dSize=0;}//判断是否为空bool empty
2016-11-22 06:34:33 286
原创 STL之map实现(三)
接下来,实现抽象类//C++继承class SortedMap:public Dictionary{ public: //构造函数+析构函数 SortMap(); ~SortMap(); bool empty() ; //纯虚函数-
2016-11-22 06:28:34 428
原创 STL之map实现(二)
类和对象:以学生类为例属性int double charsex name(基本数据成员描述事物共有特性)-----基本数据成员行为:操作如 吃饭 睡觉 打游戏 ------函数纯虚函数: virtual 函数名() =0;//没有函数体,不需要函数体首先,我们来实现一个模板,我们应该写两个未知类型,不多说了,直接上代码template cl
2016-11-22 06:20:15 359
原创 STL之map实现(一)
map其实就是一个映射,想象你在使用新华字典的时候,输入一个单词,就能得到这个单词的意思,这样就形成了一个映射。为了实现map,你需要有类和对象,虚函数,模板,pair类型基础首先,介绍一下模板,看下面的函数(重复做同样事情的函数,只是类型不一样)int sum(int a,int b){ return a+b;}float sum(float
2016-11-22 05:05:47 1639
原创 Fragment Shader Program
片段着色程序对每个片段进行独立的颜色计算,最后输出颜色值的就是该片段最终显示的颜色。可以这样说,顶点着色程序主要进行几何方面的运算,而片段着色程序主要针对最终颜色值进行计算。片段着色器还有一个突出的特点是:拥有检索纹理的能力。对于GPU而言,纹理等价于数组,这意味着,如果要做通用计算,例如数组排序,字符串检索等,就必须使用片段着色程序。片段和像素的区别?
2016-11-21 05:53:47 781
原创 Vertex Shader Program
顶点着色程序从GPU前端模块(寄存器)中提取图元信息(顶点位置. 法向量 . 纹理坐标等),并完成顶点坐标空间转换,法向量空间转换,光照计算等操作。最后将计算好的数据传送到指定寄存器中。然后片段着色器从种获取需要的数据,通常为“纹理坐标,光照信息等”,并根据这些信息以及从应用程序传递的纹理信息进行每个片段的颜色计算,最后将处理后的数据送到光栅操作模块。如果只有顶点
2016-11-21 05:32:27 416
原创 Shader Language
任意一种shader language都必须基于图形硬件,所以GPU编程技术的发展本质上还是图形硬件的发展。在shader language存在之前,展示基于图形硬件的编程能力只能靠低级的汇编语言。顶点和片段处理器都拥有非常强大的并行计算能力,并且非常擅长于矩阵计算,片段着色器还可以高速查询纹理信息(目前顶点处理器还不行,这是顶点处理器的一个发展方向)顶
2016-11-21 05:29:32 412
原创 Frame Buffer
Frame buffer,称为帧缓冲器,用于存放显示输出的数据,这个buffer中的数据一般是像素颜色值。Frame buffer有时也被认为是color buffer(颜色缓冲器)和z buffer的组合。Frame buffer通常都在显卡上,但是有时显卡会集成到主板上,所以这种情况下frame buffer被放在内存区域。
2016-11-21 05:11:57 422
原创 Stencil Buffer
Stencil buffer,为“模板缓冲区”,它是一个额外的buffer,通常附加到z buffer中,15位的z buffer加上1 位的stencil buffer(总共2个字节);或者24位的z buffer 加上8位的stencil buffer(总共4个字节)。每个像素对应一个stencil buffer(其实就是对应一个Z buffer).
2016-11-21 05:09:08 522
原创 Z Buffer与Z值
Z buffer应该是大家最为熟悉的缓冲区类型,又称为depth buffer,即深度缓冲区,其中存放的是视点到每个像素所对应的空间点的距离衡量,称之为Z值或者深度值。可见物体的Z值范围位于[0,1]区间,默认情况下,最接近眼睛的顶点(近裁减面上)其Z值为0.0,离眼睛最远的顶点(远裁减面上)其Z值为1.0.使用z buffer可以用来判断空间点的遮挡关系,著名的深度缓冲区算法(depth-b
2016-11-21 04:39:55 4314
原创 GPU内存架构
从物理结构而言,寄存器是cpu或gpu内部的存储单元,即寄存器是嵌入在cpu或者gpu中的,而内存则可以独立存在;从功能上而言,寄存器是有限存储容量的高速存储部件,用来暂存指令,数据,和位址。Shader编成是基于计算机图形硬件的,这其中就包括GPU上的寄存器类型,glsl和hlsl的着色虚拟机版本就是基于GPU的寄存器和指令集而区分的。
2016-11-21 04:33:38 1271
原创 像素操作的流程
Fragment& Associated Data ===>Pixel OwnershipTest ===>Scissor Test===>Alpha Test ===>Stencil Test===>Depth Test===>Blending===>Dithering===>Logic Op===>Color Buffer.
2016-11-20 23:56:00 343
原创 Pixel Operation
Pixel operator 又称为Raster Operation,是在更新帧缓存之前,执行最后一系列针对每个片段的操作。其目的是:计算出每个像素的颜色值。在这个阶段,被遮挡面通过一个被称为深度测试的过程而消除,这其中包含了很多种计算颜色的方法以及技术。1.消除遮挡面2.纹理操作 ,根据像素的纹理坐标,查询对应的纹理值3.混色 ,根据目前已经画好的颜色
2016-11-20 23:43:38 403
原创 光栅化
光栅化:决定哪些像素被集合图元覆盖的过程。我们得到每个点的屏幕坐标值,也就知道我们需要绘制的图元(点、线、面),存在两个问题.问题一: 点的屏幕坐标值是浮点数,但像素都是由整数点来表示的,如何确定屏幕坐标值所对应的像素?问题二:在屏幕上需要绘制的有点,线,面,如何根据两个已经确定位置的2个像素点绘制一条线段,如何根据已经确定了位置的3个像素点绘制一个三角面片?
2016-11-20 23:31:15 412
原创 图元装配
图元装配,即将顶点根据primitive(原始的连接关系)还原成网格结构。网格由顶点和索引组成,在之前流水线中是对顶点的处理,在这个阶段是根据索引将顶点连接在一起,组成线、面单元。之后就是对超出屏幕外的三角形进行裁剪。想象一下:一个三角形其中一个顶点在画面外,另外两个顶点在画面内,这时我们在屏幕上看到的就是一个四边形,然后将四边形切成两个三角形。此外还有一个操作涉及到三角形的顶点顺
2016-11-20 23:16:44 4146
原创 从eye space 到 project and clip space
一旦顶点坐标被转换为eye space 中,就需要判断哪些点是视点可见的。位于viewing frustum梯形体以内的顶点,被认定为可见,而超出这个梯形体之外的场景数据,会被视点去除(Frustum Culling,也称之为视锥裁剪)。这一步通常称之为“Clip(裁剪)”,识别指定区域或区域外的图形部分的过程称之为裁剪算法。多边形裁剪就是CVV(单位立方体或者规范立方体)中完
2016-11-20 23:02:50 346
原创 从object space 到world space
object space coordinate就是模型文件中的顶点值,这些值是在模型建模时得到的,如,用3DMAX建立一个球体模型并导出.max文件,这个文件中包含的数据就是object space coordinate;其二,object space coordinate与其他物体没有任何参照关系,它是将object space coordinate和world space coordinate
2016-11-20 22:38:30 1232
原创 顶点坐标空间变换流程
几何阶段的主要工作室“变换三维顶点坐标”和“光照计算”。(T &L)顶点坐标变换的顺序: 模型坐标空间===》世界坐标系空间====》观察坐标空间===》屏幕坐标空间.
2016-11-20 22:33:46 888
原创 GPU图形绘制管线
图形绘制管线描述GPU渲染流程,即“给定视点,三维物体,光源,照明模式,和纹理等元素,如何绘制一幅二维图像”。将图形绘制管线分为三个主要阶段:应用程序阶段,几何阶段,光栅阶段。应用程序阶段: 主要和CPU,内存打交道;诸如碰撞检测,场景图建立,空间八叉树更新,视锥剪裁等经典算法都在此阶段。 该阶段的末端,几何体数据(顶点坐标、法向量、纹理坐标、纹理等)通过数据总线
2016-11-20 22:27:17 347
原创 CPU VS GPU
GPU具有高并行结构,所以GPU在处理图形数据结构和复杂算法方面拥有比CPU更高的效率。CPU大部分面积为控制器和寄存器,与之相比,GPU拥有更多的ALU(Arithmetic Logic Unit 逻辑运算单元)用于处理数据,而非数据高速缓存和流控制,这样的机构适合对密集型数据进行并行处理。CPU执行计算任务时,一个时刻只处理一个数据,不存在真正意义上的并行,而GPU具有
2016-11-20 21:23:17 341
原创 GPU介绍
GPU发展第一阶段: 这些GPU可以独立于CPU进行像素缓存区的更新,并可以光栅化三角面片以及进行纹理操作,但是缺乏三维顶点的空间坐标变换能力,这意味着“必须依赖于GPU执行顶点坐标变换的计算。”这一时期GPU的功能非常有限,智能用于纹理组合的数学计算或者像素颜色值的计算。 GPU发展第二阶段: 这一时期的GPU可以进行三维坐标转换和光照计算,并且Ope
2016-11-20 21:07:22 873
原创 局部特化
类模板可以被局部特化,可以在特定环境下指定类模板的特定实现,并且要求某些模板参数仍然必须由用户来定义。template class MyClass{}有以下几种局部特化://局部特化,两个模板参数具有相同的类型template class MyClass {};//局部特化:第2个模板参数的类型是inttemplatecl
2016-11-20 20:32:10 461
原创 类模板的特化
你可以用模板实参来特化类模板,和函数模板的重载类似,通过特化类模板,你可以优化基于某种特定类型的实现,或者克服某种特定类型在实例化类模板时所出现的不足,另外,如果要特化一个类模板,你还要特化该类模板的所有成员函数,虽然也可以只特化某个成员函数,但这个做法并没有特化整个类,也就没有特化整个模板。 为了特化一个类模板,你必须在起始处声明一个templatetempla
2016-11-20 20:05:19 922
原创 类模板
类也可以被一种或多种类型参数化。容器类就是一个具有这种特性的典型例子,通常被用于管理某种特定类型的元素。 只要使用类模板,你就可以实现容器类,而不需要确定容器中元素的类型。
2016-11-20 01:20:21 305
原创 重载函数模板
//求两个int值得最大值inline int const& max(int const& a,int const& b){ return a}//求两个任意类型值中的最大者templateinline T const& max(T const& a,T const& b){ return a}//求3个任意类型值中的最大者temp
2016-11-20 00:49:33 1775
原创 模板参数
template inline T const& max(T const& a,T const& b);max(4,7);//OK两个参数的类型都是Intmax(4,4.2)//ERROR:第1个是int,而第二个是double有3种方法处理这个错误:1.对实参进行强制类型转换,使它们可以互相匹配max(static_cast (4),4.2);//OK
2016-11-20 00:29:01 423
原创 编程风格
显然,下面几种风格都是可能的:void foo {const int &x};void foo { const int& x};void foo { int const &x};void foo {int const& x};趋向于使用int const 而不是const int首先针对问题,什么是恒定不变的,恒定不变的部分就是con
2016-11-19 23:48:35 198
原创 内存耗尽怎么办?
如果申请动态内存时找不到足够大的内存块,malloc 和new将返回NULL指针,宣告内存申请失败.处理"内存耗尽"的问题1)判断指针是否为NULL,如果是则马上用return语句终止本函数。void Fun(void){ A *a =new A;if(a==NULL){ return ;}}2)判断指针是否为NULL,如果是马上用exit(
2016-11-17 23:14:30 482
原创 malloc/free 和new/delete
对于非内部数据类型的对象而言,光用malloc/free无法满足动态对象的要求。对象创建时同事要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc是库函数不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的人物强加于malloc/free。不要企图用malloc/free来完成动态对象的内存管理,应该用new/delete.由于内部数据类型的“对象”没
2016-11-17 21:46:04 208
原创 杜绝“野指针”
“野指针”不是NULL指针,是指向“垃圾”内存的指针。野指针的成因主要有两种:1)指针变量没有被初始化。 指针刚被创建时不会自动初始化为NULL指针,缺省值是随机的。 在创建的同时应该被初始化,要么设置为NULL,要么让它指向合法的内存. 如: char* p=NULL; char * str=(char*) malloc(
2016-11-17 21:18:04 203
原创 指针参数是如何传递内存的
如果函数的参数是一个指针,不要指望用该内存去申请动态内存void GetMemory(char * p ,int num){ p=(char*)malloc(sizeof(char)*num);}void Test(void){ char* str=NULL; GetMemory(str,100); strcpy(str,"hello");}
2016-11-17 04:11:02 216
原创 指针与数组的比较
数组要么在静态存储区被创建(如全局数组),要么在栈上呗创建。数组名对应一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。指针随时指向任意类型的内存块,特征是“可变”,常用指针来操作动态内存。‘特性比较:1.修改内容:char a[]="hello";a[0]='X';coutchar* p="world";
2016-11-17 03:30:12 201
原创 常见内存错误
1.内存分配未成功,却使用了它 如果指针p是函数的参数,那么在函数入口处 用 assert(p!=NULL)进行检查 如果是用malloc或new来申请内存,应该用if(p==NULL)或if(p!=NULL)进行防错处理2.内存分配虽然成功,但是尚未初始化就引用它。 一是没有初始化的概念,而是误以为内存的缺省初值全为零,导致引用初值错误(如数组)3.内存分配
2016-11-17 03:25:04 261
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人