I am new in the OpenGL - GLSL and trying to make a shader that taking a mercator projection texture as a source and converting it to an equirectangular projection texture.
Sample input: (1024x1024)
Desired output (1024x512)
I found this question, that have a similar problem in unity3d. But i stuck to understand it.
I have a C# code that do this task, using WindowsForms
, but it's not efficient.
static class Program
{
const double TWO_PI = Math.PI * 2;
const double PI180 = Math.PI / 180;
private static double Clip(double value, double min, double max)
{
return Math.Min(Math.Max(value, min), max);
}
public static PointF PixelXYToLatLong(int X, int Y, int mapSize)
{
PointF coordinate = new PointF();
double x = (Clip(X, 0, mapSize - 1) / mapSize) - 0.5;
double y = 0.5 - (Clip(Y, 0, mapSize - 1) / mapSize);
coordinate.X = (float)(360 * x);
coordinate.Y = (float)(90 - 360 * Math.Atan(Math.Exp(0 - y * 2 * Math.PI)) / Math.PI);
return coordinate;
}
static void Main()
{
Bitmap source = new Bitmap("INPUT_PATH");
int w = source.Width;
int h = source.Height;
int dh = h >> 1;
Bitmap des = new Bitmap(w, dh);
dh = dh >> 1;
int dw = w >> 1;
double r = w / TWO_PI;
for (int i = 0; i < w; i++)
{
for (int j = 0; j < h; j++)
{
Color color = source.GetPixel(i, j);
PointF point = PixelXYToLatLong(i, j, w);
double x = point.X * PI180;
double y = point.Y * PI180;
x = r * x;
y = r * y;
x = Math.Round(dw + x);
y = Math.Round(dh - y);
des.SetPixel((int)x, (int)y, color);
}
}
des.Save("OUTPUT_PATH");
source.Dispose();
des.Dispose();
}
}
So i try to implement it in c++ and OpenGL.
My vertex and fragment shaders
const GLchar* vertexSource = R"glsl(
#version 330 core
layout (location = 0) in vec3 texPos;
layout (location = 1) in vec2 texCoord;
out vec2 TexCoord;
void main()
{
gl_Position.xyz = texPos.xyz;
gl_Position.w = 1.0;
TexCoord = texCoord;
}
)glsl";
const GLchar* fragmentSource = R"glsl(
#version 330 core
in vec2 TexCoord;
uniform sampler2D ourTexture;
void main(){
float pi180 = 3.14159265 / 180;
float r = 1 / (2 * 3.14159265);
float x = min(max(TexCoord.x, 0), 1) - 0.5;
float y = 0.5 - min(max(TexCoord.y, 0), 1);
x = 360 * x;
y = 90 - (360 * atan(exp(0 - y * 2 * 3.14159265)) / 3.14159265);
x = x * pi180;
y = y * pi180;
x = 0.5 + (r * x);
y = 0.5 - (r * y);
gl_FragColor = texture(ourTexture, vec2(x,y));
}
)glsl";
And my vertex buffer:
static const GLfloat g_vertex_buffer_data[] = {
1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 1.0f
}
Output:
As you can see there are a lot of problems.
Also i try to change texture wrapping to GL_REPEAT
, GL_MIRRORED_REPEAT
, GL_CLAMP_TO_EDGE
and GL_CLAMP_TO_BORDER
, as below:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
And glViewport(0, 0, 512, 256)
but without any success.
So where I'm wrong?
Sorry for the long question, Thanks in advance.