Add a few vars, and support for rendering single flames

This commit is contained in:
Steven Robertson 2011-05-03 14:36:20 -04:00
parent 84c2583ba8
commit 8ee5d3edd8
3 changed files with 73 additions and 49 deletions

View File

@ -37,7 +37,7 @@ texture<uchar4, cudaTextureType2D, cudaReadModeNormalizedFloat> palTex;
tmpl = tempita.Template(""" tmpl = tempita.Template("""
__device__ __device__
void apply_xf{{xfid}}(float *ix, float *iy, float *icolor, void apply_xf{{xfid}}(float *ix, float *iy, float *icolor,
const iter_info *info) { const iter_info *info, mwc_st *rctx) {
float tx, ty, ox = *ix, oy = *iy; float tx, ty, ox = *ix, oy = *iy;
{{apply_affine('ox', 'oy', 'tx', 'ty', px, 'xf.c', 'pre')}} {{apply_affine('ox', 'oy', 'tx', 'ty', px, 'xf.c', 'pre')}}
@ -47,7 +47,7 @@ void apply_xf{{xfid}}(float *ix, float *iy, float *icolor,
{{for v in xform.vars}} {{for v in xform.vars}}
if (1) { if (1) {
float w = {{px.get('xf.var[%d]' % v)}}; float w = {{px.get('xf.var[%d]' % v)}};
{{variations.var_code[variations.var_nos[v]]()}} {{variations.var_code[variations.var_nos[v]].substitute(locals())}}
} }
{{endfor}} {{endfor}}
@ -82,7 +82,7 @@ void iter(mwc_st *msts, iter_info *infos, float *accbuf, float *denbuf) {
{{for xfid, xform in enumerate(features.xforms)}} {{for xfid, xform in enumerate(features.xforms)}}
if (xfsel <= {{packer.get('cp.norm_density[%d]' % xfid)}}) { if (xfsel <= {{packer.get('cp.norm_density[%d]' % xfid)}}) {
apply_xf{{xfid}}(&x, &y, &color, info); apply_xf{{xfid}}(&x, &y, &color, info, &rctx);
} else } else
{{endfor}} {{endfor}}
{ {
@ -97,7 +97,7 @@ void iter(mwc_st *msts, iter_info *infos, float *accbuf, float *denbuf) {
nsamps--; nsamps--;
if (x <= -1.0f || x >= 1.0f || y <= -1.0f || y >= 1.0f) { if (x <= -0.5f || x >= 0.5f || y <= -0.5f || y >= 0.5f) {
consec_bad++; consec_bad++;
if (consec_bad > {{features.max_oob}}) { if (consec_bad > {{features.max_oob}}) {
x = mwc_next_11(&rctx); x = mwc_next_11(&rctx);
@ -109,8 +109,8 @@ void iter(mwc_st *msts, iter_info *infos, float *accbuf, float *denbuf) {
} }
// TODO: dither? // TODO: dither?
int i = ((int)((y + 1.0f) * 511.0f) * 1024) int i = ((int)((y + 0.5f) * 1023.0f) * 1024)
+ (int)((x + 1.0f) * 511.0f) + 1025; + (int)((x + 0.5f) * 1023.0f) + 1025;
// since info was declared const, C++ barfs unless it's loaded first // since info was declared const, C++ barfs unless it's loaded first
float cp_step_frac = {{packer.get('cp_step_frac')}}; float cp_step_frac = {{packer.get('cp_step_frac')}};
@ -129,7 +129,7 @@ void iter(mwc_st *msts, iter_info *infos, float *accbuf, float *denbuf) {
def silly(features, cps): def silly(features, cps):
nsteps = 1000 nsteps = 500
abuf = np.zeros((1024, 1024, 4), dtype=np.float32) abuf = np.zeros((1024, 1024, 4), dtype=np.float32)
dbuf = np.zeros((1024, 1024), dtype=np.float32) dbuf = np.zeros((1024, 1024), dtype=np.float32)
seeds = mwc.MWC.make_seeds(512 * nsteps) seeds = mwc.MWC.make_seeds(512 * nsteps)
@ -139,28 +139,37 @@ def silly(features, cps):
for lno, line in enumerate(code.split('\n')): for lno, line in enumerate(code.split('\n')):
print '%3d %s' % (lno, line) print '%3d %s' % (lno, line)
mod = SourceModule(code, options=[], keep=True) mod = SourceModule(code, options=['--use_fast_math'], keep=True)
cps_as_array = (Genome * len(cps))() cps_as_array = (Genome * len(cps))()
for i, cp in enumerate(cps): for i, cp in enumerate(cps):
cps_as_array[i] = cp cps_as_array[i] = cp
cp = Genome()
memset(byref(cp), 0, sizeof(cp))
infos = [] infos = []
pal = np.empty((16, 256, 4), dtype=np.uint8)
# TODO: move this into a common function # TODO: move this into a common function
pal = np.empty((16, 256, 4), dtype=np.uint8) if len(cps) > 1:
sampAt = [int(i/15.*(nsteps-1)) for i in range(16)] cp = Genome()
memset(byref(cp), 0, sizeof(cp))
sampAt = [int(i/15.*(nsteps-1)) for i in range(16)]
for n in range(nsteps): for n in range(nsteps):
flam3_interpolate(cps_as_array, 2, float(n)/nsteps - 0.5, 0, byref(cp)) flam3_interpolate(cps_as_array, 2, float(n)/nsteps - 0.5,
0, byref(cp))
cp._init() cp._init()
if n in sampAt: if n in sampAt:
pidx = sampAt.index(n) pidx = sampAt.index(n)
for i, e in enumerate(cp.palette.entries): for i, e in enumerate(cp.palette.entries):
pal[pidx][i] = np.uint8(np.array(e.color) * 255.0) pal[pidx][i] = np.uint8(np.array(e.color) * 255.0)
infos.append(iter.packer.pack(cp=cp, cp_step_frac=float(n)/nsteps)) infos.append(iter.packer.pack(cp=cp, cp_step_frac=float(n)/nsteps))
else:
for i, e in enumerate(cps[0].palette.entries):
pal[0][i] = np.uint8(np.array(e.color) * 255.0)
pal[1:] = pal[0]
infos.append(iter.packer.pack(cp=cps[0], cp_step_frac=0))
infos *= nsteps
infos = np.concatenate(infos) infos = np.concatenate(infos)
dpal = cuda.make_multichannel_2d_array(pal, 'C') dpal = cuda.make_multichannel_2d_array(pal, 'C')

View File

@ -1,40 +1,58 @@
import tempita
var_nos = {} var_nos = {}
var_code = {} var_code = {}
def _var(num, name = None): def var(num, name, code):
def _var1(func): var_nos[num] = name
if name: var_code[name] = tempita.Template(code)
namelo = name
else:
namelo = func.__name__
var_nos[num] = namelo
var_code[namelo] = func
return _var1
# Variables note: all functions will have their weights as 'w', # Variables note: all functions will have their weights as 'w',
# input variables 'tx' and 'ty', and output 'ox' and 'oy' available # input variables 'tx' and 'ty', and output 'ox' and 'oy' available
# from the calling context. Each statement will be placed inside brackets, # from the calling context. Each statement will be placed inside brackets,
# to avoid namespace pollution. # to avoid namespace pollution.
@_var(0) var(0, 'linear', """
def linear():
return """
ox += tx * w; ox += tx * w;
oy += ty * w; oy += ty * w;
""" """)
@_var(1) var(1, 'sinusoidal', """
def sinusoidal(): ox += w * sinf(tx);
return """ oy += w * sinf(ty);
ox += w * sin(tx); """)
oy += w * sin(ty);
"""
@_var(2) var(2, 'spherical', """
def spherical():
return """
float r2 = w / (tx*tx + ty*ty + 1e-20); float r2 = w / (tx*tx + ty*ty + 1e-20);
ox += tx * r2; ox += tx * r2;
oy += ty * r2; oy += ty * r2;
""" """)
var(5, 'polar', """
ox += w * atan2f(tx, ty) * M_1_PI;
oy += w * (sqrtf(tx * tx + ty * ty) - 1.0);
""")
var(10, 'hyperbolic', """
float a = atan2f(tx, ty);
float r = sqrt(tx*tx + ty*ty) + 1e-20;
ox += w * sinf(a) / r;
oy += w * cosf(a) * r;
""")
var(33, 'juliascope', """
float ang = atan2f(ty, tx);
float power = {{px.get('xf.juliascope_power', 'juscope_power')}};
float t_rnd = truncf(mwc_next_01(rctx) * fabsf(power));
// TODO: don't draw the extra random number
if (mwc_next(rctx) & 1) ang = -ang;
float tmpr = (2 * M_PI * t_rnd + ang) / power;
float cn = {{px.get('xf.juliascope_dist / xf.juliascope_power / 2',
'juscope_cn')}};
float r = w * powf(tx * tx + ty * ty, cn);
ox += r * cosf(tmpr);
oy += r * sinf(tmpr);
""")

View File

@ -32,21 +32,18 @@ from cuburn.code.iter import silly, membench
def main(args): def main(args):
membench()
return
#MWCTest.test_mwc() #MWCTest.test_mwc()
with open(args[-1]) as fp: with open(args[-1]) as fp:
genomes = Genome.from_string(fp.read()) genomes = Genome.from_string(fp.read())
anim = Animation(genomes) anim = Animation(genomes)
accum, den = silly(anim.features, genomes) accum, den = silly(anim.features, genomes)
if '-g' not in args:
return
noalpha = np.delete(accum, 3, axis=2) noalpha = np.delete(accum, 3, axis=2)
scipy.misc.imsave('rendered.png', noalpha) scipy.misc.imsave('rendered.png', noalpha)
if '-g' not in args:
return
imgbuf = (np.minimum(accum * 255, 255)).astype(np.uint8) imgbuf = (np.minimum(accum * 255, 255)).astype(np.uint8)
image = pyglet.image.ImageData(1024, 1024, 'RGBA', imgbuf.tostring(), -4096) image = pyglet.image.ImageData(1024, 1024, 'RGBA', imgbuf.tostring(), -4096)