Here's a example of how to create a procedural texture. It generates the Mandelbrot set in Lua. This script is just me goofing off, the script won't cure cancer or create world peace. For the one interested in Mandelbrot set, you can read all about them here:
http://en.wikipedia.org/wiki/Mandelbrot_set
All it does is colour the pixels that are in the Mandelbrot set orange and the others black:
- Code: Select all
--
-- @description Creates a Mandelbrot set texture node.
-- @author Stratified
-- @version 0.1
--
-- The code to generate the Mandelbrot set is a modified version of this code:
-- http://www.timestretch.com/article/mandelbrot_fractal_benchmark#aba942b3e0f9e50dd67b83d89ec88139
--
local BAILOUT = 4
local MAX_ITERATIONS = 1000
-- Checks if a pixel in the image plane is in the mandelbrot set.
-- Returns 0 if the pixel is not. The modulus of the last generated
-- complex number is returned when the thing is in the set
--
-- Boring theory:
-- A point c (complex number really) is in the Mandelbrot set if the series
-- generated by z(n+1) = z(n)^2 + c (with z(0) = 0 + j*0) is not going to infinity.
local function inMandelbrotSet(x, y)
local cr = x
local ci = y
local zi = 0.0
local zr = 0.0
local k = 0
while 1 do
k = k+1
-- calculate z(n+1) from z(n)
local zrzi2 = zr * zi * 2
local zr2 = zr * zr
local zi2 = zi * zi
zr = zr2 - zi2 + cr
zi = ci + zrzi2
-- check if we're still bound, bail out if not
if (zi2 + zr2 > 4) then
return false
end
-- if we reached the maximum number of iterations and the last value
-- of the generated series is still bounded, we assume the pixel is
-- in the Mandelbrot set.
if (k > MAX_ITERATIONS) then
return true
end
end
end
-- Generates a Mandelbrot set centered around the centre of the image.
function genMandelbrotTex(w, h)
-- create a data structure for the image
local image = {}
image.size = { w, h }
image.type = octane.image.type.LDR_RGBA
image.buffer = {}
-- see which pixels are in the Mandelbrot set
for y = 0, h-1 do
for x = 0, w-1 do
-- transform x so it's in the range [-2, 1]
local sx = 3 * (x / w) - 2
-- transform y so it's in the range [-1, 1]
local sy = 2 * (y / h) - 1
local colour = inMandelbrotSet(sx, sy)
-- colour pixels in the set
if colour then
table.insert(image.buffer, 255)
table.insert(image.buffer, 127)
table.insert(image.buffer, 0)
table.insert(image.buffer, 0)
-- pixels not in the set are black
else
table.insert(image.buffer, 0)
table.insert(image.buffer, 0)
table.insert(image.buffer, 0)
table.insert(image.buffer, 0)
end
end
end
return image
end
-- dimensions of the generated texture
local WIDTH, HEIGHT = 400, 400
-- actually create the Mandelbrot texture
local tex = genMandelbrotTex(WIDTH, HEIGHT)
assert(#tex.buffer == 4 * WIDTH * HEIGHT, "invalid buffer length")
-- create an image texture node
texNode = octane.node.create{ type=octane.NT_TEX_IMAGE, name="Mandelbrot Texture" }
-- set up the gradient in the attributes
texNode:setAttribute(octane.A_BUFFER , tex.buffer , false)
texNode:setAttribute(octane.A_SIZE , tex.size , false)
texNode:setAttribute(octane.A_TYPE , tex.type , false)
-- evaluate the texture node
texNode:evaluate()
Here's the texture mapped on a cube:
The colours are still a bit lacking, a gradient would be nicer...
cheers,
Thomas