Skip to content

Instantly share code, notes, and snippets.

@tnlogy
Created March 22, 2013 05:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tnlogy/5219140 to your computer and use it in GitHub Desktop.
Save tnlogy/5219140 to your computer and use it in GitHub Desktop.
Simple Volume Renderer in Codea
--# Main
-- Slices
function setup()
displayMode(FULLSCREEN)
parameter.number("Limit",0,1,.1)
parameter.integer("LowSlice",-80,80,-80)
parameter.integer("HighSlice",-80,80,80)
R = 0
-- VolumePacker()
v = Volume()
end
function draw()
background(40, 40, 50)
perspective(45)
camera(0,0,500,0,0,0)
rotate(R,0,1,0)
v:draw()
end
function touched(touch)
R = R + touch.deltaX
end
--# Volume
Volume = class()
function Volume:init()
local sq = {
vec3(0,0,0), vec3(1,0,0),
vec3(1,1,0), vec3(1,1,0),
vec3(0,1,0), vec3(0,0,0)
}
local dz = 1.3
local hd = 100*dz/2
self.m = mesh()
local vs,uvs = {},{}
self.m.shader = VolumeShader
-- self.m.texture = "Documents:Slices"
-- self.m.shader.texture2 = "Documents:Slices2"
self:loadTextures()
for i=1,99 do
for j,v in ipairs(sq) do
table.insert(vs, (v - vec3(.5,.5,0))*256 +
vec3(0,0,i*dz - hd))
-- texture space divided by 8 to match smaller images
local x = (math.floor(i)-1)
local y = math.floor(x*.125)
local uv = (vec2(v.x,v.y) + vec2(x%8,y))*.125
table.insert(uvs, uv)
end
end
self.m.vertices = vs
self.m.texCoords = uvs
end
function Volume:loadTextures()
local url = "https://dl.dropbox.com/s/mzz2hce40r8kq35/"
http.request(url .. "Slices.png", function (data)
self.m.texture = data
end)
end
function Volume:draw()
self.m.shader.limit = Limit
self.m.shader.lowSlice = LowSlice
self.m.shader.highSlice = HighSlice
self.m:draw()
end
--# VolumeShader
VolumeShader = shader()
VolumeShader.vertexProgram = [[
uniform mat4 modelViewProjection;
attribute vec4 position;
attribute vec2 texCoord;
varying highp vec2 vTexCoord;
uniform highp float lowSlice;
uniform highp float highSlice;
void main()
{
vTexCoord = texCoord;
if(position.z > lowSlice && position.z < highSlice) {
gl_Position = modelViewProjection * position;
} else {
// move all points of slice to origin to hide it.
gl_Position = vec4(0.,0.,0.,0.);
}
}
]]
VolumeShader.fragmentProgram = [[
uniform lowp sampler2D texture;
uniform lowp sampler2D texture2;
varying highp vec2 vTexCoord;
uniform highp float limit;
void main()
{
lowp vec4 col;
if(vTexCoord.y > 1.) {
col = texture2D(texture2, vTexCoord);
} else {
col = texture2D(texture, vTexCoord);
}
if(col.r < limit) discard;
gl_FragColor = col;
}
]]
--# VolumePacker
-- Used to pack several images into one image
VolumePacker = class()
function VolumePacker:init(x)
local w = 2048
local img = image(w,w)
local img2 = image(w,w)
local x,y = 0,0
spriteMode(CORNER)
setContext(img)
for i=1,99 do
sprite(self:getSlice(i),x,y)
x = x + 256
if x >= w then
x,y = 0,y + 256
if y >= w then
setContext(img2)
x,y = 0,0
end
end
end
setContext()
saveImage("Documents:Slices", img)
saveImage("Documents:Slices2", img2)
end
function VolumePacker:getSlice(i)
local id = i
if i < 10 then id = "00" .. id
else id = "0" .. id end
return "Dropbox:slices/mrbrain-8bit" .. id
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment