[away3D]Globe Materials Tutorial
This tutorial will guide you step by step in the creation of a realistic Planet Earth scene,focusing on materials and shaders in Away3D 4.x. User Level Prerequisite knowledge: Required tools Sources Downloads Author Contents:
IntroductionAway3D is a powerful 3D engine that abstracts us from the powerful,yet low level Stage3D API. In just a few lines of code,we can accomplish advanced scenes and let the engine take care of the rest. Such is the case for advanced material usage. In this tutorial we will take a quick tour along Away3D’s material system in trying to emulate a scene depicting our beautiful planet Earth,floating ominously in deep space. We will start from simple geometries and materials,and little by little get more and more involved into the engine’s powerful material system. So let’s get started,enjoy the ride! ? Setting Up the SceneFirst things first,lets set up the geometries of the scene. We will use spheres to create the Earth and the Moon,group them appropriately in order to be able to simulate axis and orbit rotations,and texture them with basic materials. Listing 1 shows our basic set up: ? ? Listing 1 ( click image to launch ). Basic Earth scene with grouped transforms and non-lit texture materials.Full source code. For each celestial body,we’ve reproduced the same sequence of steps. We’ve created atexture,a geometry,wrapped them in amesh object,added it to a containerand added the container to the scene. Lets quickly review each of these steps. Materials:We are embedding jpg images and using Away3D’s Cast utility class to create var moonSurfaceTexture:BitmapTexture = Cast.bitmapTexture( MoonSurfaceDiffuse ); var moonSurfaceMaterial:TextureMaterial = new TextureMaterial( moonSurfaceTexture ); Geometries:The celestial bodies are represented by var moonSurfaceGeometry:SphereGeometry = new SphereGeometry( 50,100,50 ); Meshes:Geometries combined with materials conform mesh objects,which gather the necessary functionality for actual rendering. The geometry determines the object’s shape,and the material determines the object’sshader,or how it will be drawn to screen. Meshes also wrap other objects,such astransforms. These are another essential part of the 3D rendering pipeline and allow us to position,scale and rotate our objects in the scene. Notice how we altered the x coordinate of the moon body. var moonSurfaceMesh:Mesh = new Mesh( moonSurfaceGeometry,moonSurfaceMaterial ); Containers:Another object that owns transforms is _moon = new ObjectContainer3D(); _moon.rotationY = rand( 0,360 ); _view.scene.addChild( _moon ); moonSurfaceMesh.x = 1000; _moon.addChild( moonSurfaceMesh ); Enriching the SceneOur scene still looks pretty bare and there are several aspects we could focus on to make it look better. We could work on the object’s materials,and we will,but something we could at look at first is adding more elements to our scene in order to populate it with a bit of eye-candy. We will add the Sun,some stars,and deep space graphics to our scene. Lets look at the result first,and then analyze what we’ve done. ? ? Listing 2. The basic scene with Sprite3D’s to represent the Sun and stars and a SkyBox to represent deep space.Full source code. We’ve compacted the code from the last listing. As we advance in this tutorial,our code is going to get more and more involved,so we will want to have previously studied elements in the source out of our current main focus. Our listing has three new methods,one that creates the sun,another that creates a starfield and another one that creates our deep space graphics using a skybox. Sprite3DThe sun and the stars use Notice the new method var bitmapData:BitmapData = blackToTransparent( Cast.bitmapData( StarTexture ) ); var starMaterial:TextureMaterial = new TextureMaterial( new BitmapTexture( bitmapData ) ); starMaterial.alphaBlending = true; The star field is layed out using a for loop that creates each billboard,spits out random spherical coordinates,calculates its cartesian coordinates equivalent and assigns it to the position of each star. We used spherical coordinates here because they tend to be easier for laying out things in a spherical distribution. You can read more about this system and its useshere. SkyBoxAnother commonly used trick we’ve used here is the skybox. This is simply an infinitely large cube with images attached to its inner faces,ideal for simulating environmental elements that are sufficiently far away do not require parallax or perspective effects. They are so far away,that moving around won’t actually make them look very different. For this,we embed 6 images,one for each face of the cube and wrap them around a // Cube texture. var cubeTexture:BitmapCubeTexture = new BitmapCubeTexture( Cast.bitmapData( PosX ),Cast.bitmapData( NegX ),Cast.bitmapData( PosY ),Cast.bitmapData( NegY ),Cast.bitmapData( PosZ ),Cast.bitmapData( NegZ ) ); // Skybox geometry. var skyBox:SkyBox = new SkyBox( cubeTexture ); _view.scene.addChild( skyBox ); Great. We now have a rich scene populated with many objects. Let’s see what we can do next. ? LightsNow that we have sufficient objects in our scene to make it a bit richer,its time to make or celestial bodies look a little more realistic. A fundamental aspect of 3D graphics that that we have ignored so far is lighting. Light sources and light enabled materials shade objects depending on the configuration of the light sources and materials. This provides a powerful enhancement to our scene. Let’s see how it looks like when applied. ? ? Listing 3. Usage of lights. Full source code. We haven’t changed much in this listing,just added a point light,adjusted some settings on it and on the materials,and associated the lights with the material’s Phong ShadingShading via Stage3D uses a rather complicated shading language called AGAL. It looks almost like assembler and is quite hard to code. It allows us to produce shader programs which can be uploaded to the GPU and,and together with geometries,textures,transforms,etc,define how things are drawn to screen. Fortunately,Away3D wraps all these complexities into an intuitive material system where we can control shading models by simply manipulating parameters and properties. Here,we’ve touched on the light source’s ambient,diffuse and specular values and the materials’ gloss values. The ambient property of the light illuminates objects from no specific origin or direction,simulating a scene’s random reflectance with no specifically directed shading. In this case,we’ve set it to 1 so that the dark side of our celestial bodies are not completely in darkness. The diffuse property affects the amount in which incident light on the geometry’s normals illuminates it. We’ve set it to 2 to exaggerate the difference between the lit areas and the ones in darkness. The specular property of the light affects how much the reflecting highlight (depending on the incident direction of the light),the surface normals and the view angle light the surface. Finally,the gloss property of the material determines how spread out the specular highlight is. Try different values for each,you’ll get a better glimpse of what each does if you do so. Or if you want to dwell deeper into the fantastic world of shading,this is a good place to start. It’s GLSL instead of AGAL,but the concepts are what matter. One thing to note and that is sometimes confusing is that materials,as lights,share some of the ambient,diffuse and specular properties. These values get combined in the shader so you can have,for instance,different ambient illumination on a set of objects affected by the same light source. Additional MapsLighting did improve the look of our celestial bodies didn’t it? There is still a lot more we can do to enhance them though. ? ? Figure 1. Multiple maps used for shading of the globe. In order,diffuse map,normal map,specular map and ambient map.
The following listing implements all these maps. ? ? Listing 4. Usage of additional maps for shading of the Earth. Full source code. As you can see,these rather advanced shading topics are absurdly easy to implement on Away3D. The most significant change in the listing is the addition of the following lines,which simply assign the mentioned maps into the Earth’s earthMaterial.normalMap = Cast.bitmapTexture( EarthSurfaceNormals ); earthMaterial.specularMap = Cast.bitmapTexture( EarthSurfaceSpecular ); earthMaterial.ambientTexture = Cast.bitmapTexture( EarthSurfaceNight ); Additionally,notice that we have tweaked illumination values of each of the bodies independently,in order to achieve the desired aspect of each one. ? Fresnel Specular MethodTo be honest,our specular highlights on the celestial bodies still don’t look very realistic. They do make things look more interesting,but they would truly be more appropriate for billiard balls than for celestial bodies. Planets aren’t that shiny. Also notice an undesired specular highlight trail off when looking at the bodies from behind. Lets change the way our To improve our highlights,we will use a ? ? Listing 5. Fresnel specular method implemented on the surface of the Earth and the Moon.Full source code. Once again,the implementation in code is very simple. We simply initialize var earthFresnelSpecularMethod:FresnelSpecularMethod = new FresnelSpecularMethod( true ); earthFresnelSpecularMethod.fresnelPower = 1; earthFresnelSpecularMethod.normalReflectance = 0.1; earthFresnelSpecularMethod.shadingModel = SpecularShadingModel.PHONG; //... earthMaterial.specularMethod = earthFresnelSpecularMethod; Adding CloudsThe planet Earth contains a rich atmosphere and our simulation would become so much richer if we considered it. We will do this first by adding a slightly bigger transparent sphere to the earth container with a texture of clouds. The implementation is naive in a sort of way,but impressively effective: ? ? Listing 6. Representing clouds using a slightly larger,transparent sphere. Full source code. You may be asking yourself why didn’t we merge the earth surface and sky diffuse maps,or even layer the materials in some way? This would definitely save us a lot of triangles since using a new sphere certainly adds a lot of them. Well,we can afford them in this scenario,plus,if we merged the maps together,the additional maps we added to the surface would affect the clouds,and this would definitely be unwanted. Instead,we give it its own geometry and material and completely ignore specular highlights on the clouds by setting its specular property to zero. var bitmapData:BitmapData = blackToTransparent( Cast.bitmapData( EarthSkyDiffuse ) ); var earthCloudMaterial:TextureMaterial = new TextureMaterial( new BitmapTexture( bitmapData ) ); earthCloudMaterial.alphaBlending = true; earthCloudMaterial.lightPicker = _lightPicker; earthCloudMaterial.specular = 0; Cool! This is starting to look more realistic. ? Adding an AtmosphereLet’s continue with the simulation of our atmosphere. This time,we’re going to try to simulate a thin layer of gas around the Earth’s surface. We’re going to do this by using a similar trick to the one we used for the clouds. That is,a slightly larger sphere,tweaked to generate the desired effect. In this case,we won’t be mapping a texture onto it,we just want a fading blueish color,so we’re going to use a ? ? Listing 7. Full source code. The bit of code that inverts the sphere is: earthAtmosphere.scaleX = -1; We could have inverted any of the 2 other axis,but having arbitrarily chosen the X axis,the result is the same; the sphere’s normals point into it’s center instead of away from it. As a result the faces that would be normally pointing towards us,i.e. on top of the Earth’s surface,are clipped by back face culling,and the ones that would normally be clipped are visible. Hence we see only triangles that are on the opposite hemisphere of the globe and not occluded by the other spheres. Exactly what we were looking for. The construction of the material for this geometry is very simple. Two things to note here though. First,we are applying lighting to the sphere so we don’t see the atmosphere on the dark face of the planet,and secondly,we use var atmosphereMaterial:ColorMaterial = new ColorMaterial( 0x1671cc ); atmosphereMaterial.blendMode = BlendMode.ADD; atmosphereMaterial.lightPicker = _lightPicker; atmosphereMaterial.gloss = 5; Right… this is sort of what we wanted,but it doesn’t look to good does it? The results makes the atmosphere a *bit* to rough on the edges. Lets see how we can improve this in the next section. ? A More Advanced AtmosphereIn order to make our atmosphere more realistic,we need to make it fade out radially from the center of the sphere. In reality,the atmosphere’s gases are denser nearer to the surface of the planet,and gradually become less and less dense as the distance from the surface increases. This is a pretty particular requirement we will be making to our ? ? Listing 8. Using a custom shader for our atmosphere. Full source code. The main part of the code is the usage of function myModulatingMethod( vo:MethodVO,t:ShaderRegisterElement,regCache:ShaderRegisterCache ):String Basically,we receive information on previous parts of the shader,and are expected to return the bit we are altering. The private function modulateDiffuseMethod( vo:MethodVO,regCache:ShaderRegisterCache ):String {? ?var viewDirFragmentReg:ShaderRegisterElement = _atmosphereDiffuseMethod.viewDirFragmentReg; ?var normalFragmentReg:ShaderRegisterElement = _atmosphereDiffuseMethod.normalFragmentReg; ?var temp:ShaderRegisterElement = regCache.getFreeFragmentSingleTemp(); ?regCache.addFragmentTempUsages( temp,1 ); ?var code:String = "dp3 " + temp + "," + viewDirFragmentReg + ".xyz," + normalFragmentReg + ".xyzn" + ?"mul " + temp + "," + temp + "," + temp + "n" +??? ?"mul " + t + ".w," + t + ".w," + temp + "n"; ?regCache.removeFragmentTempUsage( temp ); ?return code; } First,we ask the register cache for a temporary register onto which we store the projection of the current fragment to the viewer vector onto the normal vector of the fragment. This value is then squared. Such projection will be larger as the view and normal vectors become aligned and smaller as they tend to be perpendicular to each other. If we think about the normals of our sphere,such projection will be larger near the center,and smaller near the edges of the sphere,to completely zero at it’s edges. We then multiply this value by the w component of our incoming t registry element which contains diffuse lighting intensity depending on the position of the light and the surface normal,hence taking into account the previously calculated diffuse phong shading. By storing the result in the w component of such register,we are affecting the alpha component of the current color,hence making areas near the edge of the sphere more transparent. Pheww,exactly what we wanted. Post ProcessingOf course,we could continue enhancing our experiment indefinitely,but for the purpose of this tutorial,we are going to do just one more thing to it: Pimp up the graphics with a bit of post processing. That is,we won’t be working on the scene itself anymore,but will be adding a few rendering effects on top of our current result. We will add a bloom effect as a GPU ? ? Listing 9. Postprocessing with bloom and lens flare effects. Full source code. Ain’t it cool? Let’s have a look at how each of the effects are accomplished. Bloom EffectAway3D offers an awesome,extensible post processing kit via the filters package. These effects can be considered to be shaders,but instead of acting on independent materials and regular 3D geometry,work on the final output of the scene’s rendering and drawing the result on a quad that perfectly fits the screen. This gives us the possibility of using the GPU’s vast processing power for global scene rendering effects. In this case,we are using a bloom filter. You can read about ithere. Basically,a bloom filter emulates how lenses experience film over exposure by very bright light sources. On our case,we use it when looking directly at the sun. To set up filters in Away3D we simply initialize the objects and set them as the view’s _bloomFilter = new BloomFilter3D( 2,2,0.5,4 ); _view.filters3d = [ _bloomFilter ];
Then,at runtime,we evaluate the strength ( exposure parameter ) of the filter by calculating ‘how much in front of the sun’ the viewer is. This is done in the Lens Flare EffectThis is a classical 2D,regular Flash display API,lens flare effect. We simply load a few bitmaps,place them on top of our view and align them to produce the desired effect. What’s interesting is how we evaluate the position and visibility of the flares in the That looks good doesn’t it? ConclusionThis concludes our little Planet Earth simulation. We started with a very basic scene in terms of geometry and shading and step by step enhanced the way it looked. First,we used a sky box and billboards to enrich the scene,and then we meticulously focused on enhancing the materials of the Earth. This even got us into coding a bit of AGAL. With all this,you should now be a bit more familiar with Away3D’s powerful and flexible material system,which allows us to produce some pretty stunning visual effects. Surely,you could enhance our experiment greatly,since we’ve kept things as simple as possible here. You could move on though,since you have the full power of the GPU to accomplish whatever effect is in your creative mind,and Away3D makes it very easy for us to make these ideas happen. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |