1-- Material animation example. 2-- This sample is base on StaticScene, and it demonstrates: 3-- - Usage of material shader animation for mush room material 4 5require "LuaScripts/Utilities/Sample" 6 7function Start() 8 -- Execute the common startup for samples 9 SampleStart() 10 11 -- Create the scene content 12 CreateScene() 13 14 -- Create the UI content 15 CreateInstructions() 16 17 -- Setup the viewport for displaying the scene 18 SetupViewport() 19 20 -- Set the mouse mode to use in the sample 21 SampleInitMouseMode(MM_RELATIVE) 22 23 -- Hook up to the frame update events 24 SubscribeToEvents() 25end 26 27function CreateScene() 28 scene_ = Scene() 29 30 -- Create the Octree component to the scene. This is required before adding any drawable components, or else nothing will 31 -- show up. The default octree volume will be from (-1000, -1000, -1000) to (1000, 1000, 1000) in world coordinates it 32 -- is also legal to place objects outside the volume but their visibility can then not be checked in a hierarchically 33 -- optimizing manner 34 scene_:CreateComponent("Octree") 35 36 -- Create a child scene node (at world origin) and a StaticModel component into it. Set the StaticModel to show a simple 37 -- plane mesh with a "stone" material. Note that naming the scene nodes is optional. Scale the scene node larger 38 -- (100 x 100 world units) 39 local planeNode = scene_:CreateChild("Plane") 40 planeNode.scale = Vector3(100.0, 1.0, 100.0) 41 local planeObject = planeNode:CreateComponent("StaticModel") 42 planeObject.model = cache:GetResource("Model", "Models/Plane.mdl") 43 planeObject.material = cache:GetResource("Material", "Materials/StoneTiled.xml") 44 45 -- Create a directional light to the world so that we can see something. The light scene node's orientation controls the 46 -- light direction we will use the SetDirection() function which calculates the orientation from a forward direction vector. 47 -- The light will use default settings (white light, no shadows) 48 local lightNode = scene_:CreateChild("DirectionalLight") 49 lightNode.direction = Vector3(0.6, -1.0, 0.8) -- The direction vector does not need to be normalized 50 local light = lightNode:CreateComponent("Light") 51 light.lightType = LIGHT_DIRECTIONAL 52 53 -- Create more StaticModel objects to the scene, randomly positioned, rotated and scaled. For rotation, we construct a 54 -- quaternion from Euler angles where the Y angle (rotation about the Y axis) is randomized. The mushroom model contains 55 -- LOD levels, so the StaticModel component will automatically select the LOD level according to the view distance (you'll 56 -- see the model get simpler as it moves further away). Finally, rendering a large number of the same object with the 57 -- same material allows instancing to be used, if the GPU supports it. This reduces the amount of CPU work in rendering the 58 -- scene. 59 local mushroomMat = cache:GetResource("Material", "Materials/Mushroom.xml") 60 -- Apply shader parameter animation to material 61 local specColorAnimation = ValueAnimation:new() 62 specColorAnimation:SetKeyFrame(0.0, Variant(Color(0.1, 0.1, 0.1, 16.0))) 63 specColorAnimation:SetKeyFrame(1.0, Variant(Color(1.0, 0.0, 0.0, 2.0))) 64 specColorAnimation:SetKeyFrame(2.0, Variant(Color(1.0, 1.0, 0.0, 2.0))) 65 specColorAnimation:SetKeyFrame(3.0, Variant(Color(0.1, 0.1, 0.1, 16.0))) 66 -- Optionally associate material with scene to make sure shader parameter animation respects scene time scale 67 mushroomMat.scene = scene_; 68 mushroomMat:SetShaderParameterAnimation("MatSpecColor", specColorAnimation) 69 70 local NUM_OBJECTS = 200 71 for i = 1, NUM_OBJECTS do 72 local mushroomNode = scene_:CreateChild("Mushroom") 73 mushroomNode.position = Vector3(Random(90.0) - 45.0, 0.0, Random(90.0) - 45.0) 74 mushroomNode.rotation = Quaternion(0.0, Random(360.0), 0.0) 75 mushroomNode:SetScale(0.5 + Random(2.0)) 76 local mushroomObject = mushroomNode:CreateComponent("StaticModel") 77 mushroomObject.model = cache:GetResource("Model", "Models/Mushroom.mdl") 78 mushroomObject.material = mushroomMat 79 end 80 81 -- Create a scene node for the camera, which we will move around 82 -- The camera will use default settings (1000 far clip distance, 45 degrees FOV, set aspect ratio automatically) 83 cameraNode = scene_:CreateChild("Camera") 84 cameraNode:CreateComponent("Camera") 85 86 -- Set an initial position for the camera scene node above the plane 87 cameraNode.position = Vector3(0.0, 5.0, 0.0) 88end 89 90function CreateInstructions() 91 -- Construct new Text object, set string to display and font to use 92 local instructionText = ui.root:CreateChild("Text") 93 instructionText:SetText("Use WASD keys and mouse to move") 94 instructionText:SetFont(cache:GetResource("Font", "Fonts/Anonymous Pro.ttf"), 15) 95 96 -- Position the text relative to the screen center 97 instructionText.horizontalAlignment = HA_CENTER 98 instructionText.verticalAlignment = VA_CENTER 99 instructionText:SetPosition(0, ui.root.height / 4) 100end 101 102function SetupViewport() 103 -- Set up a viewport to the Renderer subsystem so that the 3D scene can be seen. We need to define the scene and the camera 104 -- at minimum. Additionally we could configure the viewport screen size and the rendering path (eg. forward / deferred) to 105 -- use, but now we just use full screen and default render path configured in the engine command line options 106 local viewport = Viewport:new(scene_, cameraNode:GetComponent("Camera")) 107 renderer:SetViewport(0, viewport) 108end 109 110function MoveCamera(timeStep) 111 -- Do not move if the UI has a focused element (the console) 112 if ui.focusElement ~= nil then 113 return 114 end 115 116 -- Movement speed as world units per second 117 local MOVE_SPEED = 20.0 118 -- Mouse sensitivity as degrees per pixel 119 local MOUSE_SENSITIVITY = 0.1 120 121 -- Use this frame's mouse motion to adjust camera node yaw and pitch. Clamp the pitch between -90 and 90 degrees 122 local mouseMove = input.mouseMove 123 yaw = yaw +MOUSE_SENSITIVITY * mouseMove.x 124 pitch = pitch + MOUSE_SENSITIVITY * mouseMove.y 125 pitch = Clamp(pitch, -90.0, 90.0) 126 127 -- Construct new orientation for the camera scene node from yaw and pitch. Roll is fixed to zero 128 cameraNode.rotation = Quaternion(pitch, yaw, 0.0) 129 130 -- Read WASD keys and move the camera scene node to the corresponding direction if they are pressed 131 -- Use the Translate() function (default local space) to move relative to the node's orientation. 132 if input:GetKeyDown(KEY_W) then 133 cameraNode:Translate(Vector3(0.0, 0.0, 1.0) * MOVE_SPEED * timeStep) 134 end 135 if input:GetKeyDown(KEY_S) then 136 cameraNode:Translate(Vector3(0.0, 0.0, -1.0) * MOVE_SPEED * timeStep) 137 end 138 if input:GetKeyDown(KEY_A) then 139 cameraNode:Translate(Vector3(-1.0, 0.0, 0.0) * MOVE_SPEED * timeStep) 140 end 141 if input:GetKeyDown(KEY_D) then 142 cameraNode:Translate(Vector3(1.0, 0.0, 0.0) * MOVE_SPEED * timeStep) 143 end 144end 145 146function SubscribeToEvents() 147 -- Subscribe HandleUpdate() function for processing update events 148 SubscribeToEvent("Update", "HandleUpdate") 149end 150 151function HandleUpdate(eventType, eventData) 152 -- Take the frame time step, which is stored as a float 153 local timeStep = eventData["TimeStep"]:GetFloat() 154 155 -- Move the camera, scale movement with time step 156 MoveCamera(timeStep) 157end 158