My p5.js self-portrait is more than simply a picture of my face; it’s a story that illuminates my path to enroll in the “Introduction to Interactive Media” course. The artistic representation of that voyage is this portrait. My conversation with my friends regarding me not being able to enroll in this course until senior spring revolved around how I might be in the hall of fame for not being able to complete my minor because of an introductory course.
The goal of my portrait is to elevate the accomplishment by placing my face on a pedestal and using a lighted stage as the background. It acts as a metaphor for the significant problems I faced since freshmen fall to enroll in this course to complete my minor. Pedestals are typically used to display objects of significant worth or significance. I also thought of adding an interactive element (by clicking the mouse button) that allows me to change the emotions on my face. The face changes from a smile to a laughing face which serves as a cathartic release for the difficulties during the journey.
Sketch
Code
The code that I am proud of is how I was able to illustrate two different expressions with an easy mouse-click interactive technique. Initially, the value of isLaughing is set to false and when the mouse clicks the value changes to true.
function mouseClicked() {
// Toggle the laughing state
isLaughing = !isLaughing;
}
The drawFace function is the core code for making this sketch possible. This code uses the mouse-toggled laughing boolean variable to show different expressions. The portrait has a lot of facial details that resemble me in real life. The addition of stud-adorned ears, a neck, and a cap enhances the portrait’s authenticity and individuality.
function drawFace(laughing) {
// Ears
fill(skinColor);
// Left ear
ellipse(135, 156, 30, 40);
// Right ear
ellipse(265, 156, 30, 40);
// Making studs on both ears
fill(255,255,255);
// stud on left ear
ellipse(131, 167, 8, 8);
fill(255,255,255);
// stud on right ear
ellipse(269, 167, 8, 8);
// Drawing the neck
fill(skinColor);
rect(175, 206, 50, 60);
// Drawing the head
fill(skinColor);
ellipse(200, 156, 125, 170);
// Cap
fill(0);
arc(200, 120, 115, 125, PI, TWO_PI, OPEN);
strokeWeight(10);
line(150,115,110,115)
strokeWeight(1);
if (laughing) {
// Laughing face
// Eyes closed
fill(0);
// left eye closed
ellipse(170, 136, 30, 10);
// right eye closed
ellipse(230, 136, 30, 10);
// Tears
fill(0, 191, 255);
// tears from left eye
ellipse(165, 151, 10, 25);
// tears from right eye
ellipse(235, 151, 10, 25);
// Open mouth - laughing state
fill(255);
arc(200, 206, 60, 40, 0, PI, CHORD);
} else {
// Smiling Face
// Eyes
fill(255);
// left eye
ellipse(170, 140, 35, 25);
// left eye
ellipse(230, 140, 35, 25);
// Pupil
fill(0);
// left eye - pupil
ellipse(170, 145, 15, 15);
// right eye - pupil
ellipse(230, 145, 15, 15);
// Mouth
noFill();
arc(200, 206, 60, 15, 0, PI);
}
// Nose (same for both faces)
line(200, 165, 200, 190);
}
Lastly, the concept was achieved by using the pedestal in the center of the room with spotlights showing a significant person.
// Background image of pedestal
function preload(){
bgImage = loadImage("https://st2.depositphotos.com/1051355/6256/i/450/depositphotos_62569733-stock-photo-illuminated-empty-stage-podiums-for.jpg")
}
Challenges
There were a few challenges that I faced while doing this assignment. Initially, I planned on giving hair to my portrait, however, I was not able to achieve that. So I had to improvise and I made a cap instead.
Another challenge was to determine the x and y coordinates. To solve this issue I printed the cursor’s x and y values in the console using the draw function.
function draw() {
// finding the value of x and y
print(mouseX, mouseY)
}
Reflection and Improvements
All the IM courses that I have taken have encouraged me to find meaning behind what I am doing or to show a story. I am happy with the portrait that I have made, it is close to what I look like in real life and also can show the story behind making it.
There is always room for improvement. For example, the portrait may show various emotions depending on which keyboard keys are pressed. Also, the portrait does not have eyebrows, so the eyebrows can follow the mouse when hovering over the portrait.
References
I took a reference from schemecolor.com to use the exact skin color for my portrait.
Another reference was the background image of the pedestal.
In case p5js Editor website is down, below is the recording of working demo on YouTube.
1) 🤔 Conceptualization
As below, I wanted my self portrait to reflect my silhouette, not too realistic but not too cartoony, but something in the style of graphic novels or marvel/DC comics. I am an artist and engineer, and hence, I also would like to include some bells and whistles which define both my art and engineering aspects. Normally for my everyday casual wear, I usually wear the black Chinese long dress – Changshan (長衫), with a red and black Tangzhuang (唐裝) coat on the top, with my long hair properly tied with a red ribbon as below.
Moreover, I also wanted the portrait to show my personal emblem, the stylized rectangular Greek letter Pi.
As below, my usual real life portraits will feature me wearing my Chinese traditional outfit, with floating glowing code in futuristic HUD (Head-up display), and some equations that either I derived, or some equations I use in my work frequently. And of course the Pi emblem. This concept perfectly “marries the traditions from the past with the technology of the future, and hence justifying my existence as the artistic engineer in 2024 at present.”
While doing this portrait, here are the constraints I would like to adhere to.
Implement the portrait purely in p5js without any external libraries, external files in a single sketch.js file – such that when you copy and paste and run, it will run without additional configuration.
Follow the rubrics of the course assignment (do not import any existing image or do not use mouse to draw, and must not be realistic – A manga style silhouette is ‘not’ realistic)
In addition to the portrait, have items around me that defines me.
2) ⚙️ Technical Plan of Attack & Implementation
Since this is a “self-portrait” it should contain all the elements that gives the viewer a super brief introduction about a fraction of my life. Hence, below are the individual components used for the composition of the portrait.
Portrait : I am a manga/anime artist and animator. The entire portrait is implemented using bezierVertex() functions to allow me greater control over the shapes, and obtain the sketchy graphic novel/manga style I want to achieve. This has to combine 1) the line art and the 2) color. Colors are added in between the bezier curves to fill the shape. Therefore, a component of my portrait would look like
Animated Gears : I am a roboticist, and very fond of gears and servos. The gears are nothing but circles with partial opacity, and rectangles rendered on the side of the circles programmatically.
Animated Cubes : I am an XR/VR/AR developer, a 3D artist and a mathematician. Hence, I want to do some maths to show some interactive floating 3D cubes around me to symbolize this aspect of my life. Just because p5 js is a 2D canvas technology does not mean I should not attempt my beloved 3D art here. And just because webGL is available in p5 does not mean I have to follow what everyone is doing. Who needs webGL when we can just do some readings in linear algebra, define the vertices of the cubes, and do some matrix multiplication through rotation matrices in 3D space, and project them to the 2D p5js canvas? The matrix multiplication, and the rendering the projection is coded in my single sketch.js file, a snapshot of the code is as follows.
// Rotation matrices for X, Y, and Z axes
let rotationZ = [
[cos(angleCube), -sin(angleCube), 0],
[sin(angleCube), cos(angleCube), 0],
[0, 0, 1],
];
let rotationY = [
[cos(angleCube), 0, sin(angleCube)],
[0, 1, 0],
[-sin(angleCube), 0, cos(angleCube)],
];
let rotationX = [
[1, 0, 0],
[0, cos(angleCube), -sin(angleCube)],
[0, sin(angleCube), cos(angleCube)],
];
Personal Emblem : I am a citizen Sinologist, and have always been inspired by East Asian culture. Traditional Japanese clans have their own family emblems called Mon (紋). I also have one myself, visually designed similar to that used by Nakagawa clan. I can draw my emblem by defining the (x,y) coordinates of my emblem through an array, and letting vertex function loop through the shape.
function drawPiEmblem(x, y, scale) {
const points = [
{ x: 46.3, y: 72.7 },
...
{ x: 73.3, y: 72.7 },
];
beginShape();
fill("#903C37");
for (let i = 0; i < points.length; i++) {
vertex(x + points[i].x * scale, y + points[i].y * scale);
}
endShape(CLOSE);
}
Quine Code : I am a Computer Engineer, and quite fond of cool code tricks. In Computer Science, a quine is a computer program which takes no input and produces a copy of its own source code as its only output. Since I usually put code in my real life portraits, I thought it would be cool for my self portrait to print out its own p5js code at my back. The approach is simple, I just copy the first a few lines of my code and just let it print like a terminal. This would have been a lot cooler if I can go under the hood of p5js, and overwrite its event loop + file reading permissions to read its own source code and print it out dynamically, rather than me hardcoding it.
Custom font without using a custom font : I also wanted to use a better font, but I do not want to import anything into my single sketch.js implementation, hence I just produced some other good looking unicode characters using Stylish Text Generator (https://lingojam.com/StylishTextGenerator), if it works it works.
Falling Pi Digits : My name is Pi, the infinite mathematical constant which never repeats. This means a lot to me since that name allows me to pull out infinite ideas from my brain, which never repeats (but pratically work, and aesthetically beautiful) at will. Hence, in my portrait, the mouse pointer will drop the digits of pi, as a particle system, in a repeated fashion (because you can’t hard code infinite Pi digits)… So, the mouse pointer at time intervals will drop the digits three, point, one, four, one , five , nine, two ….
Backpropagation Equations : I am a published machine learning researcher, and deep learning is my default weapon of choice. Therefore, I wanted to honor the basic four equations which allows me to do my everyday work (sorry Maxwell, your equations take the second priority in my heart). Hence, I have the equations floating around me in my portrait.
Accompanying music : I am a multi instrumentalist and a composer, and I wanted to give a background music to my portrait. However, since I am not using any external libraries, and I still want to implement a basic metal guitar riff, I ended up defining two oscillators to symbolize the top two guitar strings in dropped D tuning, and hard coding a metal riff – but only using the simple waveforms 🙁 . I could have done the wave superpositions to simulate the acoustics and distortion pedal signal processing of the electric guitar, but let it be for now.
3) 🎨 Artistic Plan of Attack & Implementation
Vignette : The white background is bland, and as a big fan of Assassin’s Creed Animus Loading Screens, I wanted a pale vignette effect. However, since I am not importing anything, I just loop over the entire canvas and painting each of the background pixels the right intensity and alpha values.
Rule of third placement : A good rule of thumb in visual composition is to divide the entire canvas in three and place the subjects on these lines. My portrait is on the left line. Checklist checked.
Whitespace consideration : I could have added more because this portrait paints a very limited aspect of my life. I could have added more computational chemistry, professional Game Development, martial arts choreography, epidemiology simulation models, Web Dev , Dev Ops and linguistics and so on – but stopped, to keep the whitespace visually clear, I let the majority of dark colors sit on the left side, and right side of the portrait contains the main whitespace.
Mouse Interactivity : Also, I find my self portrait after coding to be very static, so I browsed through old archives of this Intro to IM blogs. My friend Naz did something cool and interactive with the mouse pointer to give a parallax effect, so I ended up stealing her idea from Self-Portrait by Naz (https://editor.p5js.org/iremnaz/sketches/oxRGnv701).
4) 💪 Challenges
There was zero challenge. I became one with the machine, and implemented the entire sketch.js in one sitting in one boring afternoon, sipping Jasmine tea.
5) 💡 Potential Improvements
One tricky thing is how quick my self portrait code runs (on computers which are slow). Since I am generating a lot of objects and doing a lot, I could have refactored my code more to run more smoothly. For instance, for the falling Pi digits, I can implement an Object pool pattern and reuse the previous particles as soon as they are out of frame. But these are just off the top of my head.
As a bonus, through obfuscation and clever syntax formatting, I could have made the source code of the program actually look like my portrait ascii art, just like how this donut generation code is in the shape of a donut (https://www.a1k0n.net/2006/09/15/obfuscated-c-donut.html). But let it be this time.
For this assignment, I aimed to incorporate one of my favorite things to do, that instantly fills my entire body with peace and happiness. Watching the sunset. The plan was ideally to make the background more ombre other than fading, however, as it’s my first time using p5js I found it difficult to implement that into my background. For future assignments, I’m hoping to create more interactive projects and master the ombre affect as well as getting more familiar with coding.
While working on this assignment, I wanted to recreate my middle school self. I had some experience with Processing so working with P5.js wasn’t so hard to navigate and work with. The thing I struggles with the most in this assignment was the bow. The idea is simple but I never worked with triangles in code before so it was quite difficult trying to figure out the right coordinates. For future assignments I’d like to make my projects much more interactive and fun.
My initial Idea was to create a realistic picture of a self-portrait of how I look in the traditional clothes I would wear when I am out.
Reflection and ideas for future work or improvements:
I would say that in the future, I would truly write down the numbers I try when it comes to centering things on the sketch because I kept going around in circles trying to center everything and because I kept placing the same numbers for the different heights and length due to me constantly forgetting what numbers I already tried so It just unnecessarily prolonged the process.
Code Implementation:
I have never used Javascript before, and my understanding of coding is somewhat simple. I had a tough time managing to create hair that looked normal at first, so I tossed that Idea out and wanted to create something else without knowing it was going to be a more complex idea in terms of coding, which was the Ghutra, thinking I would have to create a rectangle and be done with it. However, it did not look like anything close to what I wanted it to be, so I had to use a circle to show that the portrait was wearing it while using three different rectangles layered at different heights so that it shows the way I would personally tie it around my head. But now, looking back at the finished sketch, I would say that I was glad to take the long road of creating a Ghutra to showcase a more realistic portrait of the whole look I have going on.
function setup() {
createCanvas(400, 400);
background(255);
}
function draw() {
// Body
fill("white")// Body base color.
ellipse(200,420,240,300)// Body base.
// Face
fill(210, 180, 140); // skin color
ellipse(200, 200, 160, 200); // head shape
// Ghutra
fill("white");
arc(200, 130, 130, 90, PI, 0);
rect(125, 120, 150, 30);
rect(125, 110, 150, 25);
rect(125, 130, 150, 10);
// Eyebrows
fill("black");
rect(150, 160, 40, 10); // left eyebrow
rect(215, 165, 40, 10); // right eyebrow
// Eyes
fill("white");
ellipse(170, 190, 40, 20); // left eye white
ellipse(230, 190, 40, 20); // right eye white
fill("black");
ellipse(170, 190, 20, 20); // left pupil
ellipse(230, 190, 20, 20); // right pupil
// Mustache
fill("black");
arc(200, 248, 80, 30, PI, TWO_PI);
// Beard
fill("black");
arc(200, 245, 140, 120, 0, PI);
// Mouth
fill("white");
arc(200, 250, 50, 20, 0, PI);
// Hair
fill("white");
noLoop(); // Stops draw loop
}
The first assignment was different than any assignments I have done, it was a fun activity to me. I learned a lot from the past two classes and learned more by doing this task, using my skill of self learning and learning something new at the moment when i think of it.
The portrait itself, initially I tried to make a portrait of myself but I thought after that it would be cliche and everybody will do the same. I came up afterwards with the alien head which is an emoji that I always use and everyone knows me remembers me instantly, so it is me in another universe. I tried to make the same shape of the aliens head but It got challenging, and tried to shape the eyes with the big black pupils, with a tiny circle that shows the reflection of the light. Afterwards I got an idea of drawing some stars behind the head, I tried to draw the quad and shape it afterwards to look like a star but I found it hard fixing the dimensions and not the way I wanted it to be. I came up with an idea of making tiny points all over the canvas behind the head, going back to the reference page in P5 website, I created a starry universe by using the dots and with the command random() and made them infinite by using a loop function to create the starry effect.
Through this assignment I learnt a lot and loved the process of doing it. As a freshman I want to improve my self learning skills and this assignment is helping me achieving this skill that will help me in my future courses throughout my four years at the university.
function drawAlien(x, y) {
// Alien face
fill(0, 200, 120, 50);
ellipse(x, y, 100, 110); // Head
// Eyes
fill(0);
ellipse(x - 20, y - 10, 30, 40); // Left eye
ellipse(x + 20, y - 10, 30, 40); // Right eye
// Pupils
fill(255);
ellipse(x - 29, y -17, 5, 10); // Left pupil
ellipse(x + 29, y -17, 5, 10); // Right pupil
// Smiling mouth
noFill();
stroke(0);
strokeWeight(3);
arc(x, y + 20, 10, 15, 0, PI);
}
In my first coding project, I decided to represent myself through a unique concept, creating a digital persona that reflects my identity.
I used a triangular shape body to symbolize my abaya and incorporated a head turban, adding personal elements to the visual representation. Choosing lilac as the background, my favorite color, not only adds aesthetic appeal but also creates a connection to my preferences. I took pride in successfully integrating my name into the background and even discovered the possibility of including an emoji through my research, which was a pleasant surprise. Looking ahead, I aspire to advance my coding skills by incorporating more details like hands and feet, aiming for a more realistic depiction of a human figure.
Taking small steps and exploring the possibilities at my own pace is part of my learning journey, and I’m excited about the potential for future improvements in my coding projects.
This is my first attempt at p5.js. I’ve tried to reflect my personal preferences and appearances in this “self-portrait”. My idea is to portray a Bangladeshi girl with big eyes, dark lipstick, and blush wearing a dress and a necklace. I matched the skin color with my own complexion, and the hair color with my hair highlight’s color. Concept wise I think the intention was to personalize the drawing as much as I can using only the simple shapes like ellipse, circle, arc, rectangles and straight lines. I tried to make the colors pop and to make it very detailed for example the necklace is similar to an actual one that I have with an Emerald stone, then the parting between the hair which is something very prominent in my appearance. Placing the lips and the eyelashes were the most difficult part for me I think.
I added interactivity with a smile formed on the mouth upon mouse-click with the if-else statement and mouseIsPressed function. So if you click on the image the lips change to a smile.
For improvements I think adding interactivity with the eyes opening and closing periodically and having some texts would have been nice. Also maybe making it a full-body self-portrait would be a very detailed development I believe which I intend to work on later. Overall, I loved playing with the numbers and parameters and colors and shapes to make it more and more perfect to the reality.
Description:
For this assignment, I opted for a straightforward approach to create a self-portrait. The portrait includes various facial features, notably the eyes move horizontally due to the animation, and the eyebrows respond to the eye movement.
Sketch:
Code Implementation:
let eye1X = 170;
let eye2X = 230;
let direction1 = 1;
let direction2 = 1;
let lipYOffset = 0;
function setup() {
angleMode(DEGREES);
rectMode(CENTER);
createCanvas(400, 400);
background(240);
}
function draw() {
background(240);
// Draw the existing elements
// hair
fill(41, 38, 31);
rect(200, 220, 205, 330, 90);
// shirt
fill(167, 181, 169);
rect(200, 380, 190, 270, 40);
// neck
fill(245, 227, 176);
rect(200, 239, 100, 100, 30);
// face
fill(245, 227, 176);
ellipse(200, 150, 150, 175);
// left eye
fill(255);
ellipse(eye1X, 143, 40, 40);
// right eye
ellipse(eye2X, 143, 40, 40);
// left pupil
fill(0);
ellipse(eye1X, 143, 15, 20);
// right pupil
ellipse(eye2X, 143, 15, 20);
// mouth
arc(200, 192, 50, 50, 0, 180);
// nose
noFill();
arc(198, 175, 20, 15, 270, 90);
// bangs
noStroke();
fill(41, 38, 31);
rect(200, 81, 90, 43, 58);
strokeWeight(5);
stroke(41, 38, 31);
line(150, 115, 175, 115); // left eyebrow
line(225, 115, 250, 115); // right eyebrow
strokeWeight(1);
stroke(0);
// eye positions
eye1X += direction1 * 2;
eye2X += direction2 * 2;
// Check if eyes reach the edge and change direction
if (eye1X <= 160 || eye1X >= 180) {
direction1 *= -1;
}
if (eye2X <= 220 || eye2X >= 240) {
direction2 *= -1;
}
}
Considering my beginner coding skills and the project’s deadline, I focused on portraying recognizable features like my curly hair and glasses in my self-portrait. To achieve this, I used circles to mimic the curls of my hair and smooth squares to represent the frames of my glasses. This approach allowed me to create a clear and straightforward depiction of these key features within the technical and time constraints of the project.
A highlight of some code that you’re particularly proud of:
Reflection and ideas for future work or improvements:
In my self-portrait, I generally feel content with the overall outcome, but there are elements I now recognize could have been improved. After looking at other examples, I realized a missed opportunity in the portrayal of my glasses. I wish I had learned to isolate a specific area for the eyes that would follow the cursor, adding an interactive and dynamic aspect to the artwork.
Another aspect I would revise is the portrayal of my facial features. Initially, I used simple shapes, but now I see the potential for more accurately representing features like my eyes, nose, and mouth. With more advanced coding skills, I could have added detail to these features, making the portrait not just an abstract representation but a more recognizable portrait of myself.
However I look forward to delving deeper into the possibilities of creative coding, pushing the boundaries of what I can create and express.