Created
March 22, 2013 05:22
-
-
Save tnlogy/5219140 to your computer and use it in GitHub Desktop.
Simple Volume Renderer in Codea
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--# 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