xxxxxxxxxx
592
let defaultColor;
let defaultNormal;
let defaultAOSD;
let depthTestNoShine;
let depthTestFullShine;
let shineTest;
let block0;
let block0AOSD;
let block1;
let normalSphere;
let swordAndShieldColor;
let swordAndShieldNormal;
let swordAndShieldAOSD;
let swordAndShieldLorgeColor;
let swordAndShieldLorgeNormal;
let tetrisColor;
let tetrisNormal;
let tetrisAOSD;
let randomNormals;
let phong;
let canvasW;
let canvasH;
let halfW;
let halfH;
let drawDot = false;
let objX = 0;
let objY = 0;
let objZ = 0;
let scaleX = 1;
let scaleY = 1;
let currentColor;
let currentNormal;
let currentAOSD;
let defaultZoom = 8;
let zoom = defaultZoom;
let minZoom = 0.25;
let maxZoom = 64.0;
let zoomChange = 0.025;
let useDirectionalLight = true;
let directionalLightX = 11;
let directionalLightY = 121;
let directionalLightZ = -100;
class LightInputData
{
constructor(x, y, z, r, g, b, fa, fb, fc)
{
this.x = x; this.y = y; this.z = z;
this.r = r; this.g = g; this.b = b;
this.fa = fa; this.fb = fb; this.fc = fc;
}
get WorldPosArray() { return [this.x, this.y, this.z]; }
get ColorArray() { return [this.r, this.g, this.b]; }
get FalloffArray() { return [this.fa, this.fb, this.fc]; }
SetWorldPos(x, y, z) { this.x = x; this.y = y; this.z = z; }
SetColor(r, g, b) { this.r = r; this.g = g; this.b = b; }
SetFalloff(fa, fb, fc) { this.fa = fa; this.fb = fb; this.fc = fc; }
}
let pointLights = [];
let mainBuffer;
let post;
let eightBitSquare;
let useTextify = false;
let usePointLightRotation = true;
let usePointLights = true;
let useColor = true;
let useNormal = true;
let useAO = true;
let useSpecular = true;
let useDepth = true;
let useInterpolation = true;
let linear;
let nearestNeighbor;
let thresholdMap;
let objW;
let objH;
let robotoRegular;
let robotoBlack;
let hudShouldDraw = true;
function preload()
{
defaultColor = loadImage("defaultColor.png");
defaultNormal = loadImage("defaultNormal.png");
defaultAOSD = loadImage("defaultAOSD.png");
depthTestNoShine = loadImage("depthTestNoShine.png");
depthTestFullShine = loadImage("depthTestFullShine.png");
shineTest = loadImage("shineTest.png");
block0 = loadImage("block0.png");
block0AOSD = loadImage("block0AOSD.png");
block1 = loadImage("block1.png");
normalSphere = loadImage("normalSphere.png");
swordAndShieldColor = loadImage("SwordAndShieldColor.png");
swordAndShieldNormal = loadImage("SwordAndShieldNormal.png");
swordAndShieldAOSD = loadImage("SwordAndShieldAOSD.png");
swordAndShieldLorgeColor = loadImage("SwordAndShieldLorgeColor.png");
swordAndShieldLorgeNormal = loadImage("SwordAndShieldLorgeNormal.png");
tetrisColor = loadImage("TetrisColor.png");
tetrisNormal = loadImage("TetrisNormal.png");
tetrisAOSD = loadImage("TetrisAOSD.png");
randomNormals = loadImage("RandomNormals.png");
phong = loadShader("Basic.vert", "Phong.frag");
post = loadShader("FullQuad.vert", "Textify.frag");
eightBitSquare = loadImage("EightBitSquare.png");
thresholdMap = loadImage("Bayer16.png");
currentColor = randomNormals;
currentNormal = randomNormals;
currentAOSD = randomNormals;
robotoRegular = loadFont("Fonts/RobotoRegular.otf");
robotoBlack = loadFont("Fonts/RobotoBlack.otf");
}
function setup()
{
canvasW = windowWidth;
canvasH = windowHeight;
halfW = canvasW / 2;
halfH = canvasH / 2;
createCanvas(canvasW, canvasH, WEBGL);
objW = currentColor.width;
objH = currentColor.height;
mainBuffer = createGraphics(canvasW, canvasH, WEBGL);
mainBuffer.fill(255);
mainBuffer.noStroke();
mainBuffer.rectMode(CENTER);
let lightCount = 6;
let radius = 200;
angleMode(DEGREES);
colorMode(HSB, 1.0);
let dAngle = 360 / lightCount;
let initialAngle = 0;
for (let i = 0; i < lightCount; ++i)
{
let angle = initialAngle + i * dAngle;
let x = radius * cos(angle);
let y = radius * sin(angle);
let z = 10;
let h = angle / 360.0;
let s = 0.8;
let v = 0.9;
let c = color(h, s, v, 1.0);
let r = red(c) / 255.0;
let g = green(c) / 255.0;
let b = blue(c) / 255.0;
let pl = new LightInputData();
pl.SetWorldPos(x, y, z);
pl.SetColor(r, g, b);
pl.SetFalloff(0.3, 0.03, 0.01);
pointLights.push(pl);
}
colorMode(RGB, 255);
}
function draw()
{
background(0);
mainBuffer.clear();
mainBuffer.push();
let change = 0.0;
if (!keyIsDown(SHIFT) && keyIsDown(88))
change += zoomChange;
if (!keyIsDown(SHIFT) && keyIsDown(90))
change -= zoomChange;
zoom = constrain(zoom * (1 + change), minZoom, maxZoom);
let dX = 0;
let dY = 0;
if (keyIsDown(RIGHT_ARROW))
dX += 1;
if (keyIsDown(LEFT_ARROW))
dX -= 1;
if (keyIsDown(DOWN_ARROW))
dY += 1;
if (keyIsDown(UP_ARROW))
dY -= 1;
if (keyIsDown(SHIFT))
{
dX *= 0.25;
dY *= 0.25;
}
objX += dX * (((zoom - 1) * 0.1) + 1);
objY += dY * (((zoom - 1) * 0.1) + 1);
if (keyIsDown(SHIFT) && mouseIsPressed && mouseButton === LEFT)
{
directionalLightX = halfW - mouseX;
directionalLightY = halfH - mouseY;
}
mainBuffer.shader(phong);
let totalWidth = objW * zoom * scaleX;
let totalHeight = objH * zoom * scaleY;
phong.setUniform("uSourceSize", [objW, objH]);
phong.setUniform("uLightingSize", [totalWidth, totalHeight]);
phong.setUniform("uColorMap", currentColor);
phong.setUniform("uNormalMap", currentNormal);
phong.setUniform("uAOSDMap", currentAOSD);
phong.setUniform("uEmissionColor", [0.0, 0.0, 0.0]);
phong.setUniform("uAmbiemtColor", [0.2, 0.15, 0.6]);
phong.setUniform("uUseDirectionalLight", useDirectionalLight);
phong.setUniform("uDirectionalLightDirection", [directionalLightX, directionalLightY, directionalLightZ]);
phong.setUniform("uDirectionalLightColor", [1.0, 1.0, 1.0]);
phong.setUniform("uUseColor", useColor);
phong.setUniform("uUseNormal", useNormal);
phong.setUniform("uUseAO", useAO);
phong.setUniform("uUseSpecular", useSpecular);
phong.setUniform("uUseDepth", useDepth);
phong.setUniform("uUseInterpolation", useInterpolation);
let pointLightCount = pointLights.length;
if (!usePointLights)
pointLightCount = 0;
phong.setUniform("uPoimtLightCount", pointLightCount);
for (let i = 0; i < pointLightCount; ++i)
{
let pointLight = pointLights[i];
phong.setUniform(`uPointLights[${i}].worldPos`, pointLight.WorldPosArray);
phong.setUniform(`uPointLights[${i}].color`, pointLight.ColorArray);
phong.setUniform(`uPointLights[${i}].falloff`, pointLight.FalloffArray);
}
phong.setUniform("uKA", 0.3);
phong.setUniform("uKD", 1.0);
phong.setUniform("uKS", 1.0);
phong.setUniform("uDepthScale", 10.0);
phong.setUniform("uObjectWorldPos", [objX, objY, objZ]);
mainBuffer.rect(objX, objY, totalWidth, totalHeight);
if (hudShouldDraw)
DrawHud();
if (useTextify)
{
push();
{
shader(post);
let mw = thresholdMap.width;
let mh = thresholdMap.height;
let atlasW = eightBitSquare.width;
let atlasH = eightBitSquare.height;
let tileW = 8;
let tileH = 8;
post.setUniform("uSource", mainBuffer);
post.setUniform("uTileAtlas", eightBitSquare);
post.setUniform("uThresholdMap", thresholdMap);
post.setUniform("uSourceSize", [canvasW, canvasH]);
post.setUniform("uAtlasSize", [atlasW, atlasH]);
post.setUniform("uTileSize", [tileW, tileH]);
post.setUniform("uMapSize", [mw, mh]);
post.setUniform("uTileIndexMin", 7);
post.setUniform("uBackgroundColor", [0, 0, 0]);
rect(0, 0, 0, 0);
}
pop();
}
else
{
image(mainBuffer, -canvasW / 2, -canvasH / 2);
}
if (usePointLightRotation)
RotatePointLights();
mainBuffer.pop();
}
function keyPressed()
{
switch (keyCode)
{
case 77: // M
PrintDirectionalLightData();
break;
case 32: // Spacebar
ToggleDirectionalLight();
break;
case 84: // T for textify
ToggleTextify();
break;
case 82: // R for rotate
TogglePointLightRotation();
break;
case 81: // Q for quit? Not really clear :(
ResetZoom();
break;
case 80: // P for point lights
TogglePointLights();
break;
case 67: // C for Catwoman
ToggleColor();
break;
case 78: // N for normal
ToggleNormal();
break;
case 65: // A for ambient occlusion
ToggleAO();
break;
case 83: // S for specular
ToggleSpecular();
break;
case 68: // D for depth
ToggleDepth();
break;
case 73: // I for interpolation
ToggleInterpolation();
break;
case 88: // X
if (keyIsDown(SHIFT))
ZoomStep(1);
break;
case 90: // Z
if (keyIsDown(SHIFT))
ZoomStep(-1);
break;
case 72: // H for HUD
ToggleHud();
break;
}
}
function RotatePointLights()
{
let rotationSpeed = 30;
let dAngle = rotationSpeed * deltaTime / 1000;
for (const pl of pointLights)
{
let x = pl.x;
let y = pl.y;
let r = sqrt(x * x + y * y);
let angle = atan2(y, x) + dAngle;
pl.x = r * cos(angle);
pl.y = r * sin(angle);
}
}
function PrintDirectionalLightData()
{
print(directionalLightX, directionalLightY, directionalLightZ);
}
function ResetZoom()
{
zoom = defaultZoom;
}
function ToggleDirectionalLight()
{
useDirectionalLight = !useDirectionalLight;
print(`Directional light ${useDirectionalLight ? "en" : "dis"}abled`);
}
function ToggleTextify()
{
useTextify = !useTextify;
print(`Textify ${useTextify ? "en" : "dis"}abled`);
}
function TogglePointLightRotation()
{
usePointLightRotation = !usePointLightRotation;
print(`Point light rotation ${usePointLightRotation ? "en" : "dis"}abled`);
}
function TogglePointLights()
{
usePointLights = !usePointLights;
print(`Point lights ${usePointLights ? "en" : "dis"}abled`);
}
function ToggleColor()
{
useColor = !useColor;
print(`Color mapping ${useColor ? "en" : "dis"}abled`);
}
function ToggleNormal()
{
useNormal = !useNormal;
print(`Normal mapping ${useNormal ? "en" : "dis"}abled`);
}
function ToggleAO()
{
useAO = !useAO;
print(`Ambient occlusion mapping ${useAO ? "en" : "dis"}abled`);
}
function ToggleSpecular()
{
useSpecular = !useSpecular;
print(`Specular mapping ${useSpecular ? "en" : "dis"}abled`);
}
function ToggleDepth()
{
useDepth = !useDepth;
print(`Depth mapping ${useDepth ? "en" : "dis"}abled`);
}
function ToggleInterpolation()
{
useInterpolation = !useInterpolation;
print(`Interpolation ${useInterpolation ? "en" : "dis"}abled`);
}
function ZoomStep(dir)
{
let size = 8;
let rounded = size * round(zoom / size);
let delta = size * (dir / abs(dir));
zoom = constrain(rounded + delta, 1, maxZoom);
}
function ToggleHud()
{
hudShouldDraw = !hudShouldDraw;
print(`HUD ${hudShouldDraw ? "en" : "dis"}abled`);
}
function DrawHud()
{
mainBuffer.push();
{
mainBuffer.textAlign(LEFT, TOP);
let headerColor = color(255, 235);
let defaultColor = color(255, 220);
let enabledColor = color(255, 255, 0, 220);
let disabledColor = color(255, 200);
let spacing = 20;
let x = 8 - halfW;
let y = 8 - halfH;
let rightX = x + 120;
mainBuffer.textSize(24);
mainBuffer.fill(headerColor);
mainBuffer.textFont(robotoBlack);
mainBuffer.text("CONTROLS", x, y);
mainBuffer.textSize(20);
y += 24;
mainBuffer.fill(defaultColor);
mainBuffer.text("Shift + LMB", x, y);
mainBuffer.textFont(robotoRegular);
mainBuffer.text("Change directional light direction", rightX, y);
y += spacing;
mainBuffer.textFont(robotoBlack);
mainBuffer.text("Arrow Keys", x, y);
mainBuffer.textFont(robotoRegular);
mainBuffer.text("Move graphic", rightX, y);
y += spacing;
mainBuffer.textFont(robotoBlack);
mainBuffer.text("X and Z", x, y);
mainBuffer.textFont(robotoRegular);
mainBuffer.text("Zoom", rightX, y);
y += spacing;
mainBuffer.textFont(robotoBlack);
mainBuffer.text("Q", x, y);
mainBuffer.textFont(robotoRegular);
mainBuffer.text("Reset zoom", rightX, y);
y += spacing;
mainBuffer.textFont(robotoBlack);
mainBuffer.text("T", x, y);
mainBuffer.textFont(robotoRegular);
mainBuffer.fill(useTextify ? enabledColor : disabledColor);
mainBuffer.text("Toggle textify effect", rightX, y);
y += spacing;
mainBuffer.fill(defaultColor);
mainBuffer.textFont(robotoBlack);
mainBuffer.text("I", x, y);
mainBuffer.textFont(robotoRegular);
mainBuffer.fill(useInterpolation ? enabledColor : disabledColor);
mainBuffer.text("Toggle texture interpolation", rightX, y);
y += spacing;
mainBuffer.fill(defaultColor);
mainBuffer.textFont(robotoBlack);
mainBuffer.text("Spacebar", x, y);
mainBuffer.textFont(robotoRegular);
mainBuffer.fill(useDirectionalLight ? enabledColor : disabledColor);
mainBuffer.text("Toggle directional light", rightX, y);
y += spacing;
mainBuffer.fill(defaultColor);
mainBuffer.textFont(robotoBlack);
mainBuffer.text("P", x, y);
mainBuffer.textFont(robotoRegular);
mainBuffer.fill(usePointLights ? enabledColor : disabledColor);
mainBuffer.text("Toggle point lights", rightX, y);
y += spacing;
mainBuffer.fill(defaultColor);
mainBuffer.textFont(robotoBlack);
mainBuffer.text("R", x, y);
mainBuffer.textFont(robotoRegular);
mainBuffer.fill(usePointLightRotation ? enabledColor : disabledColor);
mainBuffer.text("Toggle point light rotation", rightX, y);
y += spacing;
mainBuffer.fill(defaultColor);
mainBuffer.textFont(robotoBlack);
mainBuffer.text("C", x, y);
mainBuffer.textFont(robotoRegular);
mainBuffer.fill(useColor ? enabledColor : disabledColor);
mainBuffer.text("Toggle color mapping", rightX, y);
y += spacing;
mainBuffer.fill(defaultColor);
mainBuffer.textFont(robotoBlack);
mainBuffer.text("N", x, y);
mainBuffer.textFont(robotoRegular);
mainBuffer.fill(useNormal ? enabledColor : disabledColor);
mainBuffer.text("Toggle normal mapping", rightX, y);
y += spacing;
mainBuffer.fill(defaultColor);
mainBuffer.textFont(robotoBlack);
mainBuffer.text("A", x, y);
mainBuffer.textFont(robotoRegular);
mainBuffer.fill(useAO ? enabledColor : disabledColor);
mainBuffer.text("Toggle ambient occlusion mapping", rightX, y);
y += spacing;
mainBuffer.fill(defaultColor);
mainBuffer.textFont(robotoBlack);
mainBuffer.text("S", x, y);
mainBuffer.textFont(robotoRegular);
mainBuffer.fill(useSpecular ? enabledColor : disabledColor);
mainBuffer.text("Toggle specular mapping", rightX, y);
y += spacing;
mainBuffer.fill(defaultColor);
mainBuffer.textFont(robotoBlack);
mainBuffer.text("D", x, y);
mainBuffer.textFont(robotoRegular);
mainBuffer.fill(useDepth ? enabledColor : disabledColor);
mainBuffer.text("Toggle depth mapping", rightX, y);
y += 1.5 * spacing;
mainBuffer.fill(defaultColor);
mainBuffer.textFont(robotoBlack);
mainBuffer.text("H", x, y);
mainBuffer.textFont(robotoRegular);
mainBuffer.fill(enabledColor);
mainBuffer.text("Toggle HUD", rightX, y);
}
mainBuffer.pop();
}