SceneManager - LiXizhi/NPLRuntime GitHub Wiki
3D Scene
There are a number of 3D objects which one can create via scripting API, such as mesh, physics mesh, skybox, camera, biped character, light, particles, containers, overlays, heightmap terrain, blocks, animations, shaders, 3D assets, etc.
Triangle Limitations
One can set the maximum number of total triangles of animated characters in the 3d scene per frame, like below
ParaScene.GetAttributeObject():SetField("MaxCharTriangles", 150000);
Faraway objects exceeding this value will be skipped during rendering. Another way of reducing triangle count is via level-of-detail (LOD) when loading mesh or characters. Currently, one must manually provide all LOD of mesh when loading a 3d file.
Rendering Pipeline
Currently, all fixed function, shaders, and deferred shading share the same predefined rendering pipelines. The render order can be partially affected by RenderImportance, RenderOrder, several Shader files property. But in general, it is a fixed general purpose rendering pipeline suitable in most situations.
The source code of the pipeline is hard-coded in SceneObject.cpp's AdvanceScene() function.
Here is what it does:
For each active viewport, we do the following:
- traverse the scene and quad-tree tile manager and call
PrepareRender()for each visible scene object, which will insert the object into a number of predefined global render queues. PIPELINE_3D_SCENE- draw
MiniSceneGraphwith local cameras and render into textures - draw owner-draw objects like render targets.
- draw all m_mirrorSurfaces into local textures
- tesselate
global terrainaccording to current camera - render shadow map for shadow casters queue, and other global object like blocks that cast shadows.
- draw block engine multiframe world texture
- render
global terrain - draw opaque blocks in block engine
- draw alpha-test enabled blocks in block engine
- draw static meshes in big mesh queue from front to back
- draw static meshes in small mesh queue from back to front
- draw sprite objects queue
- draw animated characters queue
- render selection queue
- render current sky object
- draw block engine multiframe world texture on sky
- draw missile object queue
- draw block engine water reflection pass
- block engine deferred shading post processing for opaque objects
- draw batched transparent particles
- block engine draw all alpha blended blocks
- draw transparent animated characters in transparent biped queue
- block engine deferred shading post processing for alpha blended object
- draw block engine deferred lights
- draw all head-on display
- draw simulated global ocean surface
- draw transparent static mesh objects in transparent mesh queue
- draw transparent triangle face groups
- draw objects in
post render queue - draw particle systems
- invoke custom post rendering shaders in NPL script for 3d scene
- draw water waves
- draw helpers for physics world debugging
- draw helpers for bounding boxes of scene objects
- draw portal system
- draw overlays
- draw
PIPELINE_UI- render all visible GUI objects by traversing the
GUIRootobject.
- render all visible GUI objects by traversing the
PIPELINE_POST_UI_3D_SCENE- only
MiniSceneGraphwhoseGetRenderPipelineOrder() == PIPELINE_POST_UI_3D_SCENEwill be rendered in this pipeline
- only
PIPELINE_COLOR_PICKING
Pipeline customization
RenderImportanceproperty of ParaObject only affects render order in a given queue.RenderOrderproperty of ParaObject will affect which queue the object goes into, as well as the order inside the queue. However, onlyRenderOrder>100is used to insert objects topost render queue.
For example, the following code will ensure the two objects are rendered last and ztest is disabled.
local asset = ParaAsset.LoadStaticMesh("","model/common/editor/z.x")
local obj = ParaScene.CreateMeshPhysicsObject("blueprint_center", asset, 1,1,1, false, "1,0,0,0,1,0,0,0,1,0,0,0");
obj:SetPosition(ParaScene.GetPlayer():GetPosition());
obj:SetField("progress",1);
obj:GetEffectParamBlock():SetBoolean("ztest", false);
obj:SetField("RenderOrder", 101)
ParaScene.Attach(obj);
local player = ParaScene.CreateCharacter ("MyPlayer1", ParaAsset.LoadParaX("","character/v3/Elf/Female/ElfFemale.x"), "", true, 0.35, 0, 1.0);
local x,y,z = ParaScene.GetPlayer():GetPosition()
player:SetPosition(x+1,y,z);
player:SetField("RenderOrder", 100)
player:GetEffectParamBlock():SetBoolean("ztest", false);
ParaScene.Attach(player);
Mouse Ray Picking
Use ParaScene.MousePick.
/**
* Pick scene object at the current mouse cursor position.
* pick the smallest intersected object which is un-occluded by any objects. Object A is considered occluded by object B only if
* (1) both A and B intersect with the hit ray.
* (2) both A and B do not intersect with each other.
* (3) B is in front of A, with regard to the ray origin.
*
* this function will ray-pick any loaded scene object(biped & mesh, but excluding the terrain) using their oriented bounding box.
* a filter function may be provided to further filter selected object.
* this function will transform all objects to the near-camera coordinate system.
* This will remove some floating point inaccuracy near the camera position. Hence this function is most suitable for
* testing object near the camera eye position. This function does not rely on the physics engine to perform ray-picking.
* @param x: screen position relative to the render target.
* @param y: screen position relative to the render target.
* @params fMaxDistance: the longest distance from the ray origin to check for collision. If the value is 0 or negative, the view culling radius is used
* as the fMaxDistance.
* @param sFnctFilter: it can be any of the following string or a number string
* "mesh": mesh any mesh object in the scene. Usually for selection during scene editing.
* "cmesh": mesh object that is clickable (associated with scripts). Usually for game playing.
* "notplayer": any object in the scene except for the current player. Usually for selection during scene editing.
* "": any object in the scene except. Usually for selection during scene editing.
* "light": only pick light objects
* "biped": any character objects :local or global.
* "anyobject": any objects, including mesh and characters. but not including helper objects, such as light.
* "global": all global objects, such as global character and mesh. This is usually for game mode.
* "point": the returned object is invalid if there no collision with any physics faces. otherwise, one can use GetPosition function of the returned object to retrieve the intersection point.
* "terrain": pick a point on the global terrain only.
* "walkpoint": pick a point on the global terrain or any physical object with camera obstruction attribute set to true.
* "actionmesh": mesh with action script.
* number: if it is a number, it is treated as a 32 bitwise DWORD filter code. see SetPickingFilter() for more example.
* @return :the scene object. if the object is invalid, it means that the ray has hit nothing.
*/
ParaObject MousePick(float x, float y, float fMaxDistance, const char* sFilterFunc);
3D Object
All 3D object interface is exposed via ParaObject interface in NPL. One can access almost all C++ properties via GetField() and SetField() method. They are just short-cuts to ParaObject:GetAttributeObject():GetField()
3D Object Rendering
In NPL, one can change the appearance of 3d object, using replaceable textures, attachment point, primary asset file and primary effect file.
To change a user defined shader parameter in NPL, use GetEffectParamBlock
local params = obj:GetEffectParamBlock();
params:SetFloat("g_opacity", 1);
To manually animate 3d object
obj:SetField("AnimFrame", 33);
obj:SetField("IsAnimPaused", true);