Add support for variations.

--HG--
rename : cuburn/variations.py => cuburn/code/variations.py
This commit is contained in:
Steven Robertson 2011-05-01 09:36:29 -04:00
parent 088299423e
commit a7900f187d
6 changed files with 69 additions and 50 deletions

View File

@ -7,7 +7,7 @@ from pycuda.driver import In, Out, InOut
from pycuda.compiler import SourceModule from pycuda.compiler import SourceModule
import numpy as np import numpy as np
from cuburn.code import mwc from cuburn.code import mwc, variations
from cuburn.code.util import * from cuburn.code.util import *
import tempita import tempita
@ -32,10 +32,18 @@ void apply_xf{{xfid}}(float *ix, float *iy, float *icolor,
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')}}
// tiny little TODO: variations ox = 0;
oy = 0;
*ix = tx; {{for v in xform.vars}}
*iy = ty; if (1) {
float w = {{px.get('xf.var[%d]' % v)}};
{{variations.var_code[variations.var_nos[v]]()}}
}
{{endfor}}
*ix = ox;
*iy = oy;
float csp = {{px.get('xf.color_speed')}}; float csp = {{px.get('xf.color_speed')}};
*icolor = *icolor * (1.0f - csp) + {{px.get('xf.color')}} * csp; *icolor = *icolor * (1.0f - csp) + {{px.get('xf.color')}} * csp;
@ -64,7 +72,7 @@ void iter(mwc_st *msts, const iter_info *infos, float *accbuf, float *denbuf) {
float xfsel = mwc_next_01(&rctx); float xfsel = mwc_next_01(&rctx);
{{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);
} else } else
{{endfor}} {{endfor}}
@ -78,9 +86,9 @@ void iter(mwc_st *msts, const iter_info *infos, float *accbuf, float *denbuf) {
continue; continue;
} }
if (x <= -1.0f || x >= 1.0f || y <= -1.0f || y >= 1.0f nsamps--;
|| consec_bad < 0) {
if (x <= -1.0f || x >= 1.0f || y <= -1.0f || y >= 1.0f) {
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);
@ -92,8 +100,8 @@ void iter(mwc_st *msts, const iter_info *infos, float *accbuf, float *denbuf) {
} }
// TODO: dither? // TODO: dither?
int i = ((int)((y + 1.0f) * 256.0f) * 512) int i = ((int)((y + 1.0f) * 255.0f) * 512)
+ (int)((x + 1.0f) * 256.0f); + (int)((x + 1.0f) * 255.0f);
accbuf[i*4] += color < 0.5f ? (1.0f - 2.0f * color) : 0.0f; accbuf[i*4] += color < 0.5f ? (1.0f - 2.0f * color) : 0.0f;
accbuf[i*4+1] += 1.0f - 2.0f * fabsf(0.5f - color); accbuf[i*4+1] += 1.0f - 2.0f * fabsf(0.5f - color);
accbuf[i*4+2] += color > 0.5f ? color * 2.0f - 1.0f : 0.0f; accbuf[i*4+2] += color > 0.5f ? color * 2.0f - 1.0f : 0.0f;
@ -101,7 +109,6 @@ void iter(mwc_st *msts, const iter_info *infos, float *accbuf, float *denbuf) {
denbuf[i] += 1.0f; denbuf[i] += 1.0f;
nsamps--;
} }
} }
""") """)
@ -118,7 +125,7 @@ def silly(features, cp):
iter = IterCode(features) iter = IterCode(features)
code = assemble_code(BaseCode, mwc.MWC, iter, iter.packer) code = assemble_code(BaseCode, mwc.MWC, iter, iter.packer)
print code print code
mod = SourceModule(code) mod = SourceModule(code, options=['-use_fast_math'], keep=True)
info = iter.packer.pack(cp=cp) info = iter.packer.pack(cp=cp)
print info print info

View File

@ -3,7 +3,6 @@ The multiply-with-carry random number generator.
""" """
import numpy as np import numpy as np
import tempita
from cuburn.code.util import * from cuburn.code.util import *

40
cuburn/code/variations.py Normal file
View File

@ -0,0 +1,40 @@
var_nos = {}
var_code = {}
def _var(num, name = None):
def _var1(func):
if name:
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',
# input variables 'tx' and 'ty', and output 'ox' and 'oy' available
# from the calling context. Each statement will be placed inside brackets,
# to avoid namespace pollution.
@_var(0)
def linear():
return """
ox += tx * w;
oy += ty * w;
"""
@_var(1)
def sinusoidal():
return """
ox += w * sin(tx);
oy += w * sin(ty);
"""
@_var(2)
def spherical():
return """
float r2 = w / (tx*tx + ty*ty);
ox += tx * r2;
oy += ty * r2;
"""

View File

@ -219,12 +219,11 @@ class Features(object):
self.non_box_temporal_filter = genomes[0].temporal_filter_type self.non_box_temporal_filter = genomes[0].temporal_filter_type
self.palette_mode = genomes[0].palette_mode and "linear" or "nearest" self.palette_mode = genomes[0].palette_mode and "linear" or "nearest"
xforms = [XForm.parse(cp) for cp in genomes] assert len(set([len(cp.xforms) for cp in genomes])) == 1, ("genomes "
assert len(xforms[0]) == len(xforms[-1]), ("genomes must have same " "must have same number of xforms! (use flam3-genome first)")
"number of xforms! (try running through flam3-genome first)") self.nxforms = len(genomes[0].xforms)
self.xforms = [XFormFeatures([x[i] for x in xforms], i) self.xforms = [XFormFeatures([cp.xforms[i] for cp in genomes], i)
for i in range(len(xforms[0]))] for i in range(self.nxforms)]
self.nxforms = len(self.xforms)
if any(lambda cp: cp.final_xform_enable): if any(lambda cp: cp.final_xform_enable):
raise NotImplementedError("Final xform") raise NotImplementedError("Final xform")
@ -242,8 +241,10 @@ class XFormFeatures(object):
self.id = xform_id self.id = xform_id
any = lambda l: bool(filter(None, map(l, xforms))) any = lambda l: bool(filter(None, map(l, xforms)))
self.has_post = any(lambda xf: getattr(xf, 'post', None)) self.has_post = any(lambda xf: getattr(xf, 'post', None))
self.vars = set([n for x in xforms for n in Variations.names self.vars = set()
if getattr(x, n, None)]) for x in xforms:
self.vars = (
self.vars.union(set([i for i, v in enumerate(x.var) if v])))
class Camera(object): class Camera(object):
"""Viewport and exposure.""" """Viewport and exposure."""

View File

@ -1,28 +0,0 @@
class Variations(object):
"""
You know it.
"""
# TODO: precalc
shortname = "variations"
def __init__(self, features):
self.features = features
names = [ "linear", "sinusoidal", "spherical", "swirl", "horseshoe",
"polar", "handkerchief", "heart", "disc", "spiral", "hyperbolic",
"diamond", "ex", "julia", "bent", "waves", "fisheye", "popcorn",
"exponential", "power", "cosine", "rings", "fan", "blob", "pdj",
"fan2", "rings2", "eyefish", "bubble", "cylinder", "perspective",
"noise", "julian", "juliascope", "blur", "gaussian_blur",
"radial_blur", "pie", "ngon", "curl", "rectangles", "arch", "tangent",
"square", "rays", "blade", "secant2", "twintrian", "cross", "disc2",
"super_shape", "flower", "conic", "parabola", "bent2", "bipolar",
"boarders", "butterfly", "cell", "cpow", "curve", "edisc", "elliptic",
"escher", "foci", "lazysusan", "loonie", "pre_blur", "modulus",
"oscilloscope", "polar2", "popcorn2", "scry", "separation", "split",
"splits", "stripes", "wedge", "wedge_julia", "wedge_sph", "whorl",
"waves2", "exp", "log", "sin", "cos", "tan", "sec", "csc", "cot",
"sinh", "cosh", "tanh", "sech", "csch", "coth", "auger", "flux", ]

View File

@ -45,8 +45,8 @@ def main(args):
bins = np.minimum(bins, 255) bins = np.minimum(bins, 255)
bins = bins.astype(np.uint8) bins = bins.astype(np.uint8)
#if '-g' not in args: if '-g' not in args:
# return return
imgbuf = (accum * 255).astype(np.uint8) imgbuf = (accum * 255).astype(np.uint8)