Pull to refresh

Context Free: язык для генерации изображений

Reading time 6 min
Views 3.7K


Эта картина сгенерирована программой Context Free по следующему описанию:

startshape T
// FLIGIZ
background{b -1}
tile {s 2.5}
rule T {3*{r 120 hue 30}S{x .3}}
rule S 3{CIRCLE{hue 30}4*{r 20 b.007 sat .1}S[s.3.7y.9]}
rule S {CIRCLE{hue 15}9*{r 20 b.05 hue -3}S[s.3.7y.9]}
rule S {S{flip 90}}

Для описания изображений в программе Context Free используется язык программирования CFDG с контекстно-свободной грамматикой, созданный специально для генерации изображений. Грубо говоря, это набор базовых правил со всего двумя терминалами CIRCLE и SQUARE. Рендеринг осуществляется с помощью библиотеки Anti-Grain Geometry Максима Шеманарева.

Вот несколько других картин из галереи Context Free Art. Все работы в галерее опубликованы под лицензией Creative Commons (по клику — ссылка на оригинал).


Код
 startshape START
 
rule START {
CIRCLE{}
RAINBOW_SPLIT{hue 0 sat 0 b 0}
RAINBOW_SPLIT{r 180 hue 120 sat 0}
}
 
rule RAINBOW_SPLIT{
RAINBOW{}
}
 
rule RAINBOW_SPLIT{
RAINBOW_MINI{alpha -.9 y -.4 s .2 flip 1 b -1}
RAINBOW{}
}
 
rule RAINBOW{
 SHADOW{}
CIRCLE{}
HIGHLIGHT{}
 
RAINBOW_SPLIT{hue 1.5 sat .1  s .99 b .001 x .09 r 2.8 }
}
 
 
rule RAINBOW_MINI{
 SHADOW{}
CIRCLE{}
  HIGHLIGHT{}
 
 
RAINBOW_MINI{alpha .1 hue 2 s .98  x .3 r 2.8 }
}
 
 
rule RAINBOW_MINI .04{
 SHADOW{}
CIRCLE{}
 HIGHLIGHT{}
 
 
RAINBOW_MINI{flip 1 alpha .1 hue 5 s .99  x .3 r 2.8 }
}
 
 
 
rule SHADOW {
CIRCLE{hue 3 b -1 sat -.6 s 1.1 y .04 alpha -.7}
 
}
 
rule HIGHLIGHT {
CIRCLE{ hue 3 b .7 sat -.3 s .98 y .05}
CIRCLE{ hue 3 b 2 sat -.7 s .9 y .01}
} 



Код
/*
Ancient Scripts by Leaf Garland
*/
 
background { hue 40 sat 0.2 b -0.2}
 
startshape LINES
 
rule LINES {
    20 * {y -90} NEWLINE {hue 90 sat 0.7 b 0.2 a -0.5}
}
 
rule NEWLINE {
    LINE {y 0}
}
 
rule NEWLINE {
    LINE {y 20}
}
 
rule NEWLINE {
    LINE {y 30}
}
 
rule LINE {
    50 * {x 36} CHAR {}
}
 
rule CHAR 0.3 { 
    // space
}
 
rule CHAR {
    2 * {x 20 flip 180} STROKE {r 90}
    2 * {y 20 flip 180} STROKE {}
}
 
rule CHAR {
    4 * {r 60} STROKE {}
}
 
rule CHAR {
    STROKE {r 90}
    3 * {y 10 flip 180} STROKE {}
}
 
rule STROKE {
    B {}
}
 
rule STROKE {
    B {flip 90}
}
 
rule B 30 {
    MARK {}
    B {x .6 r 10}
}
 
rule B 30 {
    MARK {}
    B {x .6 r 3}
}
 
rule B 250 {
    MARK {}
    B {x .9}
}
 
rule B 10 {
    MARK {}	
    B {flip 90}
}
 
rule B 10 { }
 
 
rule MARK 3 {
    CIRCLE {}
}
 
rule MARK {
    CIRCLE {s 2}
}
 
rule MARK {
    SQUARE {s 3}
}
 
rule MARK {
    CIRCLE {s 4}
}
 
rule MARK 0.01 {
    CIRCLE {s 7}
}



Код
background{b -1} startshape init
rule init{time{z 0 r -90 sat .5 |h 220}}
 
 
//CONTROL
 
 
rule time 40 {draw{} time{r 1 s .9991 b .1| a .1|}}
rule time    {slow{|b -1 |a 1 |sat 1}}
rule time    {slow{|b 1 |a -1 |sat 1}}
 
rule slow 20 {draw{} slow{ r 1 s .9991 b .03| a .03| h -1}}
rule slow    {time{|sat -1}}
 
 
//IMAGING
 
 
rule draw{
    SQUARE[z 0 x 1 s .27 .018 x -.5 a 1 h 1|]
    stars{z 1 x .91}
    cloud[z 2 x .83 s .17 x .5 h .7| a 1 sat .3|]
    ground[z 3 x .73 s .1 x .5]
}
 
 
rule ground{
    SQUARE[s 1 .18 a 1 b -.5]
    highlight{s 1 .14} 
    stuff{z 1}
}
 
 
rule stuff 5 {block[z 79 x .5 s .7225 .2 x -.5 a 1]}
rule stuff  {bush[z 86 x -.5 s 1.62 r -90 b -.7| a 1]}
rule stuff  {}
 
 
rule block 2 {block{b -.1|}}
rule block 3 {block[z -4 x .5 s .7225 x -.5 b .4|]}
rule block 1 {block2{} block[z -4 x .5 s .64 x -.5 b .4|]}
 
rule block2 {block3[x -.5 s .5 x .5 h 12]}
rule block2 {block3[x -.5 s .5 x .5 h -12]}
rule block3{SQUARE{} gleam{}}
 
rule gleam{}
rule gleam 2 {highlight{a 1}}
rule highlight{SQUARE[z 50 x .5 s .02 1 x -.5 b 1]}
 
 
rule bush 2 {bush[z -2 y .617 s .85 y -.617 b .3|]}
rule bush {tree{h 180 sat -.4 b -.7}}
rule tree {
    SQUARE{y .08 s .064 .16}
    fork{y .155}
    fork{y .155 f 90}
}
rule branch{tree{}}
rule branch 3 {
    SQUARE{y .192 s .064 .384}
    fork{y .38}
    fork{y .38 f 90}
}
rule fork{branch{r 22 s .7}}
rule fork{branch{r 33 s .7}}
rule fork 0.2 {}
 
 
rule stars   {}
rule stars 6 {star1{sat -1 h .99|} stars{}}
rule star1   {star1{sat .12}}
rule star1 6 {star1{r 139}}
rule star1   {star2{}}
rule star2   {star3{x .05 s .8}}
rule star2   {star3{}}
rule star3 9 {star3{s .8}}
rule star3   {CIRCLE{x .03 s .007 b 1 h -.55|}}
 
 
rule cloud 25 {}
rule cloud{puff[ x -.6 s .25 .6 x .5 a -.95 h 170 sat .2]}
rule puff 7 {TRIANGLE{} puff{x .5 r 20 s .91}}
rule puff  { TRIANGLE{} puff{x .5 f 0 s .91}}
rule puff 5 {puff{x .5 r 20 s .9} puff{z 1 s .9 sat -.2 b
.02}}



Код
//CKL
 
startshape MAIN
 
CF::Background = [hue 0 sat 0.84 b -0.9]
CF::MinimumSize = 1
 
// how far to move each tree part in the local Y axis
GTreePartMove = 0.02
 
// how much to scale each successive tree part
GTreePartScale = 0.990
 
// Min and max length for the size of the trunk
MaxTrunkDepth() = randint(10,40)
 
// Min and max length for a branch coming off the trunk
MaxTrunkBranchDepth() = randint(20,90)
 
// Min and max length for a leaf branch
MaxLeafBranchDepth() = randint(50,200)
 
// returns a random int between (-High,-Low) and (Low,High)
RandRange(Low,High) = select( randint(), -1, 1 ) *
randint(Low,High)
 
// Returns a rotation angle for a new branch
NewBranchRotation() = randint(25,50)
 
// Returns a random scale for a new branch
NewBranchScale() = rand(0.6,0.9)
 
NewStemRotation() = RandRange(30,50)
 
NewSteamScale() = rand(0.4,0.6)
 
LeafScale(Depth) = Depth / 250
 
// returns a random rotaiton amount of a single branch, to
give them a less rigid shape
BranchTwistSmall() = randint(10) - 5
BranchTwistLarge() = RandRange(10,25)
 
 
shape MAIN 
    rule 1 {
        SKY [ z -2 s 100 ]
        SUN [ z -1 s 400 ]
        TREE [ x -0.1 y -0.75 ]
        GRASS [ x -1 y -1 ]
    }
 
shape SKY
    rule 1 {
        CIRCLE [ s rand(0.02,0.04) rand(0.01,0.03) sat 1 a
-0.02 ]
        SKY [ s 0.9990 b 0.0005 hue 0.018 a -0.001 ]
    }
 
shape SUN
    rule 1 {
        CIRCLE [ s rand(0.001,0.002) sat 0.84 b 1 a -0.95 ]
        SUN [[ r 40 s 0.9990 y 0.0001 hue (0.02,48) ]]
    }
 
shape GRASS
    rule 1 {
        loop 20 [ y 0.01 ]
            loop 200 [ x 0.01 ]
                GRASSBLADE [ x rand(0.02) y rand(0.1) ]
    }
 
shape GRASSBLADE
    rule 1 {
        CIRCLE [ s 0.02 a -0.9 ]
        GRASSBLADE [ y 0.01 s 0.95 r BranchTwistSmall() ]
    }
 
shape TREE
    rule 1 {
        TRUNK( 0, MaxTrunkDepth() ) [ r ( randint(20) - 10 )
]
    }
 
shape TRUNK( natural Depth, natural EndDepth )
    rule 20 {
        TreePart[]
        if ( Depth > EndDepth )
        {
            TRUNKSPLIT(Depth) []
        }
        else
        {
            TRUNK( Depth + 1, EndDepth ) [ y GTreePartMove s
GTreePartScale]
        }
    }
    rule 5 {
        TRUNK( Depth + 1, EndDepth ) [ r BranchTwistSmall()
]
    }
 
shape TRUNKSPLIT( natural Depth )
    rule 1 {
        // split right
        TRUNKBRANCH( Depth, Depth + MaxTrunkBranchDepth() )
[ r NewBranchRotation() s NewBranchScale() ]
        TRUNKBRANCH( Depth, Depth + MaxTrunkBranchDepth() )
[ r randint(-20,0) s NewBranchScale() ]
    }
    rule 1 {
        // split left
        TRUNKBRANCH( Depth, Depth + MaxTrunkBranchDepth() )
[ r -NewBranchRotation() s NewBranchScale() ]
        TRUNKBRANCH( Depth, Depth + MaxTrunkBranchDepth() )
[ r -randint(-20,0) s NewBranchScale() ]
    }
 
shape TRUNKBRANCH( natural Depth, natural EndDepth )
    rule 1000 {
        TreePart[]
        if ( Depth > EndDepth )
        {
            TRUNKBRANCHSPLIT(Depth) []
        }
        else
        {
            TRUNKBRANCH( Depth + 1, EndDepth ) [ y
GTreePartMove s GTreePartScale]
        }
    }
    rule 200 {
        TRUNKBRANCH( Depth + 1, EndDepth ) [ r
BranchTwistSmall() ]
    }
    rule 50 {
        TRUNKBRANCH( Depth + 1, EndDepth ) [ r
BranchTwistLarge() ]
    }
    rule 1 {
        TRUNKBRANCH( Depth + 1, EndDepth ) [ ]
        LEAFBUNCH( Depth ) [ r NewBranchRotation() ]
    }
    rule 1 {
        TRUNKBRANCH( Depth + 1, EndDepth ) [ ]
        LEAFBUNCH( Depth ) [ r -NewBranchRotation() ]
    }
 
shape TRUNKBRANCHSPLIT( natural Depth )
    rule 1 {
        // split right
        LEAFBRANCH( Depth, Depth + MaxLeafBranchDepth() ) [
r NewBranchRotation() s NewBranchScale() ]
        LEAFBRANCH( Depth, Depth + MaxLeafBranchDepth() ) [
r randint(-20,0) s NewBranchScale() ]
    }
    rule 1 {
        // split left
        LEAFBRANCH( Depth, Depth + MaxLeafBranchDepth() ) [
r -NewBranchRotation() s NewBranchScale() ]
        LEAFBRANCH( Depth, Depth + MaxLeafBranchDepth() ) [
r -randint(-20,0) s NewBranchScale() ]
    }
 
shape LEAFBRANCH( natural Depth, natural EndDepth )
    rule 50 {
        TreePart[]
        if ( Depth > EndDepth )
        {
            //TRUNKBRANCHSPLIT(Depth) []
        }
        else
        {
            LEAFBRANCH( Depth + 1, EndDepth ) [ y
GTreePartMove s GTreePartScale]
        }
    }
    rule 50 {
        LEAFBRANCH( Depth + 1, EndDepth ) [ r
BranchTwistSmall() ]
    }
    rule 5 {
        LEAFBUNCH( Depth ) []
    }
    //rule 1 {
    //	TRUNKBRANCHSPLIT(Depth) []
    //}
 
shape LEAFBUNCH( natural Depth )
    rule 100 {
        TreePart [ ]
        LEAFBUNCH( Depth + 1 ) [ y GTreePartMove s
GTreePartScale a -0.01 r BranchTwistSmall() ]
    }
    rule 25 {
        LEAFSTEM( Depth ) [ r NewStemRotation() s
NewSteamScale() ]
        LEAFBUNCH( Depth ) []
    }
    rule 1 {
        // split right
        LEAFBUNCH( Depth ) [ r NewBranchRotation() s
NewBranchScale() ]
        LEAFBUNCH( Depth ) [ r randint(-20,0) s
NewBranchScale() ]
    }
    rule 1 {
        // split left
        LEAFBUNCH( Depth ) [ r -NewBranchRotation() s
NewBranchScale() ]
        LEAFBUNCH( Depth ) [ r -randint(-20,0) s
NewBranchScale() ]
    }
 
shape LEAFSTEM( natural Depth )
    rule 100 {
        TreePart []
        LEAFSTEM( Depth + 1 ) [ y GTreePartMove s 0.98 a
-0.05 ]
    }
    rule 25 {
        LEAFSTEM( Depth + 1 ) [ r BranchTwistSmall() ]
    }
    rule 25 {
        LEAF(Depth) [ r BranchTwistSmall() ]
        LEAFSTEM(Depth) []
    }
 
shape LEAF( natural Depth )
    rule 1 {
        LEAFSTAMP [[ s LeafScale(Depth) y 0.5 ]]
    }
 
shape LEAFSTAMP
    rule 1 {
        CIRCLE [ a -0.1 s rand(0.1,0.8) 1 ]
    }
 
shape TreePart
    rule 1 {
        CIRCLE [ s 0.1 ]
        CIRCLE [ s 0.1 x +0.005 a -0.9 ]
        CIRCLE [ s 0.1 x -0.005 a -0.9 ]
        CIRCLE [ s 0.1 x +0.0075 a -0.9 ]
        CIRCLE [ s 0.1 x -0.0075 a -0.9 ]
        CIRCLE [ s 0.1 x +0.0125 a -0.9 ]
        CIRCLE [ s 0.1 x -0.0125 a -0.9 ]
    }


Программа Context Free распространяется под лицензией GPL, скачать её можно здесь (Win / Mac / Linux), документация.

Добавим, что это не единственная инициатива по созданию удобной грамматики для генерации изображений. Например, вот open source проект Structure Synth для 3D-графики.

UPD. Оказывается, про Context Free на Хабре писали аж в 2008 году! Спасибо Imposeren за ссылку.
Tags:
Hubs:
+143
Comments 31
Comments Comments 31

Articles