Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save companje/10c44743911955ea71cca39355b7d206 to your computer and use it in GitHub Desktop.
Save companje/10c44743911955ea71cca39355b7d206 to your computer and use it in GitHub Desktop.
3D Sphere to CubeMap to Equirectangular texture
PImage earth;
PShape globe;
PGraphics fbo[] = new PGraphics[6];
int cubemapSize = 1024;
PImage output_texture;
PImage tex;
PGraphics view3D,ortho3D;
float h, hd2;
PVector center[] = {
new PVector(-1, 0, 0), // afrika
new PVector(1, 0, 0), // japan (wrap)
new PVector(0, -1, 0), // noordpool
new PVector(0, 1, 0), // zuidpool
new PVector(0, 0, 1), // india
new PVector(0, 0, -1) // zuid-amerika
};
PVector up[] = {
new PVector(0, -1, 0), // afrika
new PVector(0, 1, 0), // japan (wrap)
new PVector(0, 0, 1), // noordpool
new PVector(0, 0, -1), // zuidpool
new PVector(0, -1, 0), // india
new PVector(0, 1, 0) // zuid-amerika
};
PVector rotateY(PVector v, float angle) {
return new PVector(
cos(angle) * v.x + sin(angle) * v.z,
v.y,
-sin(angle) * v.x + cos(angle) * v.z
);
}
void setup() {
size(1536, 512, P3D);
h=height;
hd2=h/2;
earth = loadImage("earth.jpg");
tex = createImage(1024, 512, RGB);
view3D = createGraphics((int)h, (int)h, P3D);
ortho3D = createGraphics((int)h, (int)h, P3D);
globe = createShape(SPHERE, hd2);
globe.rotateY(HALF_PI);
globe.setStroke(false);
globe.setTexture(earth);
for (int i = 0; i < 6; i++) {
fbo[i] = createGraphics(cubemapSize, cubemapSize, P3D);
}
}
void draw() {
background(0);
renderToTexture(fbo, tex);
image(tex, h, 0, h*2, h);
renderToDome(view3D);
image(view3D, 0, 0);
renderOrtho(ortho3D);
image(ortho3D, 0, 0);
}
void render(PGraphics pg) {
pg.background(0);
pg.shape(globe);
pg.translate(0, 0, 185);
pg.fill(255, 255, 0);
pg.textAlign(CENTER);
pg.textSize(30);
pg.text("HELLO PROJECTION", 0, 0);
}
void renderOrtho(PGraphics pg) {
pg.beginDraw();
pg.ortho();
pg.camera(0, 0, 0, 0, 0, hd2, 0, 1, 0);
pg.scale(-1, 1, 1);
render(pg);
pg.endDraw();
}
void renderToDome(PGraphics pg) {
float eyeZ = 1900, distToCam = 1900;
pg.beginDraw();
pg.perspective(atan(hd2/distToCam)*2, 1, distToCam, 10000);
pg.camera(0, 0, -distToCam, 0, 0, 0, 0, 1, 0);
pg.scale(-1, 1, 1);
render(pg);
pg.endDraw();
}
void renderToTexture(PGraphics fbo[], PImage tex) { //via cubemap
int c[][] = {
{0, 0, 1, 0, -1, 0},
{0, 0, -1, 0, 1, 0},
{0, -1, 0, 1, 0, 0},
{0, 1, 0, -1, 0, 0},
{1, 0, 0, 0, -1, 0},
{-1, 0, 0, 0, 1, 0}};
for (int i = 0; i < 6; i++) {
fbo[i].beginDraw();
fbo[i].camera(0, 0, 0, c[i][0], c[i][1], c[i][2], c[i][3], c[i][4], c[i][5]);
fbo[i].perspective(HALF_PI, 1.0, 1, 1000);
render(fbo[i]);
fbo[i].endDraw();
fbo[i].loadPixels();
}
convertToTexture(tex, 1024, 512);
}
PImage convertToTexture(PImage tex, int w, int h) {
tex.loadPixels();
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
float u = map(x, 0, w, -PI, PI);
float v = map(y, 0, h, HALF_PI, -HALF_PI);
PVector dir = new PVector(cos(v) * cos(u), sin(v), cos(v) * sin(u));
tex.pixels[y * w + x] = sampleFromCubemap(dir);
}
}
tex.updatePixels();
return tex;
}
color sampleFromCubemap(PVector dir) {
float ax = abs(dir.x), ay = abs(dir.y), az = abs(dir.z);
boolean xGreatest = ax >= ay && ax >= az, yGreatest = ay >= az;
int face = xGreatest ? (dir.x > 0 ? 0 : 1) :
yGreatest ? (dir.y > 0 ? 2 : 3) :
dir.z > 0 ? 4 : 5;
float uc = xGreatest ? dir.z / ax :
yGreatest ? dir.x / ay :
-dir.x / az;
float vc = (face % 2 == 0 ? 1 : -1) *
(xGreatest ? dir.y / ax :
yGreatest ? dir.z / ay :
dir.y / az);
int px = int(map(uc, -1, 1, 0, fbo[face].width - 1));
int py = int(map(vc, -1, 1, 0, fbo[face].height - 1));
return fbo[face].pixels[py*fbo[face].width+px];
}
@companje
Copy link
Author

Screenshot 2025-02-12 at 21 03 11

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment