当前位置:  编程技术>综合
本页文章导读:
    ▪c++编程风格----读书笔记(1)      一、抽象     在软件开发中,抽象处于一种中心地位,而类则是C++中最重要的抽象机制。类描述的是所有从这个类实例化出来的对象的共同属性,并且刻画了这些对象的共.........
    ▪codeforces round 160      又跪了。。。继续做吧,坚持!! codeforces 261B     先用背包处理出一个dp数组,然后枚举每一个分隔数(即前面的数再加上这个数就超过p了) 统计出所有的数量,然后直接算,, h.........
    ▪【Visual C++】游戏开发笔记四十 浅墨DirectX教程之八 绘制真实质感的三维世界:光照与材质专场       本系列文章由zhmxy555(毛星云)编写,转载请注明出处。  文章链接: http://blog.csdn.net/zhmxy555/article/details/8499438作者:毛星云(浅墨)    邮箱: happylifemxy@163..........

[1]c++编程风格----读书笔记(1)
    来源: 互联网  发布时间: 2013-11-19

一、抽象

    在软件开发中,抽象处于一种中心地位,而类则是C++中最重要的抽象机制。类描述的是所有从这个类实例化出来的对象的共同属性,并且刻画了这些对象的共同行为。在C++设计中,正确识别抽象是一个很关键的步骤。如果想获得高质量的抽象,那么程序员就必须要充分地理解程序中的各种对象的内在属性。

1、编程风格示例,如下程序:

#include "stdafx.h"
#include "iostream"

enum CARD	{ CDROM, TAPE, NEWWORK };
enum MONITOR{ MONO, COLOR };

class Card
{
public:
	virtual int	 Price() = 0;
	virtual char *Name() = 0;
	virtual int	 Rebate();
};

class NetWork : public Card
{
public:
	int	 Price();
	char *Name();
};

class CDRom : public Card
{
public:
	int	 Price();
	char *Name();
	int  Rebate();
};

class Tape : public Card
{
public:
	int	 Price();
	char *Name();
};

class Monitor
{
public:
	virtual int	 Price() = 0;
	virtual char *Name() = 0;
};

class Color : public Monitor
{
public:
	int	 Price();
	char *Name();
};

class Monochrome : public Monitor
{
public:
	int	 Price();
	char *Name();
};

int Card::Rebate()		 { return 45; }

int	 NetWork::Price()	 { return 600;       }
char *NetWork::Name()	 { return "NetWork"; }

int CDRom::Price()		 { return 1500;    }
char *CDRom::Name()		 { return "CDRom"; }
int CDRom::Rebate()		 { return 135;     }

int Tape::Price()		 { return 1000;   }
char *Tape::Name()		 { return "Tape"; }

int Color::Price()		 { return 1500;	   }
char *Color::Name()		 { return "Color"; }

int Monochrome::Price()	 { return 500;	  }
char *Monochrome::Name() { return "Mono"; }

class Computer
{
public:
	Computer(CARD, MONITOR);
	~Computer();

public:
	int NetPrice();
	void Print();
private:
	Card	*card;
	Monitor *mon;
};

Computer::Computer(CARD c, MONITOR m)
{
	switch (c)
	{
	case CDROM:
		card = new CDRom();
		break;
	case TAPE:
		card = new Tape();
		break;
	case NEWWORK:
		card = new NetWork();
		break;
	default:
		break;
	}
	switch (m)
	{
	case MONO:
		mon = new Monochrome();
		break;
	case COLOR:
		mon = new Color();
		break;
	default:
		break;
	}
}

Computer::~Computer()
{
	if (card)
	{
		delete card;
		card = NULL;
	}
	if (mon)
	{
		delete mon;
		mon = NULL;
	}
}

int Computer::NetPrice()
{
	return mon->Price() + card->Price() - card->Rebate();
}

void Computer::Print()
{
	std::cout << card->Name() << "   " << mon->Name() << " , " << 
		"net Price = " << NetPrice() << std::endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	Computer mn(NEWWORK, MONO);
	Computer mc(CDROM,	 MONO);
	Computer mt(TAPE,	 MONO);
	Computer cn(NEWWORK, COLOR);
	Computer cc(CDROM,	 COLOR);
	Computer ct(TAPE,	 COLOR);

	mn.Print();
	mc.Print();
	mt.Print();
	cn.Print();
	cc.Print();
	ct.Print();

	return 0;
}

想一想这里是否有必要写得这么冗长和复杂?这个程序是不是一定需要8个类,并且其中有7个类含有虚函数,才能解决问题?

2、找出上面程序中共同的抽象

    Card和Monitor这两个类的接口是相似的:它们都含有纯虚函数Pirce()和Name()。不同的地方在于Card类中海油一个虚函数Rebate()。所以可以把这两个类再次抽象出来一个Component类,还有这段代码:

int Computer::NetPrice()
{
	return mon->Price() + card->Price() - card->Rebate();
}

不应该显示地依赖于组件是否存在折扣,而应该对每种组件进行统一处理,这里实际上隐含了另一个抽象,如果将NetPrice也作为一个成员函数添加到Component类中,那么在函数Component::NetPrice()中只需调用Component的其他成员函数即可(也就是将共同的抽象提取出来并放到基类中)

3、来看看其他的如CDRom和NetWork之间的区别,而他们只在于各自虚函数返回的值时不同。在实际工作中,程序并不会为每个需要创建的对象提供一个不同的类,而是用一个类来表示一组对象(也就是一个类应该能够描述一组对象)

4、最初编写这个程序的人员陷入了一个常见的思维陷阱,他认为,在用C++来进行程序设计时,继承和虚函数是唯一的方法。于是,他在程序中过度地使用了继承,从而导致某些类的声明过于具体,甚至只能描述一种对象。如果在不同的对象之间有不同的行为,那么继承和多态是很有用的工具。然而,在本程序中,对象之间的不同之处在于他们的属性,而并非行为(如果派生类之间的区别在于属性,则用数据成员来表示;如果在于行为,则用虚函数来表示)

5、引入继承

    经过修改,我们现在的程序只有Component,但是程序需要将扩展卡和显示器区分开来,并且他们只是折扣不一样,所以加入继承,为两者提供不同的构造函数,从而提供合适的特化

    通常,如果派生类是基类的特化,存在着派生类是“一种基类对象”这种关系时,可以考虑将派生类之间的不同之处局限在初始化过程中

6、去掉枚举

    Card和Monitor是两种截然不同的类型。如果将Computer::Computer的参数改为指向对象的指针,那么就可以去掉枚举和switch语句。


7、来看看经过修改的程序:

#include "stdafx.h"
#include "iostream"

class Component
{
public:
	Component(int price, char *name, int rebate)
		:price_(price), name_(name), rebate_(rebate)
	{

	}
public:
	int	 Price()  { return price_; }
	char *Name()  { return name_;  }
	int Rebate()  { return rebate_;}
	int NetPrice(){ return (rebate_ - rebate_); }
private:
	int price_;
	char *name_;
	int rebate_;
};

class Card : public Component
{
public:
	Card(int price, char *name, int rebate = 45)
		: Component(price, name, rebate)
	{

	}
};

class Monitor : public Component
{
public:
	Monitor(int price, char *name, int rebate = 0)
		: Component(price, name, rebate)
	{

	}
};

class Computer
{
public:
	Computer(Card *card, Monitor *monitor);

public:
	int NetPrice();
	void Print();
private:
	Card	*card_;
	Monitor *monitor_;
};

Computer::Computer(Card *card, Monitor *monitor)
{
	card_ = card;
	monitor_ = monitor;
}

int Computer::NetPrice()
{
	return (card_->Rebate() + monitor_->Rebate());
}

void Computer::Print()
{
	std::cout << card_->Name() << "   " << monitor_->Name() << " , " << 
		"net price = " << NetPrice() << std::endl;
}

void InitSoming()
{
	Card NetWork(600, "NetWork");
	Card CDRom(600, "CDROM", 135);
	Card Tape(600, "TAPE");

	Monitor Color(1500, "Color");
	Monitor Mono(500, "Mono");

	Computer mn(&NetWork,&Mono);
	Computer mc(&CDRom,	 &Mono);
	Computer mt(&Tape,	 &Mono);
	Computer cn(&NetWork,&Color);
	Computer cc(&CDRom,	 &Color);
	Computer ct(&Tape,	 &Color);

	mn.Print();
	mc.Prin      
    
[2]codeforces round 160
    来源: 互联网  发布时间: 2013-11-19

又跪了。。。继续做吧,坚持!!

codeforces 261B    

先用背包处理出一个dp数组,然后枚举每一个分隔数(即前面的数再加上这个数就超过p了) 统计出所有的数量,然后直接算,,

http://www.codeforces.com/contest/261/submission/2921844

作者:haha593572013 发表于2013-1-14 3:07:21 原文链接
阅读:21 评论:0 查看评论

    
[3]【Visual C++】游戏开发笔记四十 浅墨DirectX教程之八 绘制真实质感的三维世界:光照与材质专场
    来源: 互联网  发布时间: 2013-11-19

 

本系列文章由zhmxy555(毛星云)编写,转载请注明出处。  

文章链接: http://blog.csdn.net/zhmxy555/article/details/8499438

作者:毛星云(浅墨)    邮箱: happylifemxy@163.com   

 


 

一、引言



光,乃万物之源。我们根本无法想象,这个美丽怡人的世界,如果没有光的陪伴,会是怎样的一副满目疮痍。计算机3D世界作为现实世界的高度逼真的模仿,必然也少不了光的陪伴。回到我们的Direct3D应用程序中来,在Direct3D中运用光照,能有效地增强3D场景的真实感。在3D场景中使用光照其实非常地简单,我们不需要为物体的每个顶点都去指定颜色值,只要我们告诉Direct3D我们使用的是什么类型的光照,我们的物体的材质的具体参数以及物体表面相对于光源的朝向,Direct3D就会根据其内置的算法计算出每个顶点的颜色值,产生出逼真的光照效果。

当然随着我们学习的深入,功力的加深,就可以不单单依赖于Direct3D中内建的光照算法,可以根据各种功能的着色器的编写,自己写出更加优化更加逼真的光照效果来。

作为目前刚刚接触到Direct3D中的光照和材质这一块内容,我们还是老老实实地先把固定功能流水线中的这一套非常好学好掌握的光照与材质的体系系统地进行讲解,先把基础打牢,先把走学会,这样才能为后面我们的腾飞做铺垫。

 

说到一套完整的光照体系,有两对组成方面,第一,光照,第二,材质。这两者天生就是一对好搭档,我们可以把它们看做光照计算的两要素,想要绘制出具有光照的真实三维世界,两者缺一不可。

下面就开始正式讲解,首先我们来看看四大光照类型:

 

 

二、四大光照类型


1.环境光(Ambient Light)




一个物体即使没有直接被光源照射,但是只要有光线通过其他物体的折射、反射到达物体,它也可能被看见。这种基于整个自然界环境的整体亮度,称为环境光(Ambient Light)或者背景光。环境光没有位置或者方向上的特征,只有一个颜色亮度值,而且不会衰减,所以在所有方向和所有物体表面上投射的环境光的数量是恒定不变的。想要以较低的代价和开销来近似模拟光照的话,直接开启环境光是一个不错的选择。

在Direct3D中环境光的设置非常简单,也就是用一下SetRenderState,代码如下:

pd3dDevice->SetRenderState(D3DRS_AMBIENT,D3DCOLOR_XRGB(36, 36, 36));   //设置一下环境光

其中第一个参数填D3DRS_AMBIENT,代表环境光的设置,而第二个参数填一个颜色值就可以了。

 

 

2.漫反射光(DiffuseLight)




漫反射光在我们的生活中最为普遍,太阳的直射,日光灯的照射都可以看成漫反射的近似。这种类型的光沿着特定的方向传播。当它到达某一表面时,将沿着各个方向均匀反射,所以我们无论从哪个方向观察,物体表面的亮度都是相同的,所以采用漫反射这种光照模型时,无需考虑观察者的位置,但是需要考虑漫反射光的空间位置和方向。从一个光源发出的光一般都是这种类型的。漫反射光并没有简洁的设置方法,具体下文会讲到的,请大家继续往下看。

 

 

 

3.镜面反射光(SpecularLight)




镜面反射光,顾名思义,沿着特定的方向传播,当此类光到达一个表面时,将严格地沿着另一个方向反射,从而形成只能在一个角度范围内才能观察到的高亮度照射。这种光照模型模拟了从光滑发光面如镜子、一块金属或者一块发光塑料等材料来进行光线反射的情形。如果我们移动一下光源的话,就会发现镜面亮光区所发生的变化,这意味着镜面反射取决于观察者的角度。我们可以这样来归纳,漫反射与视觉无关,而镜面反射与视觉相关。

需要注意的是,镜面光与其他类型的光相比,计算量要大得多,Direct3D默认情况是把镜面反射关起来的。如果我们想启用镜面反射的话,用下面的代

    
最新技术文章:
▪error while loading shared libraries的解決方法    ▪版本控制的极佳实践    ▪安装多个jdk,多个tomcat版本的冲突问题
▪简单选择排序算法    ▪国外 Android资源大集合 和个人学习android收藏    ▪.NET MVC 给loading数据加 ajax 等待loading效果
▪http代理工作原理(3)    ▪关注细节-TWaver Android    ▪Spring怎样把Bean实例暴露出来?
▪java写入excel2007的操作    ▪http代理工作原理(1)    ▪浅谈三层架构
▪http代理工作原理(2)    ▪解析三层架构……如何分层?    ▪linux PS命令
▪secureMRT Linux命令汉字出现乱码    ▪把C++类成员方法直接作为线程回调函数    ▪weak-and算法原理演示(wand)
▪53个要点提高PHP编程效率    ▪linux僵尸进程    ▪java 序列化到mysql数据库中
▪利用ndk编译ffmpeg    ▪活用CSS巧妙解决超长文本内容显示问题    ▪通过DBMS_RANDOM得到随机
▪CodeSmith 使用教程(8): CodeTemplate对象    ▪android4.0 进程回收机制    ▪仿天猫首页-产品分类
▪从Samples中入门IOS开发(四)------ 基于socket的...    ▪工作趣事 之 重装服务器后的网站不能正常访...    ▪java序列化学习笔记
▪Office 2010下VBA Addressof的应用    ▪一起来学ASP.NET Ajax(二)之初识ASP.NET Ajax    ▪更改CentOS yum 源为163的源
▪ORACLE 常用表达式    ▪记录一下,AS3反射功能的实现方法    ▪u盘文件系统问题
▪java设计模式-观察者模式初探    ▪MANIFEST.MF格式总结    ▪Android 4.2 Wifi Display核心分析 (一)
▪Perl 正则表达式 记忆方法    ▪.NET MVC 给loading数据加 ajax 等待laoding效果    ▪java 类之访问权限
▪android Content Provider详解九    ▪简单的图片无缝滚动效果    ▪required artifact is missing. iis7站长之家
▪sharepoint 2010 自定义列表启用版本记录控制 如...    ▪解决UIScrollView截获touch事件的一个极其简单有...    ▪Chain of Responsibility -- 责任链模式
▪运行skyeye缺少libbfd-2.18.50.0.2.20071001.so问题    ▪sharepoint 2010 使用sharepoint脚本STSNavigate方法实...    ▪让javascript显原型!
▪kohana基本安装配置    ▪MVVM开发模式实例解析    ▪sharepoint 2010 设置pdf文件在浏览器中访问
▪spring+hibernate+事务    ▪MyEclipse中文乱码,编码格式设置,文件编码格...    ▪struts+spring+hibernate用jquery实现数据分页异步加...
▪windows平台c++开发"麻烦"总结    ▪Android Wifi几点    ▪Myeclipse中JDBC连接池的配置
▪优化后的冒泡排序算法    ▪elasticsearch RESTful搜索引擎-(java jest 使用[入门])...    ▪MyEclipse下安装SVN插件SubEclipse的方法
▪100个windows平台C++开发错误之七编程    ▪串口转以太网模块WIZ140SR/WIZ145SR 数据手册(版...    ▪初识XML(三)Schema
▪Deep Copy VS Shallow Copy    ▪iphone游戏开发之cocos2d (七) 自定义精灵类,实...    ▪100个windows平台C++开发错误之八编程
▪C++程序的内存布局    ▪将不确定变为确定系列~Linq的批量操作靠的住...    ▪DIV始终保持在浏览器中央,兼容各浏览器版本
▪Activity生命周期管理之三——Stopping或者Restarti...    ▪《C语言参悟之旅》-读书笔记(八)    ▪C++函数参数小结
▪android Content Provider详解九    ▪简单的图片无缝滚动效果    ▪required artifact is missing.
▪c++编程风格----读书笔记(1)    ▪codeforces round 160    ▪【Visual C++】游戏开发笔记四十 浅墨DirectX教程...
▪【D3D11游戏编程】学习笔记十八:模板缓冲区...    ▪codeforces 70D 动态凸包    ▪c++编程风格----读书笔记(2)
▪Android窗口管理服务WindowManagerService计算Activity...    ▪keytool 错误: java.io.FileNotFoundException: MyAndroidKey....    ▪《HTTP权威指南》读书笔记---缓存
▪markdown    ▪[设计模式]总结    ▪网站用户行为分析在用户市场领域的应用
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3