--------------------------- --------------------------- -- Dynamic textures example -- Copyright (c) 2007-09 Capricorn 76 Pty. Ltd. -- -- Dynamic textures and Render targets allow us to -- draw different views of the ScriptENGINE world, -- from different cameras, and apply the resulting image -- to an entity as a texture. Render targets then replace -- static textures, and create a dynamic texture. -- -- NOTE: -- The ./Demos/runDemo.e76script is a utility script used to run all the examples. -- It loads the world, calls the OnWorldLoad(), OnWorldUnload() functions, and runs the graphics engine loop, waiting for the user to press escape. --------------------------- --------------------------- local subTick; local subGui; ------------------------ -- PRIVATE FUNCTION -- Set a render target for the cube. ------------------------ local function _doRenderTarget() --------------------------- -- Setup a render target. -- We specify the camera to view, and the render target name. -- We use the render target name to apply it as a texture to any entity. --------------------------- if (IGraphics:queryFeature(GRAPHICS_FEATURE_RENDER_TO_TARGET)) then -- Render target dimensions can be specified as screen relative (0-1) or in absolute pixels (>1). (Will internally be sized to the closest power of 2). IGraphics:createRenderTarget('#render1', '64 64', idCamera_renderFrom); --IGraphics:createRenderTarget('#render1', '0.25 0.25', idCamera_renderFrom); -- Apply the texture to the entity IGraphics:setEntityTextureName(idUnit_box, 0, -1, '#render1'); -- Set the material style IGraphics:setEntityMaterialType(idUnit_box, -1, MAT_SOLID); else print('Your graphics cards cannot support render targets...'); end end --------------------------- -- PRIVATE FUNCTION -- Set a sold texture for the cube --------------------------- local function _doSolidTexture() -- Set texture IGraphics:setEntityTextureName(idUnit_box, 0, -1, '../Resources/crate.jpg'); -- Set the material style IGraphics:setEntityMaterialType(idUnit_box, -1, MAT_SOLID); end --------------------------- -- PRIVATE FUNCTION -- Dynamically modify the texture pixel data for the cube. --------------------------- local function _doSetPixels() --------------------------- -- Can manually create textures that to manipulate and apply to entities -- Texture dimensions can be specified as screen relative (0-1) or in absolute pixels (>1) (Will internally be sized to the closest power of 2) --------------------------- --IGraphics:createTexture('#texture1', '0.125 0.125', COLOR_FORMAT_R8G8B8); IGraphics:createTexture('#texture1', '16 16', COLOR_FORMAT_A8R8G8B8); print('Original size:', IGraphics:getTextureOriginalSize('#texture1')); print('Size:', IGraphics:getTextureSize('#texture1')); print('Format:', IGraphics:getTextureColorFormat('#texture1')); local size = IGraphics:getTextureSize('#texture1'); local w = IMisc:pointGetX(size); local h = IMisc:pointGetY(size); -- Must lock the texture before editing it local textureId = IGraphics:textureLock('#texture1'); if (textureId) then --------------------------- -- Manipulate the texture pixel-by-pixel -- Create a 2d texture with the X dimension affecting the red component, -- the Y dimension affecting the green component, and the blue used only for the textures' centre line --------------------------- for j = 0, h-1, 1 do for i = 0, w-1, 1 do local col; if (j == 7) then col = IMisc:colorCreate(i/w, j/h, 1, 1); -- red component varies with X, green component varies with y, blue set to 100%, alpha set to 100% else col = IMisc:colorCreate(i/w, j/h, 0, i/w); -- red component varies with X, green component varies with y, transparency varies with X value end IGraphics:textureSetPixel(textureId, i, j, col); end end -- Be sure to unlock the texture when you're finished editing it. IGraphics:textureUnlock(textureId); -- Apply the texture to the entity IGraphics:setEntityTextureName(idUnit_box, 0, -1, '#texture1'); -- Set the material style IGraphics:setEntityMaterialType(idUnit_box, -1, MAT_TRANSPARENT_ALPHA_CHANNEL); -- The alpha threshold is controlled via the material parameter. -- Any alpha below this is off. This controls how harsh the alpha blended edges are... -- Can range between 0-1 IGraphics:setEntityMaterialTypeParam(idUnit_box, -1, 0.01); ----------------------------------------------------- -- Here's an example of how to create an example gui image that uses the said texture ----------------------------------------------------- --[[ if (IGraphics:controlExists(100)) then IGraphics:removeControl(100); end IGraphics:createImage(100, '#texture1', '0 0 .1 .1', 0, 0, true); ]] end end --------------------------- -- PRIVATE FUNCTION -- Dynamically modify the texture pixel data for the cube. --------------------------- local function _doWriteData() --------------------------- -- Can manually create textures that to manipulate and apply to entities -- Texture dimensions can be specified as screen relative (0-1) or in absolute pixels (>1) (Will internally be sized to the closest power of 2) --------------------------- --IGraphics:createTexture('#texture1', '0.125 0.125', COLOR_FORMAT_R8G8B8); IGraphics:createTexture('#texture1', '16 16', COLOR_FORMAT_R8G8B8); --COLOR_FORMAT_A1R5G5B5); print('Original size:', IGraphics:getTextureOriginalSize('#texture1')); print('Size:', IGraphics:getTextureSize('#texture1')); print('Format:', IGraphics:getTextureColorFormat('#texture1')); local size = IGraphics:getTextureSize('#texture1'); local w = IMisc:pointGetX(size); local h = IMisc:pointGetY(size); -- Must lock the texture before editing it local textureId = IGraphics:textureLock('#texture1'); if (textureId) then --------------------------- -- We create a 4x4 data array in R8G8B8 format. -- This could optionally be loaded from file... -- Each pixel has a red/green/blue component ranging from 0-255 -- Note the 'endianess' on Windows, the actual component values are stored as blue/green/red --------------------------- local data = "\255\255\255\255\255\255\255\255\255\255\255\255" .. "\255\0\0\255\0\0\255\0\0\255\0\0" .. "\0\255\0\0\255\0\0\255\0\0\255\0" .. "\0\0\255\0\0\255\0\0\255\0\0\255"; --------------------------- -- Write the entire block of data to the texture with no scaling --------------------------- --IGraphics:textureWriteData(textureId, data, '4 4', COLOR_FORMAT_R8G8B8, IMG_SCALE_NONE, false); -- Write the entire block of data to the texture and scale it to fit the entire texture IGraphics:textureWriteData(textureId, data, '4 4', COLOR_FORMAT_R8G8B8, IMG_SCALE_BOTH, false); -- Be sure to unlock the texture when you're finished editing it. IGraphics:textureUnlock(textureId); -- Apply the texture to the entity IGraphics:setEntityTextureName(idUnit_box, 0, -1, '#texture1'); -- Set the material style IGraphics:setEntityMaterialType(idUnit_box, -1, MAT_SOLID); ----------------------------------------------------- -- Here's an example of how to create an example gui image that uses the said texture ----------------------------------------------------- --[[ if (IGraphics:controlExists(100)) then IGraphics:removeControl(100); end IGraphics:createImage(100, '#texture1', '0 0 .1 .1', 0, 0, true); ]] end end --------------------------- -- runDemo.e76script calls this function when the world is loaded --------------------------- function OnWorldLoad(worldName) --print('OnWorldLoad'); --------------------------- -- The SDK world editor creates a worldIds.e76script when the world is saved. It contains all the entity ids. -- We load the IDs so that we can refer to the world entities using friendly names. --------------------------- IApp:loadScript(IWorld:getNameLong() .. '/worldIds'); --------------------------- -- Load some constants that will be used in this example. --------------------------- IApp:loadScript(IApp:getExeFilePath() .. './Constants/constantsMaterialTypes'); IApp:loadScript(IApp:getExeFilePath() .. './Constants/constantsGuiImageParams'); IApp:loadScript(IApp:getExeFilePath() .. './Constants/constantsColorFormats'); IApp:loadScript(IApp:getExeFilePath() .. './Constants/constantsVideoDrivers'); --------------------------- -- Load this example's specific gui --------------------------- OnWorldLoadGui(); IWorld:setActiveCameraId(idCamera_cam1); --------------------------- -- Subscribe to the graphics engine 'tick' event. -- Our callback will be periodically fired by the graphics engine, -- so we can do some extra processing. -- -- Could create a thread to manage this, -- but we're showing how this can be done from the graphics engine thread. -- -- Note that you should do minimal processing this way, -- because the graphics can become jerky as the processing load increases. -- -- The returned identifier is later used to unsubscribe. --------------------------- subTick = IEvents:subscribeTickPeriodic('OnRotateCube', 100); -- Handle gui events so we can process the combobox updates subGui = IEvents:subscribeGui('OnGui'); --------------------------- -- Set the agent's animation --------------------------- IGraphics:setEntityAnimation(idAgent_Mech, nil, true, 10); -- Start off with the render target --_doRenderTarget(); _doSolidTexture(); end --------------------------- -- GUI specific to this example --------------------------- function OnWorldLoadGui() --------------------------- -- Let's show some help text --------------------------- IGraphics:loadGui('help'); --------------------------- -- Check if render-targets are supported --------------------------- if (not(IGraphics:queryFeature(GRAPHICS_FEATURE_RENDER_TO_TARGET))) then IGraphics:setControlText('text', 'Your graphics card DOES NOT support render targets.'); end end --------------------------- -- runDemo.e76script calls this function when the world is unloaded --------------------------- function OnWorldUnload(worldName) --print('OnWorldUnload'); --------------------------- -- Unsubscribe to events. -- We will no longer be notified of the graphics tick events. --------------------------- IEvents:unsubscribe(subTick); IEvents:unsubscribe(subGui); --------------------------- -- Reset the unit texture --------------------------- _doSolidTexture(); --------------------------- -- Clear dynamic textures, if they exist --------------------------- if (IGraphics:textureExists('#texture1')) then IGraphics:unloadTexture('#texture1'); end --------------------------- -- Clear the render target, if it exists --------------------------- if (IGraphics:renderTargetExists('#render1')) then IGraphics:removeRenderTarget('#render1'); end end ------------------------ -- Handle graphics tick event. -- We rotate the cube a little bit each time. ------------------------ function OnRotateCube(currentTime, lastTime, isWindowActive, userData) IWorld:manipulateEntity(idUnit_box, 'rotate', 0, 1, 0); end ------------------------ -- Handle gui events ------------------------ function OnGui(callerId, eventType, userData) if (IGraphics:comboChanged('combo', callerId, eventType)) then local selection = IGraphics:getComboboxSelection('combo'); -- Write data if (selection == 2) then _doWriteData(); -- Set pixels elseif (selection == 1) then _doSetPixels(); -- Render target else _doRenderTarget(); end end end
Copyright © 2006-23 Sep 2009 Capricorn 76 Pty. Ltd. (created on Wed Sep 23 16:49:12 2009)