Advertisement
Guest User

Untitled

a guest
Mar 28th, 2015
224
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.00 KB | None | 0 0
  1. **Please Note:** The sketches take some time to run upon loading the page. It may freeze your browser but it should return to normal shortly.
  2.  
  3. # Design Programming (DECO1012) Assessment One
  4.  
  5.  
  6. **Author**: Harry Morris (Unikey: hmor5172)
  7.  
  8. **Chosen Theme:** Movement and Energy
  9.  
  10. **Chosen Format:** Poster, Apparel (T-shirt, bags, etc)
  11.  
  12. ## Introduction and Ideation ##
  13.  
  14. As both a DJ and a musician, the ideas of movement and energy are incredibly important to me. I view music as one of the strongest instigators of movement, and, in particular, the genre of 'Techno' is among the most powerful. It was decided to represent the movement, energy and ideals of Techno in a visual manner for this project, as if the client were a Techno record label looking to promote an artist.
  15.  
  16. ## Breakdown of Themes ##
  17. In order to assist the development process, a set of themes is considered to guide the creative process. The genre of Techno is extremely broad and covers a range of themes, but there are a few that stick out.
  18.  
  19. * Darkness: Techno is among the darkest genres of music produced. This darkness is core to the genre and is its major distinction from other genres of dance music. This is commonly expressed as being 'monochrome' or 'black', and this provides a useful visual analogy.
  20.  
  21. * Texture and Atmosphere: Techno, since its inception, has often been noted for the high-energy atmosphere it creates. This is typically achieved, musically, through the combination of thick textures, layered and layered. Each layer, whilst quite simple, works with the others to create a product that is greater than the sum of its parts. Quite often these textures are described as (and sometimes are quite literally) noisy or creating a cacophany, which may translate into visual terms in a powerful manner.
  22.  
  23. * Repetition and Simplicity: In order to create the high-energy atmosphere and movement central to dance music, techno employs significant repetition in it's structure, and typically of simple parts. This repetitive minimalism is crucial to the genre, and is a similarly powerful visual device. Likewise the simplicity of the elements within a track can be metaphorically represented by basic geometry and linework, for its 'purity'. This is often cited as creating a sense of 'order' in what is otherwise a very chaotic musical form.
  24.  
  25. With the analysis of my central themes complete, it was time to find inspiration.
  26.  
  27. ## Inspiration ##
  28. Techno music has a wealth of strong visual components, particularly record covers and event flyers, and these formed the basis of my inspiration. Much of the inspiration that follows seems to strongly represent the themes express above and my extrapolation into visual terms can be seen clearly. The aspects of each image that I enjoyed are written.
  29.  
  30. * [Justin Perkovy - Vice](http://www.residentadvisor.net/images/cover/tr-392036.jpg)
  31. * Strong geometric forms.
  32. * Abstract background
  33. * Repetitive geometry - rhythmic qualities.
  34. * Absence of colour - metaphor for bleakness.
  35. * [Inigo Kennedy - Insistence](http://www.junodownload.com/plus/wp-content/uploads/2013/06/inigo_kennedy_590.jpg)
  36. * Absence of colour
  37. * Strong, abstract, simple and repetitive geometry suggest rhythm.
  38. * [Dadub - You Are Eternity](http://beatsperminute.com/wp-content/uploads/2013/04/dadub-you-are-eternity.jpg)
  39. * Abstract, black and white background creates a sense of rhythm.
  40. * [Lucy - Wordplay for Working Bees](http://3.bp.blogspot.com/-VyzQTR7Ru-E/TvvchUJgRRI/AAAAAAAABjw/wIFNitFLAhQ/s400/working%2Bbees.jpg)
  41. * Noisy, black and white background is a very strong visual metaphor for texture.
  42. * Strong geometric form created from simple, repeated shapes - again representative of the repetition in the music.
  43. * [Pfirter - Ahora](http://electropeople.org/uploads/posts/2013-05/1370008365_7329578.jpg)
  44. * Symmetry creates a powerful impression and creates a sense of order in an otherwise chaotic image.
  45. * Sense of rhythm created by repetitive texture.
  46. * [Iueke - Alecot](http://www.junodownload.com/plus/wp-content/uploads/2013/04/IUEKE-ALECOT-ARTWORK.jpg)
  47. * Extremely powerful and complex patterns created from the intersection of basic geometry.
  48.  
  49.  
  50. ## Idea Testing ##
  51.  
  52. To begin with, a list of layers was developed based on the values investigated above. By developing a composition using multiple layers, it was hoped to represent the thick layers of textures used throughout the genre. These include:
  53.  
  54. * Noise Background
  55. * Generating noise is a simple process that adds significant texture to an image. Similarly, it contains connotations of decay and darkness, which aligns well with the values of techno.
  56. * Noise details
  57. * In order to create a more interesting background, an extra layer of noise that produces sharper details should be included.
  58. * Grid
  59. * A grid is a perfect form that represents the inherent order in Techno music, juxtaposed against the chaos of the noise below it. It creates a strong sense of rhythm in its strong repetition.
  60. * Circle pattern
  61. * Much like the grid, the circle is commonly seen as the purest geometric form. This adds a rhythm that also represents the musical simplicity of the genre.
  62. * Triangle patterns
  63. * Again, a repetitive application of a simple shape, the overlapping of the simple triangle form can create extremely strong, complicated patterns. This is analogous to the 'greater than the sum of its parts' theory of Techno music.
  64. * Linework patterns
  65. * Linework patterns, much like the triangles used above, can create extremely strong visual forms, particularly when repetition is used. Similarly, these form 'vectors' in the image, leading your eye around the composition and creating a sense of movement.
  66.  
  67. ### Mockup ###
  68.  
  69. In order to evaluate the ideas generated, a mock-up was created using Adobe Photoshop and Illustrator, embodying all of the above as a test of the aesthetic created.
  70.  
  71. [First Revision](http://i.imgur.com/d65CmQq.jpg)
  72.  
  73. The first stage focused on evaluating the first few components, primarily the ones with less visual engagement. The image was created using significant processing of images of clouds and nebulae, and the repetition of patterns.
  74.  
  75.  
  76.  
  77. [Second Revision](http://i.imgur.com/wSVhitc.jpg)
  78.  
  79. In the second stage of the process, the final layers - the triangles and linework - were added. These components were created using tools in Adobe Illustrator suited to the creation of repetitive elements. The effect created was deemed incredibly effective.
  80.  
  81. The elements layered together in the final composition created a work that I found represented the values desired perfectly and in a visually-pleasing manner. It was decided that this set of layers would be used in the final composition.
  82.  
  83. ## Sketch Process ##
  84.  
  85. After the evaluation of the mockup, it was time to develop a sketch. Each component of the composition was developed in isolation before being compiled into the main sketch.
  86.  
  87. ### Noise Background / Detail ###
  88. Initial experiments with the random() function produced noise that was far too unpleasant - much like static.
  89.  
  90. ~~~
  91. /** @peep sketch */
  92. float redFactor = 0.75f;
  93. float blueFactor = 0.95f;
  94. float greenFactor = 0.5f;
  95. float alphaFactor = 0.82f;
  96.  
  97. size(400, 400);
  98. background(0);
  99.  
  100. for (int x = 0; x < width; x += 1) {
  101. for (int y = 0; y < height; y += 1) {
  102. float noiseVal = random(0, 1);
  103. color noiseColor = color(redFactor * noiseVal * 255, greenFactor * noiseVal * 255, blueFactor * noiseVal * 255, alphaFactor * noiseVal * 255);
  104. // Draw the pixel
  105. stroke(noiseColor);
  106. point(x, y);
  107. }
  108. }
  109. ~~~
  110.  
  111. Despite a more complicated implementation, the perlin-noise based noise() function provided a far better result. Unfortunately, it required much more tweaking to get a good result, experimenting with the noise detail level and the 'frequency' of the noise. Eventually an algorithm that produced reliably interesting noise was produced.
  112.  
  113. ~~~
  114. /** @peep sketch */
  115. // Colour of the noise
  116. float redFactor = 0.75f;
  117. float blueFactor = 0.95f;
  118. float greenFactor = 0.5f;
  119. float alphaFactor = 0.82f;
  120.  
  121.  
  122. int noiseDetails = 88;
  123. float noiseFrequency = 32;
  124.  
  125.  
  126. size(400, 400);
  127. background(0);
  128.  
  129. for (int x = 0; x < width; x += 1) {
  130. for (int y = 0; y < height; y += 1) {
  131. float noiseVal = noise(x / noiseFrequency, y / noiseFrequency);
  132.  
  133. // Generate the colour from noise
  134. color noiseColor = color(redFactor * noiseVal * 255, greenFactor * noiseVal * 255, blueFactor * noiseVal * 255, alphaFactor * noiseVal * 255);
  135.  
  136. // Draw the pixel
  137. stroke(noiseColor);
  138. point(x, y);
  139.  
  140. // Detail layer
  141. noiseVal = pow(noiseVal, 4);
  142.  
  143. noiseColor = color(redFactor * noiseVal * 255, greenFactor * noiseVal * 255, blueFactor * noiseVal * 255, alphaFactor * noiseVal * 255);
  144.  
  145. // Draw the pixel
  146. stroke(noiseColor);
  147. point(x, y);
  148. }
  149. }
  150. ~~~
  151.  
  152. ### Grid ###
  153. In the process of creating this piece of code, it was noted that, in order to simplify the code, this part of the program could utilize the same for loop as the noise algorithm created prior did. As such it was developed in a way that may appear suboptimal, but would work well in the complete sketch. A simple set of random ranges was defined for the grid, and it was implemented. It was difficult to evaluate the quality of this part as it was designed to work as part of the entire composition.
  154.  
  155. ~~~
  156. /** @peep sketch */
  157. int gridSize = (int)random(4, 40);
  158.  
  159.  
  160. size(400, 400);
  161. background(0);
  162.  
  163. for (int x = 0; x < width; x += 1) {
  164. for (int y = 0; y < height; y += 1) {
  165. if (x % gridSize == 0 || y % gridSize == 0) {
  166. // Draw the pixel
  167. stroke(255, 40);
  168. point(x, y);
  169. }
  170. }
  171. }
  172. ~~~
  173.  
  174. ### Circle Pattern ###
  175. The circle pattern similarly was implemented in a simple manner. The range of randomness was tweaked until a good range was found. Much like the grid, this layer was designed to work as part of the composition and as such was not very pleasing in itself.
  176.  
  177. ~~~
  178. /** @peep sketch */
  179. int circleSpacing = (int)random(8, 64);
  180. int circleSize = (int)random(2, 5);
  181.  
  182. size(400, 400);
  183. background(0);
  184. noStroke();
  185. fill(255, 100);
  186. for (int x = 0; x < width; x += 1) {
  187. for (int y = 0; y < height; y += 1) {
  188. if (x % circleSpacing == 0 && y % circleSpacing == 0) {
  189. ellipse(x, y, circleSize, circleSize);
  190. }
  191. }
  192. }
  193. ~~~
  194.  
  195. ### Triangle patterns
  196. This portion of the project was largely based on the mock-up created earlier. A simple repetition of triangles in the vertical direction was developed. In order to produce a stronger composition, it was decided to redraw the triangles on both sides, rather than just the centre. A series of random ranges was defined that produced an aesthetically pleasing outcome in most cases.
  197.  
  198. ~~~
  199. /** @peep sketch */
  200. int x = 32;
  201. float y = random(-32, 32);
  202. float w = random(64, 256);
  203. float h = random(64, 256);
  204. float s = random(16, 64);
  205. float offs = 400 - (x * 2);
  206.  
  207. size(400, 400);
  208. background(0);
  209. noFill();
  210. stroke(255, 40);
  211.  
  212.  
  213. for (int i = 0; i < 16; i++) {
  214. //Draw the triangles on the left
  215. triangle(x, y + i * s, x - w / 2, y + h + i * s, x + w / 2, y + h + i * s);
  216.  
  217. //Draw triangles in the middle
  218. pushMatrix();
  219. translate(200, 0);
  220. triangle(0, y + i * s, 0 - w / 2, y + h + i * s, 0 + w / 2, y + h + i * s);
  221. popMatrix();
  222.  
  223. //Offset using translate to save mathz.
  224. pushMatrix();
  225. translate(offs, 0);
  226. triangle(x, y + i * s, x - w / 2, y + h + i * s, x + w / 2, y + h + i * s);
  227. popMatrix();
  228. }
  229. ~~~
  230.  
  231. ### Linework Patterns ###
  232. This part of the project required some more complex thought to translate into a Processing sketch and to apply randomness. The first attempt drew lines at random, choosing two points anywhere on the canvas.
  233.  
  234. ~~~
  235. /** @peep sketch */
  236. size(400, 400);
  237. background(0);
  238. noFill();
  239. stroke(255, 40);
  240.  
  241. for (int i = 0; i < 48; i++) {
  242. line(random(0, 400), random(0, 400), random(0, 400), random(0, 400));
  243. }
  244. ~~~
  245.  
  246. The result this produced was unappealing and overly chaotic. Attempts were made to constrain the randomness, but it still appeared without thought and uninterestng.
  247.  
  248. In order to create visually interesting patterns, it was decided that a complex recursive algorithm that made use of significant randomness. A simple algorithm was created that created lines of diminishing length, rotating with each iteration. As an experiment, this was mirrored across the Y-axis to create a sense of greater repetition. Additionally, it was decided to layer a few instances of this algorithm ontop of one another, with a low alpha value. The effect this created was powerful and was decided upon.
  249.  
  250. ~~~
  251. /** @peep sketch */
  252. void setup() {
  253. size(400, 400);
  254. background(0);
  255. noFill();
  256. stroke(255, 40);
  257. }
  258.  
  259. void draw() {
  260. for (int i = 0; i < 48; i++) {
  261. tree(200, 200, (int)random(8, 256), 0f, 8);
  262. }
  263. noLoop();
  264. }
  265.  
  266. float angles[] = {
  267. 45f, 135f, 225f, 315f
  268. };
  269. // Recursive algorithm to draw a tree that branches.
  270. void tree(float x, float y, int hyp, float lastAngle, int decay) {
  271. float newx = 0f;
  272. float newy = 0f;
  273. float angle = lastAngle;
  274.  
  275. angle = angles[(int)random(0, 4)];
  276.  
  277. newx = round(x + cos(radians(angle)) * hyp);
  278. newy = round(y + sin(radians(angle)) * hyp);
  279.  
  280. line(x, y, newx, newy);
  281. // Mirror the line
  282. line(width / 2 - (x - width / 2), y, width / 2 - (newx - width / 2), newy);
  283.  
  284. // Decay
  285. int newLen = hyp - decay;
  286.  
  287. // Have we decayed past the stop point?
  288. if (newLen > 8)
  289. tree(newx, newy, newLen, angle, decay);
  290. }
  291. ~~~
  292.  
  293. ### First Integration: ###
  294.  
  295. After each component was complete, it was possible to create the final composition by combining them. To accomplish the goal of repetition and textured layers, the program was made to draw itself a number of times, one on top of the other, to produce a result with greater depth and stronger texture.
  296.  
  297. ~~~
  298. /** @peep sketch */
  299. // ------------------------------------
  300. // Constant Variables
  301. // ------------------------------------
  302.  
  303. // Number of iterations to complete.
  304. int iterations = 2;
  305.  
  306. // Tree parameters
  307. // Number of trees to run per iteration
  308. int treesMin = 20;
  309. int treesMax = 40;
  310.  
  311. // The amount to decay by each iteration
  312. int treeDecay = 4;
  313.  
  314. //The point at which to stop the recursion
  315. int treeStop = 8;
  316.  
  317. //The size of the starting branch
  318. int branchMin = 1;
  319. int branchMax = 6;
  320. int branchSize = 32;
  321.  
  322. color treeColor = color(200, 200, 200, 70);
  323.  
  324. // Triangle parameters
  325. // Number of triangles.
  326. int trisMin = 8;
  327. int trisMax = 24;
  328. float triX = 48;
  329.  
  330. // Stating Y position range
  331. float triYMin = -32;
  332. float triYMax = 128;
  333.  
  334. // Width range
  335. float triWMin = 64;
  336. float triWMax = 256;
  337.  
  338. // Triangle range
  339. float triHMin = 64;
  340. float triHMax = 256;
  341.  
  342. // Vertical spacing between the triangles
  343. float triSpaceMin = 32;
  344. float triSpaceMax = 64;
  345.  
  346. color triColor = color(200, 200, 200, 70);
  347.  
  348. float centreWidth = width / 2;
  349.  
  350. // Noise parameters
  351. // Colour of the noise
  352. float redFactor = 0.85f;
  353. float blueFactor = 0.795f;
  354. float greenFactor = 0.92f;
  355. float alphaFactor = 0.82f;
  356.  
  357. // The number of octaves used in the noise algoroithm - sharper detail
  358. int noiseDetails = 88;
  359.  
  360. // Frequency of the noise - higher value = smoother noise.
  361. float noiseFrequency = 256;
  362.  
  363. int noiseAlpha = (int)random(120, 190);
  364.  
  365. // Grid parameters
  366. int gridAlpha = (int)random(12, 58);
  367. // Width of each grid cell
  368. int gridSize = (int)random(4, 40);
  369.  
  370. // Circle pattern parameters
  371. int circleSpacing = (int)random(14, 38);
  372. int circleSize = 2;
  373. int circleAlpha = (int)random(40, 80);
  374.  
  375. color bgColor = color(0, 0, 0, 255);
  376.  
  377.  
  378. // ------------------------------------
  379. // Setup
  380. // ------------------------------------
  381. void setup() {
  382. // Setup our canvas
  383. size(400, 400);
  384. smooth();
  385. background(bgColor);
  386. noiseDetail(noiseDetails);
  387. }
  388.  
  389. // ------------------------------------
  390. // Draw loop
  391. // ------------------------------------
  392. void draw() {
  393. // We iterate through the algorithm a few times to create a decayed look with many layers.
  394.  
  395. for (int iter = 0; iter < iterations; iter++) {
  396.  
  397. //Go through every pixel of the screen.
  398. for (int x = 0; x < width; x += 1) {
  399. for (int y = 0; y < height; y += 1) {
  400.  
  401. // Draw noise layer.
  402. // Get the noise value at our position.
  403. float noiseVal = noise(x / noiseFrequency, y / noiseFrequency);
  404.  
  405. // Generate the colour from that.
  406. color noiseColor = color(redFactor * noiseVal * 255, greenFactor * noiseVal * 255, blueFactor * noiseVal * 255, alphaFactor * noiseVal * 255);
  407.  
  408. // Draw the pixel
  409. stroke(noiseColor);
  410. point(x, y);
  411.  
  412. // Detail layer
  413. noiseVal = pow(noiseVal, 4);
  414.  
  415. noiseColor = color(redFactor * noiseVal * 255, greenFactor * noiseVal * 255, blueFactor * noiseVal * 255, alphaFactor * noiseVal * 255);
  416.  
  417. // Draw the pixel
  418. stroke(noiseColor);
  419. point(x, y);
  420.  
  421. // Draw the circle pattern layer.
  422. noStroke();
  423. fill(255, circleAlpha);
  424. if (x % circleSpacing == 0 && y % circleSpacing == 0) {
  425. ellipse(x, y, circleSize, circleSize);
  426. }
  427.  
  428. // Layer of random black noise ontop to produce grit.
  429. stroke(0, random(0, noiseAlpha));
  430. point(x, y);
  431.  
  432. // Draw the grid layer
  433. // If we are on a grid line
  434. if (x % gridSize == 0 || y % gridSize == 0) {
  435. stroke(255, gridAlpha);
  436. point(x, y);
  437. }
  438. }
  439. }
  440.  
  441. stroke(triColor);
  442. noFill();
  443. // Draw triangles on all but the last iteration so they don't come through too strong.
  444. if (iter < iterations - 1) {
  445.  
  446. //X position - static.
  447. float x = triX;
  448. // Y Position
  449. float y = random(triYMin, triYMax);
  450. // Triangle width
  451. float w = random(triWMin, triWMax);
  452. // Triangle height
  453. float h = random(triHMin, triHMax);
  454. // Spacing
  455. float s = random(triSpaceMin, triSpaceMax);
  456.  
  457. // Position of the righthand side;
  458. float offs = 400 - (x * 2);
  459.  
  460. //Number of triangles to draw.
  461. int numTri = (int)random(trisMin, trisMax);
  462.  
  463. for (int i = 0; i < numTri; i++) {
  464. //Draw the triangles on the left
  465. triangle(x, y + i * s, x - w / 2, y + h + i * s, x + w / 2, y + h + i * s);
  466.  
  467. //Draw triangles in the middle
  468. pushMatrix();
  469. translate(200, 0);
  470. triangle(0, y + i * s, 0 - w / 2, -y + h + i * s, 0 + w / 2, -y + h + i * s);
  471. popMatrix();
  472.  
  473. //Offset using translate to save mathz.
  474. pushMatrix();
  475. translate(offs, 0);
  476. triangle(x, y + i * s, x - w / 2, y + h + i * s, x + w / 2, y + h + i * s);
  477. popMatrix();
  478. }
  479. }
  480.  
  481. stroke(treeColor);
  482. // Draw the tree a few times.
  483. int trees = (int)random(treesMin, treesMax);
  484. for (int i = 0; i < trees; i++) {
  485. tree(centreWidth, height / 2, (int)(random(branchMin, branchMax)) * branchSize, 0f, treeDecay);
  486. }
  487. }
  488. //Do not loop the draw function.
  489. noLoop();
  490. }
  491.  
  492. // Possible angles for the tree branches.
  493. float angles[] = {
  494. 45f, 135f, 225f, 315f
  495. };
  496.  
  497. // Recursive algorithm to draw a tree that branches.
  498. void tree(float x, float y, int hyp, float lastAngle, int decay) {
  499. float newx = 0f;
  500. float newy = 0f;
  501. float angle = lastAngle;
  502.  
  503. // Lookup possible angles in an array - don't let it repeat the same angle or the same angle in reverse.
  504. while (angle == lastAngle)
  505. angle = angles[(int)random(0, 4)];
  506.  
  507. //Calculate the end point.
  508. newx = round(x + cos(radians(angle)) * hyp);
  509. newy = round(y + sin(radians(angle)) * hyp);
  510.  
  511. // Draw the first line
  512. line(x, y, newx, newy);
  513. // Mirror the line
  514. line(width / 2 - (x - width / 2), y, width / 2 - (newx - width / 2), newy);
  515.  
  516. // Decay
  517. int newLen = hyp - decay;
  518.  
  519. // Have we decayed past the stop point?
  520. if (newLen > treeStop)
  521. tree(newx, newy, newLen, angle, decay);
  522. }
  523. ~~~
  524.  
  525. ### Refinement Process ###
  526.  
  527. After compiling the sketches together, the result was deemed far from appropriate. As such, it was neccessary to make adjustments to achieve the final result.
  528.  
  529. - It was noted that the additional detail on the noise layer became distracting as a background, and as such this layer was removed.
  530. - The noise then became very 'plasticky' looking, being too smooth. After adjustment of variables provided unsatisfactory results, an extra pass of noise, this time based on the 'harsher' random() function, was added ontop.
  531. - The grid came through too strong, so it was decided to modulate its opacity based on the noise below it.
  532. - Linework patterns became overly chaotic and had to be toned down significantly. The algorithm also had to be modified to ensure that a more focused result was created.
  533. - Additional factors of randomness were added to the linework algorithm.
  534. - The linework produced a strong pattern in the centre of the image which overpowered the composition. Conditionals were added to prevent these from drawing.
  535. - Linework often started to draw offscreen. Position was reset to the centre if this happened. This also improved the aesthetic qualities.
  536. - The triangles were often overly wide which produced an unpleasant effect. This required adjustment of the range of random values.
  537. - The triangle patterns were overly distracting - it was decided to not draw them on the last iteration as they showed through too much.
  538. - The central column of triangles was flipped to create more interest.
  539. - The circle pattern often looked like it didn't belong in the scene - they were too perfect a form. For each circle, I decided to draw a few black pixels ontop to make it look like they were worn.
  540. - Most of the layers tended to compete with the others - this required adjustment of alpha value ranges to ensure a balanced image.
  541. - An odd bug that resulted in the production of significantly different results between the desktop (Incorrect) and web-versions (Correct) of Processing. The revision above looked far better than as it is shown here. This was fixed, which then required the re-adjustment of most parameters.
  542.  
  543. To assist the above tweaking process, all the 'magic numbers' used in the code were moved into variables at the top of the code, allowing easy adjustment. This allowed me to refine the algorithms until the optimum result was found.
  544.  
  545. ## The Final Revision ##
  546.  
  547. ~~~
  548. /** @peep sketch */
  549. // ------------------------------------
  550. // Constant Variables
  551. // ------------------------------------
  552.  
  553. // Number of iterations to complete.
  554. int iterations = 3;
  555.  
  556. // Tree parameters
  557. // Number of trees to run per iteration
  558. int treesMin = 14;
  559. int treesMax = 25;
  560.  
  561. // The amount to decay by each iteration
  562. int treeDecay = 32;
  563.  
  564. // The point at which to stop the recursion
  565. int treeStop = 16;
  566.  
  567. // The size of the starting branch
  568. int branchMin = 2;
  569. int branchMax = 5;
  570. int branchSize = 32;
  571.  
  572. int branchMargin = 42;
  573.  
  574. // The chance each iteration of the recursion has to decay.
  575. float decayChance = 0.6;
  576.  
  577. color treeColor = color(200, 200, 200, 94);
  578.  
  579. // Triangle parameters
  580. // Number of triangles.
  581. int trisMin = 6;
  582. int trisMax = 16;
  583. float triX = 48;
  584.  
  585. // Stating Y position range
  586. float triYMin = -32;
  587. float triYMax = 128;
  588.  
  589. // Width range
  590. float triWMin = 32;
  591. float triWMax = 128;
  592.  
  593. // Triangle range
  594. float triHMin = 64;
  595. float triHMax = 368;
  596.  
  597. // Vertical spacing between the triangles
  598. float triSpaceMin = 32;
  599. float triSpaceMax = 64;
  600.  
  601. color triColor = color(200, 200, 200, 80);
  602.  
  603. // Noise parameters
  604. // Colour of the noise
  605. float redFactor = 0.85f;
  606. float blueFactor = 0.795f;
  607. float greenFactor = 0.92f;
  608. float alphaFactor = 0.35f;
  609.  
  610. // The number of octaves used in the noise algoroithm - sharper detail
  611. int noiseDetails = 12;
  612.  
  613. // Frequency of the noise - higher value = smoother noise.
  614. float noiseFrequency = 77;
  615.  
  616. int noiseAlpha = (int)random(100, 170);
  617.  
  618. // Grid parameters
  619. int gridAlpha = (int)random(4, 14);
  620. // Grid noise power - apparent density.
  621. int gridPow = 1;
  622.  
  623. // Width of each grid cell
  624. int gridSize = 16;
  625.  
  626. // Circle pattern parameters
  627. int circleSpacing = (int)random(14, 38);
  628. int circleSize = 2;
  629. int circleAlpha = (int)random(18, 30);
  630. int circleGrit = 7;
  631. int gritAlpha = 44;
  632.  
  633. color bgColor = color(0);
  634.  
  635.  
  636. // ------------------------------------
  637. // Setup
  638. // ------------------------------------
  639. void setup() {
  640. // Setup our canvas
  641. size(400, 400);
  642. smooth();
  643. background(bgColor);
  644. noiseDetail(noiseDetails);
  645. }
  646.  
  647. // ------------------------------------
  648. // Draw loop
  649. // ------------------------------------
  650. void draw() {
  651. // We iterate through the algorithm a few times to create a decayed look with many layers.
  652.  
  653. for (int iter = 0; iter < iterations; iter++) {
  654.  
  655. // Go through every pixel of the screen.
  656. for (int x = 0; x < width; x += 1) {
  657. for (int y = 0; y < height; y += 1) {
  658.  
  659. // Draw noise layer.
  660. // Get the noise value at our position.
  661. float noiseVal = noise(x / noiseFrequency, y / noiseFrequency);
  662.  
  663. // Generate the colour from that.
  664. color noiseColor = color(redFactor * noiseVal * 255, greenFactor * noiseVal * 255, blueFactor * noiseVal * 255, alphaFactor * noiseVal * 255);
  665.  
  666. // Draw the pixel
  667. stroke(noiseColor);
  668. point(x, y);
  669.  
  670. // Draw the circle pattern layer.
  671. noStroke();
  672. fill(255, circleAlpha);
  673. if (x % circleSpacing == 0 && y % circleSpacing == 0) {
  674. ellipse(x, y, circleSize, circleSize);
  675. stroke(0, gritAlpha);
  676. // Paint a few random black pixels around it.
  677. for (int i = 0; i < circleGrit; i++) {
  678. int ax = x + (int)random(-circleSize, circleSize + 1);
  679. int ay = y + (int)random(-circleSize, circleSize + 1);
  680. point(ax, ay);
  681. }
  682. }
  683.  
  684. // Layer of random black noise ontop to produce grit.
  685. stroke(0, random(0, noiseAlpha));
  686. point(x, y);
  687.  
  688. // Draw the grid layer
  689. // If we are on a grid line
  690. if (x % gridSize == 0 || y % gridSize == 0) {
  691. // The grid works on the inverse of the noise so that it shows where there is no noise drawn.
  692. noiseVal = 1f - noiseVal;
  693. stroke(255, pow(noiseVal, gridPow) * gridAlpha);
  694. point(x, y);
  695. }
  696. }
  697. }
  698.  
  699. stroke(triColor);
  700. noFill();
  701. // Draw triangles on all but the last iteration so they don't come through too strong.
  702. if (iter < iterations - 1) {
  703.  
  704. //X position - static.
  705. float x = triX;
  706. // Y Position
  707. float y = random(triYMin, triYMax);
  708. // Triangle width
  709. float w = random(triWMin, triWMax);
  710. // Triangle height
  711. float h = random(triHMin, triHMax);
  712. // Spacing
  713. float s = random(triSpaceMin, triSpaceMax);
  714.  
  715. // Position of the righthand side;
  716. float offs = 400 - (x * 2);
  717.  
  718. // Number of triangles to draw.
  719. int numTri = (int)random(trisMin, trisMax);
  720.  
  721. for (int i = 0; i < numTri; i++) {
  722. // Draw the triangles on the left
  723. triangle(x, y + i * s, x - w / 2, y + h + i * s, x + w / 2, y + h + i * s);
  724.  
  725. // Draw triangles in the middle - upside down.
  726. pushMatrix();
  727. translate(200, 0);
  728. triangle(0, y + i * s, 0 - w / 2, -y - h + i * s, 0 + w / 2, -y - h + i * s);
  729. popMatrix();
  730.  
  731. // Offset using translate to save mathz.
  732. pushMatrix();
  733. translate(offs, 0);
  734. triangle(x, y + i * s, x - w / 2, y + h + i * s, x + w / 2, y + h + i * s);
  735. popMatrix();
  736. }
  737. }
  738.  
  739. stroke(treeColor);
  740. // Draw the tree a few times.
  741. int trees = (int)random(treesMin, treesMax);
  742. for (int i = 0; i < trees; i++) {
  743. tree(width / 2, height / 2, (int)(random(branchMin, branchMax)) * branchSize, 0f, treeDecay);
  744. }
  745. }
  746. // Do not loop the draw function.
  747. noLoop();
  748. }
  749.  
  750. // Possible angles for the tree branches.
  751. float angles[] = {
  752. 45f, 90f, 135f, 180f, 225f, 270f, 315f
  753. };
  754.  
  755. // Recursive algorithm to draw a tree that branches.
  756. void tree(float x, float y, int hyp, float lastAngle, int decay) {
  757. float newx = -1f;
  758. float newy = -1f;
  759. float angle = lastAngle;
  760.  
  761. // Lookup possible angles in an array - don't let it repeat the same angle or the same angle in reverse.
  762. while (angle == lastAngle && angle != lastAngle - 180f)
  763. angle = angles[(int)random(0, 7)];
  764.  
  765. // Calculate the end point.
  766. newx = round(x + cos(radians(angle)) * hyp);
  767. newy = round(y + sin(radians(angle)) * hyp);
  768.  
  769. // Check that we're within our margin - prevents offscreen drawing.
  770. if (newx < 0f + branchMargin || newx > width - branchMargin || newy < 0f + branchMargin || newy > height - branchMargin) {
  771. newx = width / 2;
  772. newy = width / 2;
  773. }
  774. else {
  775. // Don't draw lines coming out the centre - these overpower the image.
  776. if (x != width / 2 && y != height / 2) {
  777. // Draw the first line
  778. line(x, y, newx, newy);
  779. // Mirror the line
  780. line(width / 2 - (x - width / 2), y, width / 2 - (newx - width / 2), newy);
  781. }
  782. }
  783. // Only decay based on chance.
  784. int newLen = hyp;
  785. if (random(0, 1) < decayChance)
  786. newLen = hyp - decay;
  787.  
  788. // Have we decayed past the stop point?
  789. if (newLen > treeStop)
  790. tree(newx, newy, newLen, angle, decay);
  791. }
  792. ~~~
  793.  
  794. ## Final Evaluation ##
  795.  
  796. Based upon the final sketch, I deem that I have achieved my goal as stated in this portfolio post. However, there are a range of factors that could be improved in the final sketch.
  797.  
  798. * Runtime: The sketch takes a large amount of time to run, and could be optimized.
  799. * Refinement of the background: The algorithm used to produce the background image often produces results that aren't visually pleasing. Development of a new algorithm that doesn't rely on Perlin noise would be optimal.
  800. * Large variability in sketch outcome: Occasionally, the sketch produces an outcome that isn't as strong as it could be. The range of random factors in the sketch need further refinement.
  801. * Experimentation with vertical symmetry: I believe this would create an aesthetic form that would even moreso espouse the values contained within the project. Whilst simple to implement, this would require the re-tweaking of all the parameters in the project to create a pleasing composition.
  802. * Experiment with different linework algorithms: Whilst I find the algorithm in use very effective, it is worth exploring other possible ways to generate strong imagery. The final outcome diverges from my mockup mostly in this component of the project, as the mockup only worked well due to extreme consideration that is not possible with random generation. Other algorithms may be able to produce a similarly striking result whilst incorporating random elements.
  803.  
  804. Despite this, in my view, the sketch produces a strongly aesthetic result that represents the values and theme desired, well within the technical constraints of the project. The result produced balances extremely complex components into a composition that well represents movement and energy, particularly through the creation of a sense of rhythm via repetition and strong vector lines. I have achieved my goal of representing 'Techno' in an abstract, visual format. Most of the images produced are extremely powerful and are, in my opinion, a match for the quality of my cited inspiration and as such absolutely suitable for the stated client and format.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement