首先,渲染到纹理是D3D中的一项高级技术。一方面,它很简单,另一方面它很强大并能产生很多特殊效果。 比如说发光效果,环境映射,阴影映射,景深效果,都可以通过它来实现。渲染到纹理只是渲染到表面的一个延伸。我们只需对得到的纹理图像进行后处理即可。首先,我们要创造一个纹理,并且做好一些防范措施。第二步我们就可以把适当的场景渲染到我们创建的纹理上了。然后,我们把这个纹理用在最后的渲染上。
GeForce 6系列图形芯片支持的PixelShader 3.0中还支持一种较新的技术,我们要额外放在这一页来简要介绍。这就是多渲染目标(MRT)技术。
这种技术的作用就是将每像素的数据保存到不同的缓冲区当中。这样的好处就是这些缓冲区数据由此可以成为照片级光照效果着色器的参数。
在这种方法的帮助下,光照可以在所有几何图形被渲染以后最后进行应用,不再需要进行多步的渲染。因而这种技术也可以被称为延期着色(Deferred Shading)。存储在这种类型的表面中的数据可以包括位置、法线、颜色以及材质的信息。
我们来看一个MRT技术用于产生一个高动态范围的场景的实例。

第一个渲染步骤
在第一个渲染步骤,开发者创造出3个输出缓冲区,这包括:1个颜色的贴图、1个法线的贴图和1个深度的贴图。

第二个渲染步骤
在第二个步骤,使用法线和深度贴图结合光照条件计算出光照。然后,场景在带有颜色贴图的情况下被精确地照明。

第三个渲染步骤
最后在第三个步骤中,超过0~1范围的超高亮度的光线值被带入场景中,计算包含高亮度像素附近的像素的发光。这个步骤产生出难以置信的发光效果。
posted @ 2008-12-01 23:41 炮灰九段 阅读(1159) 评论(0)
编辑
这几天在看Intel公司刚刚收购开放下载的havok物理引擎,有几点感受。为了研究havok,多么猥琐阴险狡诈的招都被我使了出来,在google上搜过n个正则关键字,去过专业的物理研究论坛,去了havok的官方网站,去了Inter的havok论坛。最后没找到多少资料,没找到一个小例子。所以只得再havok SDKs的Doc和Demo下面逛,看英文,猜代码意图。浑浑噩噩的过了两天。
Havok的demo看过的肯定知道,框架做得相当复杂和诡异,其实并不适合去学习。The framework of the demos is very complex and esoteric. I do not want to understand these complex framework, Because I have a practical application in my framework, companies have the framework of the company, no one will want to make their own framework replaced for a physical engine.这是我发在havok论坛上的帖子。
这也难怪,havok引擎刚刚开放下载,国内应用的都少,教程更是别提。我这几天算是过得比较痛苦,写个简单的入门文档,希望抛砖引玉,帮大家简单入入门,完全没有误人子弟的意思,大家别拍我~ ~我做的主要是havok的刚体碰撞。简单的20 * 20 的正方体自由下落在一平面上。
首先,关于Havok的几个简单的物理概念:
hkpWorld: havok的物理世界场景 场景有其自己的属性,如万有引力等,每个havok的仿真场景可以有一个或者多个hkpWorld的实例。
hkpRigidBody: havok的刚体,刚体可以有自己的运动属性,并能通过setMotionType来设置修改。
hkVisualDebugger: 关于havok的一个很好的调试工具
下面是整个程序的简单代码,没有用图形库输出图形,可以通过havok自带的工具VisualDebugger工具来查看刚体。省略了部分内存方面的代码,我也不是很明白。
int main(int argc, const char** argv)
{
{
// 创建physics world 通过填充hkpWorldCinfo
hkpWorld* physicsWorld;
{
// 创建物理世界:
hkpWorldCinfo worldInfo;
worldInfo.m_simulationType = hkpWorldCinfo::SIMULATION_TYPE_MULTITHREADED;
worldInfo.m_gravity.set(0.0f, -9.8f, 0.0f);
physicsWorld = new hkpWorld(worldInfo);
}
physicsWorld->markForWrite();
{
hkpAgentRegisterUtil::registerAllAgents( physicsWorld->getCollisionDispatcher() );
}
// 在这里创建我们的刚体模拟
setupPhysics( physicsWorld );
// 初始化VisualDebugger工具
hkVisualDebugger* vdb = setupVisualDebugger(context);
hkReal timestep = 1.f / 60.f;
int numSteps = int(60.f / timestep);
for ( int i = 0; i < numSteps; ++i )
{
// 可以得到刚体的一些实时信息,借助图形库进行渲染
hkVector4 pos = g_ball->getPosition();
printf("[%f,%f,%f]"n", pos(0), pos(1), pos(2));
}
hkBaseSystem::quit();
return 0;
}
void setupPhysics(hkpWorld* physicsWorld)
{
// 创建地面的 静态刚体
{
hkpRigidBodyCinfo boxInfo;
hkVector4 boxSize(5.0f, 0.5f , 5.0f);
hkpBoxShape* boxShape = new hkpBoxShape(boxSize);
boxInfo.m_shape = boxShape;
boxInfo.m_motionType = hkpMotion::MOTION_FIXED;
boxInfo.m_position.set(0.0f, 0.0f, 0.0f);
boxInfo.m_restitution = 0.9f;
hkpRigidBody* floor = new hkpRigidBody(boxInfo);
boxShape->removeReference();
g_ball = floor;
physicsWorld->addEntity(floor);
floor->removeReference();
}
// 创建 20 * 20 的盒子
const hkReal boxDim = 0.2f; // This is the size of the cube side of the box
const hkReal boxRadius = boxDim * 0.01f; // 盒子的角度 这个有问题 原来这个是大小
const hkReal gapx = boxDim * 0.05f; // This is the gap betwen boxes 间距是盒子大小的多少比率
const hkReal gapy = boxRadius;
const hkReal heightOffGround = 10.0f; // This is the height of the pyramid off the gound
int pyramidSize = 20; // This is the number of boxes along the base (also vertically)
// 长方体的长宽
hkReal extendedBoxDimX = boxDim + gapx;
//hkReal extendedBoxDimY = boxDim + gapy;
hkReal extendedBoxDimZ = boxDim + gapx;
hkVector4 startPos( 0.0f , heightOffGround + gapy + boxDim * 0.5f, 0.0f);
// Build pyramid 构建
{
hkVector4 boxRadii(boxDim *.5f, boxDim *.5f, boxDim *.5f);
hkpShape* boxShape = new hkpBoxShape( boxRadii , boxRadius );
// 变成横向的一块下来 20 * 20的盒子
for(int i=0; i<pyramidSize; i++)
{
// This constructs a row, from left to right 从左到右
hkVector4 start(0, 0, extendedBoxDimZ * i);
for(int j=0; j< pyramidSize; j++)
{
hkVector4 boxPos(start);
hkVector4 shift(j * extendedBoxDimX, 0.0f, 0.0f);
boxPos.setAdd4(boxPos, shift);
boxPos.setAdd4(boxPos, startPos);
hkpRigidBodyCinfo boxInfo;
//盒子的质量
boxInfo.m_mass = 100.0f;
// calculate the correct inertia 惯性与质量有关
hkReal d = boxInfo.m_mass * boxDim * boxDim / 6.0f;
// for small boxes increase inertia slightly
if ( boxRadius < 0.1f )
{
d *= 2.0f;
if ( boxRadius < 0.03f )
{
d *= 2.0f;
}
}
boxInfo.m_inertiaTensor.setDiagonal(d,d,d);
boxInfo.m_shape = boxShape;
boxInfo.m_motionType = hkpMotion::MOTION_DYNAMIC;
boxInfo.m_position = boxPos;
boxInfo.m_restitution = 0.5f; // 表面的弹力
boxInfo.m_friction = 0.6f; // 表面的摩擦
boxInfo.m_solverDeactivation = hkpRigidBodyCinfo::SOLVER_DEACTIVATION_MAX;
hkpRigidBody* boxRigidBody = new hkpRigidBody(boxInfo);
//将所有的刚体添加到世界中
physicsWorld->addEntity( boxRigidBody );
boxRigidBody->removeReference();
}
}
boxShape->removeReference();
}
}
我们只要在自己的代码中调用Havok API构建抽象的物理世界,抽象的物体,即给出物理世界的数据,就能直接通过hkVisualDebugger接口的socket连接发送世界数据到HavokVisualDebugger宿主程序,并在其可视化物理场景视图中显示出来。以下是在工具下的两张截图:

在demo框架中:

程序的可运行代码:
http://files.cnblogs.com/hellohuan/ConsoleMain.rar
posted @ 2008-09-03 22:19 炮灰九段 阅读(3646) 评论(21)
编辑