当前位置: 首页 > 知识库问答 >
问题:

OpenGL将纹理映射到球体

韩志专
2023-03-14

我有一个OpenGL程序,我想用地球的位图对球体进行纹理处理。我在搅拌器中准备了网格,并将其导出到OBJ文件。该程序加载适当的网格数据(顶点、uv和法线)和正确的位图-我已经用骨骼位图检查了它的纹理立方体。

我的程序是纹理球体,但不正确(或以我不期望的方式)。这个球体的每个三角形都包括这个位图的变形副本。我检查了位图,uv似乎没问题。我尝试了多种尺寸的位图(2的幂,2的倍数等)。

纹理是这样的:

我的程序截图(就像它会忽略我的UV):

我用这种方法在Blender中映射UV:

加载纹理后进行代码设置(除了将纹理添加到VBO中的代码-我认为这没问题):

  GLuint texID;
  glGenTextures(1,&texID);
  glBindTexture(GL_TEXTURE_2D,texID);
  glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,width,height,0,GL_BGR,GL_UNSIGNED_BYTE,(GLvoid*)&data[0]);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);

是否需要任何额外的代码来正确映射此纹理?

[Edit]初始化纹理(前面的代码在LoadTextureBMP_custom()函数中)

bool Program::InitTextures(string texturePath)
{
  textureID = LoadTextureBMP_custom(texturePath);
  GLuint TBO_ID;
  glGenBuffers(1,&TBO_ID);
  glBindBuffer(GL_ARRAY_BUFFER,TBO_ID);
  glBufferData(GL_ARRAY_BUFFER,uv.size()*sizeof(vec2),&uv[0],GL_STATIC_DRAW);
  return true;
}

我的主循环:

bool Program::MainLoop()
{
  bool done = false;
  mat4 projectionMatrix;
  mat4 viewMatrix;
  mat4 modelMatrix;
  mat4 MVP;

  Camera camera;
  shader.SetShader(true);

  while(!done)
  {
    if( (glfwGetKey(GLFW_KEY_ESC)))
      done = true;
    if(!glfwGetWindowParam(GLFW_OPENED))
      done = true;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Tutaj przeksztalcenia macierzy
    camera.UpdateCamera();
    modelMatrix = mat4(1.0f);
    viewMatrix = camera.GetViewMatrix();
    projectionMatrix = camera.GetProjectionMatrix();
    MVP = projectionMatrix*viewMatrix*modelMatrix;
    // Koniec przeksztalcen

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D,textureID);

    shader.SetShaderParameters(MVP);

    SetOpenGLScene(width,height);

    glEnableVertexAttribArray(0); // Udostepnienie zmiennej Vertex Shadera => vertexPosition_modelspace
    glBindBuffer(GL_ARRAY_BUFFER,VBO_ID);
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0);

    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER,TBO_ID);
    glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,0,(void*)0);

    glDrawArrays(GL_TRIANGLES,0,vert.size());

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);

    glfwSwapBuffers();
  }
  shader.SetShader(false);

  return true;
}

VS:

#version 330

layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec2 vertexUV;
out vec2 UV;

uniform mat4 MVP;

void main()
{
  vec4 v = vec4(vertexPosition,1.0f);
  gl_Position = MVP*v;
  UV = vertexUV;
}

FS:

#version 330

in vec2 UV;
out vec4 color;

uniform sampler2D texSampler; // Uchwyt tekstury

void main()
{
  color = texture(texSampler, UV);
}

共有2个答案

凌琦
2023-03-14

最后,我得到了答案。这里有一个错误:

bool Program::InitTextures(string texturePath)
{
  textureID = LoadTextureBMP_custom(texturePath);
  // GLuint TBO_ID; _ERROR_
  glGenBuffers(1,&TBO_ID);
  glBindBuffer(GL_ARRAY_BUFFER,TBO_ID);
  glBufferData(GL_ARRAY_BUFFER,uv.size()*sizeof(vec2),&uv[0],GL_STATIC_DRAW);
}

有Program类声明部分:

class Program
{
 private:
  Shader shader;
  GLuint textureID;

  GLuint VAO_ID;
  GLuint VBO_ID;
  GLuint TBO_ID; // Member covered with local variable declaration in InitTextures()
  ...
}

我错误地声明了局部TBO_ID,覆盖了类范围内的TBO_ID。UV生成的精度很差,接缝很可怕,但它们不是问题。

我必须承认我提供的信息太少,无法提供帮助。我应该把程序类的所有代码都放进去。感谢所有尝试过的人。

祝灼光
2023-03-14

我没有做过任何专业的GL编程,但我一直在使用3D软件。

  • 你的紫外线很可能不好
  • 你的纹理不适合投射在球体上
  • 考虑到紫外线不好,你可能也想检查一下你的正常值
  • 考虑使用ISOSPINE而不是常规ISOSPINE来更有效地使用多边形

您目前使用的是带有平面贴图的平面纹理,这可能会给您带来非常难看的结果,因为“外部”周界的分辨率非常低,如果您愿意,很可能是两个投影相交的一个令人讨厌的接缝伪影。。。旋转行星什么的。

请注意,你不需要有任何特定的UV贴图,它只需要正确的几何图形,它看起来不像现在这样。球面映射将处理剩下的部分。由于大多数地球纹理都在一个合适的投影中,所以你可能也可以使用柱面地图。

 类似资料:
  • 我已经创建了两个球体,目前正在尝试对它们进行纹理处理。然而,纹理坐标似乎有点偏离。 纹理应用于两个球体的结果(你可以忽略不在正方形周围的黑线,这只是相机-是的,这是AR应用程序): 现在,我使用perl脚本导出球体,我发现它将obj文件转换为顶点和纹理代码列表OBJ2OPENGL。obj文件已转换为2160顶点。 当我渲染球体时:

  • 有了这个功能,我可以在Android系统的OpenGL ES 1.0中创建一个球体: 我现在的问题是,我想在球体上使用这个纹理,但是只创建了一个黑色的球(当然,因为右上角是黑色的)。我使用这个纹理坐标是因为我想使用整个纹理: 要正确使用纹理,我需要做什么?

  • 我试图在从Blender导出的球体周围映射一个纹理。该模型在Blender中看起来很棒,但当我在Android应用程序中使用它时,纹理似乎映射到了几乎每一张脸,而不是整个球体。有什么想法吗?我在Android上使用libGDX。 设置代码: 渲染代码:

  • 本文向大家介绍java实现OpenGL ES纹理映射的方法,包括了java实现OpenGL ES纹理映射的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了java实现OpenGL ES纹理映射的方法。分享给大家供大家参考。具体如下: 1. GlRenderer.java文件: 2. Square.java文件: 3. Triangle.java文件: 4. Run.java文件: 希望

  • 我正在尝试使用OpenGL GLSL着色器渲染到纹理。首先,我尝试用白色填充30x30纹理的每个像素。我将顶点着色器索引从0传递到899,表示纹理的每个像素。对吗?顶点着色器: 片段着色器:

  • 我正在尝试使用“gl BlitFrameBuffer”将一个纹理复制到另一个纹理中,我正在处理来自android NDK-Samples的经典开放式gl示例hello-gl2。我改变了着色器,以支持纹理,我可以正确地渲染一个纹理三角形。我还更改了在Java端请求的opengl es版本,以便请求opengl-es3,并且我更新了Cmakelists文件以链接正确的库。调用后,我得到了blitTex