Capricorn 76
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.

---------------------------
---------------------------
-- 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)