Hi!
I am a bit of a newbie with shader, so excuse me if this is too basic.
I am trying to map a plannar FBO into a sphere of changing radius. I guess that this should be done in the vertex shader better than in the fragment shader., but I can’t find the way to do it.
Any suggestion? How to map the cartesian 2D into a sphere? I’ve found info about Mercator projection, -it should be the other way around, but that’s OK- but I can’t find the way to implement it in the vertex file.

Thanks a lot!
D!

I have very little experience with shader programming, but mapping a plane to a sphere is not too difficult (depending on exactly what you want…)

A sphere has a circumference of 2pi (or 360 degrees if you want), so you need to map the x coordinates from 0 to 2pi and the y coordinates from 0 to pi. Then you can convert these coordinates (basically latitude and longitude) to spherical coordinates to plot them on a sphere. Think about a map of the earth you want to wrap around a sphere…

the code to map an image/fbo with a given width/height to a sphere would look something like this…

``````ofMesh mesh;
float width = 500;
float height = 250;
vector <float> longitude;
vector <float> latitude;

for (int x=0; x<width; x++) {
for (int y=0; y<height; y++) {
latitude.push_back( ofMap(x, 0, width, 0, (2*PI) ) );
longitude.push_back( ofMap(y, 0, height, 0, PI ) );
}
}

for (unsigned i = 0; i<longitude.size(); i++) {
float longTMP = longitude[i];
float latTMP = latitude[i];
float X = ( SphereRadius * cos(latTMP) * sin(longTMP) );
float Y = ( SphereRadius * sin(latTMP) * sin(longTMP) );
float Z = ( SphereRadius * cos(longTMP) );
ofVec3f temp = ofVec3f(X,Y,Z);
}
``````

I used code similar to this to generate a globe that would not look out of place in the next tron movie  Unfortunately, I don’t know how to apply this trick in a shader, maybe someone else can help out?

1 Like

Hi innodle!
You project looks really interesting! I hope this could help.
This code has been developed by Javier Villaroel as estated in the coments. I used it in a fragment shader with great results. Begin it before drawing the FBO, pass the paramenters, draw and finish it after all , just the regular way.

``````//////////////////////////////////////////////////////////////////////
//                                                                  //
//                                                                  //
//  Code developed by Javier Villaroel,                             //
//                  Madrid, Spain, March 2015                       //
//                  javier@ultra-lab.net                            //
//                  www.ultra-lab.net                               //
//                                                                  //
//////////////////////////////////////////////////////////////////////

#ifdef GL_ES
precision mediump float;
#endif

uniform sampler2DRect texture0;

uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;

void main(void)
{
vec2 center = resolution/2.0;

vec2 pos = gl_TexCoord.xy;
float pi = 3.1415;
float R;
vec2 r = pos - center;
float mr = length(r);
vec2 posM;
float angT = 0.0;//10.0*time;

float expansionT = 5.0;
float giroT = 20.0;

if (time < expansionT){

} else {
if ( time < giroT + expansionT){
R = resolution.y * 0.5;
angT =  0.5 * resolution.y * sin(2.0*pi*(time - expansionT)/giroT);
} else {
+ resolution.y*0.5;
}
}

if(length(r) < R)
{

float theta = acos(-r.y/R)/pi;  //angulo con respecto a los polos
float phi = abs(atan(sqrt(abs(R*R - r.x*r.x - r.y*r.y))/r.x))/pi; //angulo en el plano XY de la esfera

float ajusteP = resolution.y / 2.0 + resolution.x / 2.0 - angT;
float ajusteN = resolution.x / 2.0 - resolution.y / 2.0 - angT;

if(R <= resolution.y / 2.0)
{
posM.y = resolution.y * theta;
posM.x = resolution.y * phi;
}

if(R > resolution.y / 2.0 )
{
float alpha = acos(resolution.y/(2.0*R))/pi;
float A = resolution.y /(1.0-(2.0*alpha));

float beta = acos(resolution.y/(2.0*R))/pi;
float B = resolution.y /(1.0-(2.0*beta));

posM.y = A * (theta - alpha);
posM.x = B * (phi - beta);
}

if(r.x > 0.0){
posM.x =  ajusteP - posM.x;
} else {
posM.x += ajusteN;
}

if (posM.x <= 0.0 || posM.y <= 0.0 || posM.y > resolution.y || posM.x > resolution.x){
} else {
vec4 color = texture2DRect(texture0, posM);
gl_FragColor = color;
}

} else {