将矩形纹理映射到球体上

Mapping rectangular texture onto sphere

我想将矩形地球纹理映射到球体上。我可以加载 "globe.jpg" 纹理并将其显示到屏幕上。我想我需要在特定纹理坐标处检索 "globe.jpg" 纹理的颜色,并使用它来为地球上的特定点着色。

我想将右中间的地球地图映射到左侧的其中一个球体上(见图)

加载纹理的代码:

int texture;

public Texture() {
   texture = LoadTexture("Content/globe.jpg");
}

public int LoadTexture(string file) {
        Bitmap bitmap = new Bitmap(file);

        int tex;
        GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);

        GL.GenTextures(1, out tex);
        GL.BindTexture(TextureTarget.Texture2D, tex);

        BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
            ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

        GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
            OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
        bitmap.UnlockBits(data);


        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
        //GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
        //GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);

        return tex;
    }

我也已经创建了一些代码,将球体上的一个点映射到我认为的纹理上的一个点(使用了 https://www.cs.unc.edu/~rademach/xroads-RT/RTarticle.html 上纹理映射球体部分的代码)。

point 是光线与球体相交的 Vector3

        vn = new Vector3(0f, 1f, 0f); //should be north pole of sphere, but it isn't based on sphere's position, so I think it's incorrect
        ve = new Vector3(1f, 0f, 0f); // should be a point on the equator

        float phi = (float) Math.Acos(-1 * Vector3.Dot(vn, point));
        float theta = (float) (Math.Acos(Vector3.Dot(point, ve) / Math.Sin(phi))) / (2 * (float) Math.PI);

        float v = phi / (float) Math.PI;

        float u = Vector3.Dot(Vector3.Cross(vn, ve), point) > 0 ? theta : 1 - theta;

我想我现在可以在我加载的纹理上使用这个 u 和 v 坐标来找到那里的纹理颜色。但我不知道怎么办。我也认为北极和赤道矢量不正确。

我不知道4个月后你是否还需要答案,但是:

如果你有一个正确的球体模型(比如用搅拌机创建的 obj 文件)和正确的 uv 信息,你只需要导入该模型(使用 assimp 或任何其他导入器)并在渲染过程中应用纹理。

你的问题有点模糊,因为我不知道你是否使用着色器。

我的方法是:

1:使用assimp库或任何其他导入库导入模型

2: 实现顶点和片段着色器,并在片段着色器中为纹理包含一个 sampler2D uniform

3: 在渲染过程中 select 你的着色器程序 id [ GL.UseProgram(...) ] 然后将顶点和纹理 uv 和纹理像素(作为统一)信息上传到着色器.

4:像这样使用标准的顶点着色器:

#version 330

in      vec3 aPosition;
in      vec2 aTexture;
out     vec2 vTexture;
uniform mat4 uModelViewProjectionMatrix;

void main()
{
    vTexture = aTexture;
    gl_Position = uModelViewProjectionMatrix * vec4(aPosition, 1.0); 
}

5: 使用像这样的标准片段着色器:

#version 330

in      vec2 vTexture;
uniform sampler2D uTexture;
out vec4 fragcolor;

void main()
{
    fragcolor = texture(uTexture, vTexture);
}

如果您需要具有矩形 uv 映射的球体的有效 obj 文件,请随意添加一行(或两行)。