Hello folks!
Star Wars Tatooine Landscape
Started as a sketch to explore Processing image scaling and rendering.
Details
- resizing with
image(img, a, b, c, d) - resizing the sketch window
- resizing PGraphics layers
- drawing into larger PGraphics layers using scaled drawing parameters
- static and animated PGraphics layer compositing
- renderer performance with JAVA2D and P2D
- smoothing / antialiasing behavior
- noSmooth() added to settings. Comment this for testing with default smooth()
- anything I missed
Keys:
1reset to 1x3toggle 3x mode between image resizing and resized PGraphics layersstoggle smoothing / antialiasingdtoggle debug timing output- lots of combinations there to explore!
Renderer:
- edit
RENDERERin the code to switch betweenJAVA2DandP2D
// canvasScaleTest
// Author: GLV
// Version 1.4.0
// Date 2026-07-02
// Time 18:00
PGraphics pgSun, pgSand, pgText, pgBackground;
int w, h;
int canvasScale = 1; // Sketch size and PGraphics size scale
int imageScale = 1; // image() scale
String RENDERER = JAVA2D;
//String RENDERER = P2D;
float ySunBase;
float sandCol;
void settings()
{
w = 16*30;
h = 9*30;
size(w, h, RENDERER);
noSmooth(); // Comment this out for testing
}
void setup()
{
makeImages();
key = '3';
keyPressed();
}
boolean debug = false;
int t0, t1, t2;
void draw()
{
if (debug)
t0 = millis();
updateSunValues();
makeSun(); // Update every frame
makeSand();
//makeText();
if (debug)
t1 = millis();
if (scaleImage)
{
image(pgBackground, 0, 0, imageScale*w, imageScale*h);
image(pgSun, 0, 0, imageScale*w, imageScale*h);
image(pgSand, 0, 0, imageScale*w, imageScale*h);
image(pgText, 0, 0, imageScale*w, imageScale*h);
} else
{
image(pgBackground, 0, 0);
image(pgSun, 0, 0);
image(pgSand, 0, 0);
image(pgText, 0, 0);
}
if (debug)
t2 = millis();
if (debug)
println(t1-t0, t2-t1, t2-t0, frameRate);
}
boolean scaleImage = true;
void keyPressed()
{
if (key == 's')
{
togSmooth = !togSmooth;
makeImages();
}
if (key == 'd')
debug = !debug;
if (key == '1')
{
scaleImage = false;
imageScale = 1;
canvasScale = 1;
surface.setSize(w, h);
makeImages();
}
if (key == '3')
{
scaleImage = !scaleImage;
if (scaleImage)
{
imageScale = 3;
canvasScale = 1;
} else
{
imageScale = 1;
canvasScale = 3;
}
surface.setSize(3*w, 3*h);
makeImages();
}
}
void updateSunValues()
{
ySunBase = -50 + (frameCount/2.0)%(h+100);
//sandCol = 255-(ySunBase+50)*(255.0/(h+100));
float p = (ySunBase + 50) / (h + 100); //normalize
//sandCol = 255 * (1 - p);
sandCol = 255 * (1 - p*p);
//sandCol = 255 * (1 - p*p*p);
//println(ySunBase, sandCol);
}
boolean togSmooth;
void makeImages()
{
pgSun = createGraphics(canvasScale*w, canvasScale*h, RENDERER);
pgSand = createGraphics(canvasScale*w, canvasScale*h, RENDERER);
pgText = createGraphics(canvasScale*w, canvasScale*h, RENDERER);
pgBackground = createGraphics(canvasScale*w, canvasScale*h, RENDERER);
if (togSmooth)
{
pgSun.smooth(4); //See reference
pgSand.smooth(4);
pgText.smooth(4);
} else
{
pgSun.noSmooth();
pgSand.noSmooth();
pgText.noSmooth();
}
updateSunValues();
makeSun();
makeSand();
makeText();
makeGradientBackground();
}
void makeSun()
{
int xSun = 2*pgSun.width/3;
float ySun = canvasScale*ySunBase;
int offSet = canvasScale*40;
pgSun.beginDraw();
pgSun.clear();
float aSun = constrain(sandCol, 0, 255); //Use as alpha or brightness
//pgSun.fill(255, aSun);
pgSun.fill(aSun, aSun, aSun);
pgSun.noStroke();
pgSun.circle(xSun, ySun, canvasScale*20);
//pgSun.fill(255, 0, 0, aSun);
pgSun.fill(aSun, 0, 0);
pgSun.noStroke();
pgSun.circle(xSun+offSet, ySun+offSet, canvasScale*20);
pgSun.endDraw();
}
void makeSand()
{
float amp = 10; //amplitude
float ps = 0; //phase shift
float col = sandCol;
//if(d)
// println(col);
pgSand.beginDraw();
pgSand.clear();
pgSand.noStroke();
//pgSand.fill(0.5*col, 0.25*col, 0);
pgSand.fill(0.75*col, 0.60*col, 0.35*col);
pgSand.beginShape();
for (int i = 0; i<=pgSand.width; i+=canvasScale*10)
{
float th = i*(TAU/pgSand.width) + ps;
float x = i;
float y = canvasScale*amp*sin(th);
pgSand.vertex(x, y+ 3*pgSand.height/4);
}
pgSand.vertex(pgSand.width, pgSand.height);
pgSand.vertex(0, pgSand.height);
pgSand.endShape(CLOSE);
pgSand.endDraw();
}
void makeText()
{
pgText.beginDraw();
pgText.clear();
pgText.fill(0);
pgText.textSize(canvasScale*24);
pgText.textAlign(LEFT, TOP);
pgText.text("Tatooine", canvasScale*10, canvasScale*10);
pgText.endDraw();
}
void makeGradientBackground()
{
color cTop = color(180, 100, 75);
color cBottom = color(70, 55, 95);
pgBackground.beginDraw();
for (int y = 0; y < pgBackground.height; y++)
{
float p = y / float(pgBackground.height - 1);
//noStroke();
//fill(lerpColor(cTop, cBottom, p));
//rect(0, y, width, 1);
pgBackground.stroke(lerpColor(cTop, cBottom, p));
pgBackground.line(0, y, pgBackground.width, y);
}
pgBackground.endDraw();
}
:)
