Creating your own image textures with the Octane Lua API

Forums: Creating your own image textures with the Octane Lua API
Forum for OctaneRender Lua scripting examples, discussion and support.

Creating your own image textures with the Octane Lua API

Postby stratified » Mon Dec 09, 2013 5:00 am

stratified Mon Dec 09, 2013 5:00 am
Hi all,

In this example we'll explain how to create an image texture in Lua. At the end you should end up with a nice gradient texture. Let's have a look at (some of) the attributes of the image texture node (octane.NT_TEX_IMAGE):

Code: Select all
A_BUFFER
     • Description    : Raw byte uncompressed data for the image.
     • Type           : AT_BYTE
     • Array          : true

A_SIZE
     • Description    : Size of the image in pixels.
     • Type           : AT_INT2
     • Array          : false
     • Default Value  : 0 0

A_TYPE
     • Description    : The image type, i.e. the data format used in A_BUFFER. Must be of type ImageType.
     • Type           : AT_INT
     • Array          : false
     • Default Value  : 0


What we need to do is correctly set up the A_BUFFER, A_SIZE and A_TYPE attributes of the image texture node. For our case we create an LDR_RGBA image which uses 4 bytes per pixel. First let's create a gradient image in Lua. The function createGradient will create an image "object" with a correct size, type and buffer. The function writes out a colour for each pixel. The colour is calculated by interpolating between the start and end colour with octane.vec.lerp. Every time we
encounter a new line in the image we recalculate the interpolation factor (it's a bit a waste of time to calculate the colour for each pixel but hey it's an example ;)

Code: Select all
-- Creates an LDR gradient image (4 bytes/pixel).
--
-- @param[in]   x
--      horizontail size of the image
-- @param[in]   y
--      vertical size of the image
-- @param[in]   c1
--      start colour for the gradient.
-- @param[in]   c2
--      end colour for the gradient.
-- @return
--      image buffer with a top to bottom gradient c1 > c2
local function createGradient(x, y, c1, c2)

    -- create a data structure for the image
    local image  = {}
    image.size   = { x, y }
    image.type   = octane.image.type.LDR_RGBA
    image.buffer = {}

    -- fill in the buffer with a gradient
    t = 0
    for i = 1, x*y do
        -- interpolate between start & end colour
        local c = octane.vec.lerp(c2, c1, t)
        table.insert(image.buffer, c[1])
        table.insert(image.buffer, c[2])
        table.insert(image.buffer, c[3])
        table.insert(image.buffer, 255) -- alpha

        -- on a new line, modify the interpolation factor
        if (i % x == 0) then t = t + 1/y end
    end

    return image
end


Like always we start with a clean slate. We call createGradient to create a 500 by 500 pixels image with a red to yellow gradient:

Code: Select all
-- start with a clean slate
octane.project.reset()

-- create a gradient (500x500, red -> yellow)
gradient = createGradient(500, 500, { 255, 0, 0 }, { 255, 255, 0 })


Now that we have created an image, we use it to set up the image texture node. First we create the image texture node. Afterwards we use our image object to set up the A_BUFFER, A_SIZE and A_TYPE attributes of the node. Note the third false parameter of setAttribute, this means we don't immediately want to evaluate the node. Only after all attributes are set up correctly we call evaluate on the node:

Code: Select all
-- create an image texture node
texNode = octane.node.create{ type=octane.NT_TEX_IMAGE, name="Gradient Texture" }

-- set up the gradient in the attributes
texNode:setAttribute(octane.A_BUFFER , gradient.buffer , false)
texNode:setAttribute(octane.A_SIZE   , gradient.size   , false)
texNode:setAttribute(octane.A_TYPE   , gradient.type   , false)
-- evaluate the texture node
texNode:evaluate()


If we would stop the script here we would have a correct image texture node but it's nice to have it on disk as well. We can do this by calling exportToFile on the node (We did this before in the geometry creation tutorial). All we have to do is specify a directory. Octane will create a subdirectory textures and create a file with the same name as our node (Octane uses .png for images of type LDR_RGBA and LDR_MONO. It uses .exr for images of type HDR_RGBA and HDR_MONO).

Code: Select all
-- save out the image texture as a png
directory = "/tmp/lua"
-- this will export to "/tmp/lua/textures/Gradient Texture.png"
texNode:exportToFile(directory)


If all went well, you should have something like this:

Code: Select all
-- Roll our own image textures

-- Creates an LDR gradient image (4 bytes/pixel).
--
-- @param[in]   x
--      horizontail size of the image
-- @param[in]   y
--      vertical size of the image
-- @param[in]   c1
--      start colour for the gradient.
-- @param[in]   c2
--      end colour for the gradient.
-- @return
--      image buffer with a top to bottom gradient c1 > c2
local function createGradient(x, y, c1, c2)

    -- create a data structure for the image
    local image  = {}
    image.size   = { x, y }
    image.type   = octane.image.type.LDR_RGBA
    image.buffer = {}

    -- fill in the buffer with a gradient
    t = 0
    for i = 1, x*y do
        -- interpolate between start & end colour
        local c = octane.vec.lerp(c2, c1, t)
        table.insert(image.buffer, c[1])
        table.insert(image.buffer, c[2])
        table.insert(image.buffer, c[3])
        table.insert(image.buffer, 255) -- alpha

        -- on a new line, modify the interpolation factor
        if (i % x == 0) then t = t + 1/y end
    end

    return image
end

-- start with a clean slate
octane.project.reset()

-- create a gradient (500x500, red -> yellow)
gradient = createGradient(500, 500, { 255, 0, 0 }, { 255, 255, 0 })

-- create an image texture node
texNode = octane.node.create{ type=octane.NT_TEX_IMAGE, name="Gradient Texture" }
-- set up the gradient in the attributes
texNode:setAttribute(octane.A_BUFFER , gradient.buffer , false)
texNode:setAttribute(octane.A_SIZE   , gradient.size   , false)
texNode:setAttribute(octane.A_TYPE   , gradient.type   , false)
-- evaluate the texture node
texNode:evaluate()

-- save out the image texture as a png
directory = "/tmp/lua"
-- this will export to "/tmp/lua/textures/Gradient Texture.png"
texNode:exportToFile(directory)


have fun,
Thomas
User avatar
stratified
OctaneRender Team
OctaneRender Team
 
Posts: 945
Joined: Wed Aug 15, 2012 6:32 am
Location: Auckland, New Zealand

Re: Creating your own image textures with the Octane Lua API

Postby gabrielefx » Mon Dec 09, 2013 8:15 am

gabrielefx Mon Dec 09, 2013 8:15 am
mmmmh....
we need a video course on Lua Scripting
what are all the Octane Lua functions?
What is possible to do with Lua within Octane? Procedural textures? Batch render? Shaders? Animation?

regards
1 X quad GTX580 3GB + 1 X quad GTX680 4GB + 1 X quad Titan 6GB rig + 1 X quad Titan-X 12GB rig
User avatar
gabrielefx
Licensed Customer
Licensed Customer
 
Posts: 1700
Joined: Wed Sep 28, 2011 2:00 pm

Re: Creating your own image textures with the Octane Lua API

Postby j7th » Mon Dec 09, 2013 1:09 pm

j7th Mon Dec 09, 2013 1:09 pm
You can find all avaluable lua functions in this buid:
viewtopic.php?f=33&t=37295
Win 7 x64 | GTX560Ti | Core i7 960 3.2GHz | 24GB RAM
User avatar
j7th
Licensed Customer
Licensed Customer
 
Posts: 124
Joined: Thu May 20, 2010 7:22 pm

Re: Creating your own image textures with the Octane Lua API

Postby stratified » Mon Dec 09, 2013 6:57 pm

stratified Mon Dec 09, 2013 6:57 pm
All available Lua functions are available in the API browser of the standalone. I will create more tutorials and put up the Lua docs in html online.

cheers,
Thomas
User avatar
stratified
OctaneRender Team
OctaneRender Team
 
Posts: 945
Joined: Wed Aug 15, 2012 6:32 am
Location: Auckland, New Zealand

Return to Lua Scripting


Who is online

Users browsing this forum: No registered users and 1 guest

Wed Aug 21, 2019 1:17 am [ UTC ]