本例包含的内容有:
- normal map
- Dot3BitmapMaterial
转载请注明出处:nooon.cnblogs.com
本例子将讲解如何使用normap map 和Dot3BitmapMaterial做一堵涂鸦墙。
本例会用到的图片:
normalmap.png ,记录墙面每点的法线信息(稍后解释)
doodle.jpg 用作墙体上的涂鸦内容。
看最终效果:点此观看(拖动鼠标,旋转摄像机;不同角度看看Dot3BitmapMaterial对光反射的变化。同时看墙后方的PhongBitmapMaterial类位图材质)。
先看看什么是normal map。
normal map ,可以帮助低面模型(面数少的模型)生成更为现实的效果。比如在本例中,涂鸦墙墙体只是一个矩形,矩形每个面都是平整的。不会有砖体,这里我们就是借助上面的normalmap.png这张图片做normal map生成墙表面凹凸不平的效果!如果不用Normal Map 的话,我们当然也可以用3D软件做出一个有凹凸不平的效果的墙体(高面模型),然后用BitmapMaterial对模型贴图。但很显然这样的模型面数多,渲染时会拖垮电脑。现在3D游戏都会用normal map 让3D让模型更贴近真实。
normal map之所以有此之能是因为normal map能记录物体表面各点的位置信息。normal map实质是一张没什么特别的RGB图像,但这样的RGB图片的每点的R、G、B值是用来记录该点的空间位置信息的(分别对应X、Y、Z)。这样3D引擎就可以根据RGB值 计算使用Normalmap的模型的表面每个小曲面的垂线方向即法线,从而计算出模型表面各点对光的反射方向。所以normal map 称之法线图。
更多内容看:http://www.blacksmith-studios.dk/projects/downloads/bumpmapping_using_cg.php
如何的到normal map 呢?
可以到网上找。
当然可以自个做,3D软件大多可以,不过这里介绍一个很有趣的方法,看http://zarria.net/nrmphoto/nrmphoto.html
最后按惯例加上本例子的源代码:
1: package
2: {
3: import away3d.cameras.HoverCamera3D;
4: import away3d.containers.View3D;
5: import away3d.core.utils.Cast;
6: import away3d.lights.DirectionalLight3D;
7: import away3d.materials.PhongBitmapMaterial;
8: import away3d.materials.Dot3BitmapMaterial;
9: import away3d.primitives.Cube;
10:
11: import flash.display.Sprite;
12: import flash.events.Event;
13: import flash.events.MouseEvent;
14: [SWF(width="500",height="500",frameRate="30", backgroundColor="#000000")]
15: public class normalMapping extends Sprite
16: {
17: private var view:View3D;
18: private var cam:HoverCamera3D;
19: private var cube:Cube;
20: private var doodle:Dot3BitmapMaterial;
21: private var originalmap:PhongBitmapMaterial;
22: private var light:DirectionalLight3D;
23:
24: private var mouseDown:Boolean;
25: private var lastMouseX:Number;
26: private var lastMouseY:Number;
27: private var lastPanangle:Number;
28: private var lastTiltangle:Number;
29: private var cameraSpeed:Number;
30:
31: [Embed(source="resources/doodle.jpg")] private var doodleImage:Class;
32: [Embed(source="resources/normalmap.png")] private var normalmapImage:Class;
33: public function normalMapping()
34: {
35: //初始3D世界(摄像机、视口。。)
36: init3D();
37: //创建场景里的3D模型(建一立方体用作涂鸦的墙体)
38: createSce();
39: //添加侦听器(监测鼠标拖动,如拖动则旋转摄像机;并且每帧渲染)
40: addEventListener(Event.ENTER_FRAME,update);
41: stage.addEventListener(MouseEvent.MOUSE_DOWN,m_down_h);
42: stage.addEventListener(MouseEvent.MOUSE_UP,m_up_h);
43: }
44: private function init3D():void
45: {
46: cam=new HoverCamera3D();
47: cam.distance=1200;
48: cam.panangle=cam.targetpanangle=30;
49: cam.tiltangle=cam.targettiltangle=0;
50: cam.mintiltangle=-90;
51: view=new View3D({camera:cam,x:250,y:250});
52: addChild(view);
53: };
54: private function createSce():void
55: {
56: //控制摄像机旋转速度
57: cameraSpeed=.3;
58: // 创建直线光源,Dot3BitmapMaterial需要光源。没有光源与普通的BitmapMaterial无异
59: var light:DirectionalLight3D = new DirectionalLight3D({brightness:1,ambient:0.25, diffuse:0.75, specular:0.9});
60: light.x = 5000;
61: light.z = -50000;
62: light.y = 1000;
63: view.scene.addChild(light);
64: //新建originalmap,是PhongBitmapMaterial类型,用作墙后方贴图
65: originalmap=new PhongBitmapMaterial(Cast.bitmap(new doodleImage()));
66: //新建doodle,是Dot3BitmapMaterial类型,用作墙前方贴图
67: doodle=new Dot3BitmapMaterial(Cast.bitmap(new doodleImage()),Cast.bitmap(new normalmapImage()),{smooth:true, precision:6});
68: //新建一立方体,用作墙体
69: cube=new Cube({600,height:300,depth:20,segmentsW:2,segmentsH:2});
70: //分别为墙体前后方贴图
71: cube.cubeMaterials.front=doodle;
72: cube.cubeMaterials.back=originalmap;
73:
74: view.scene.addChild(cube);
75: };
76: private function update(e:Event):void
77: {
78: if(mouseDown)
79: {
80: cam.targetpanangle=cameraSpeed*(stage.mouseX-lastMouseX)+lastPanangle;
81: cam.targettiltangle=cameraSpeed*(stage.mouseY-lastMouseY)+lastTiltangle;
82: };
83: cam.hover();
84: view.render();
85: };
86: private function m_down_h(e:MouseEvent):void
87: {
88: mouseDown=true;
89: lastMouseX=stage.mouseX;
90: lastMouseY=stage.mouseY;
91: lastPanangle=cam.targetpanangle;
92: lastTiltangle=cam.targettiltangle;
93: };
94: private function m_up_h(e:MouseEvent):void
95: {
96: mouseDown=false;
97: };
98: }
99: }