【问题标题】:OpenGL - Draw object with image texture from .obj/.mtlOpenGL - 使用来自 .obj/.mtl 的图像纹理绘制对象
【发布时间】:2020-11-17 17:04:23
【问题描述】:

我正在尝试使用 OpenGL 和适用于 Android 的 Google Cardboard 创建具有图像纹理的立方体。我的代码主要基于谷歌的演示代码here。我可以很好地渲染黑色/无纹理立方体,但纹理是我卡住的地方。


文件

这是 .obj 文件:

mtllib 9c9ab3c3-ea26-4524-88f5-a524b6bb6057.mtl

g Mesh1 Model

usemtl Tile_Hexagon_White
v 2.16011 0 -2.27458
vt -7.08697 8.39536
vn 0 -1 -0
v 1.16011 0 -1.27458
vt -3.80613 4.70441
v 1.16011 0 -2.27458
vt -3.80613 8.39536
f 1/1/1 2/2/1 3/3/1

v 2.16011 0 -1.27458
vt -7.08697 4.70441
f 2/2/1 1/1/1 4/4/1

vt 7.46254 0
vn 1 0 -0
v 2.16011 1 -1.27458
vt 4.1817 3.69094
vt 4.1817 0
f 1/5/2 5/6/2 4/7/2

v 2.16011 1 -2.27458
vt 7.46254 3.69094
f 5/6/2 1/5/2 6/8/2

vt -7.08697 0
vn 0 0 -1
v 1.16011 1 -2.27458
vt -3.80613 3.69094
vt -7.08697 3.69094
f 1/9/3 7/10/3 6/11/3

vt -3.80613 0
f 7/10/3 1/9/3 3/12/3

vt -4.1817 0
vn -1 0 -0
vt -7.46254 3.69094
vt -7.46254 0
f 2/13/4 7/14/4 3/15/4

v 1.16011 1 -1.27458
vt -4.1817 3.69094
f 7/14/4 2/13/4 8/16/4

vt 3.80613 0
vn 0 0 1
vt 7.08697 3.69094
vt 3.80613 3.69094
f 2/17/5 5/18/5 8/19/5

vt 7.08697 0
f 5/18/5 2/17/5 4/20/5

vt 7.08697 4.70441
vn 0 1 -0
vt 3.80613 8.39536
vt 3.80613 4.70441
f 5/21/6 7/22/6 8/23/6

vt 7.08697 8.39536
f 7/22/6 5/21/6 6/24/6

这是 .mtl 文件:

newmtl Tile_Hexagon_White
Ka 0.000000 0.000000 0.000000
Kd 0.835294 0.807843 0.800000
Ks 0.330000 0.330000 0.330000
map_Kd 9c9ab3c3-ea26-4524-88f5-a524b6bb6057/Tile_Hexagon_White.jpg

newmtl ForegroundColor
Ka 0.000000 0.000000 0.000000
Kd 0.000000 0.000000 0.000000
Ks 0.330000 0.330000 0.330000

纹理只是一个重复的六边形图案,我想覆盖整个立方体:


代码

  1. 加载 OBJ 文件并将数据分成数组。

我有 Vertices_[108]、UV_[72] 和 Indices_[36]。我确信程序此时可以正常运行,但如有必要,我可以提供这些值。

  1. 我加载图片后:
GLuint texture_id;
    glGenTextures(1, &texture_id);

    imageNum = texture_id;

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

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
      

    /*I don't really know how this block of code works but it's supposed to Load an image from the asset manager.
     * env - the JNIEnv* environment
     * java_asset_mgr - AAssetManager for fetching files
     * path - the path and name of my texture
     */
    jclass bitmap_factory_class =
            env->FindClass("android/graphics/BitmapFactory");
    jclass asset_manager_class =
            env->FindClass("android/content/res/AssetManager");
    jclass gl_utils_class = env->FindClass("android/opengl/GLUtils");
    jmethodID decode_stream_method = env->GetStaticMethodID(
            bitmap_factory_class, "decodeStream",
            "(Ljava/io/InputStream;)Landroid/graphics/Bitmap;");
    jmethodID open_method = env->GetMethodID(
            asset_manager_class, "open", "(Ljava/lang/String;)Ljava/io/InputStream;");
    jmethodID tex_image_2d_method = env->GetStaticMethodID(
            gl_utils_class, "texImage2D", "(IILandroid/graphics/Bitmap;I)V");

    jstring j_path = env->NewStringUTF(path.c_str());
    RunAtEndOfScope cleanup_j_path([&] {
        if (j_path) {
          env->DeleteLocalRef(j_path);
        }
    });
    
    jobject image_stream =
            env->CallObjectMethod(java_asset_mgr, open_method, j_path);
    jobject image_obj = env->CallStaticObjectMethod(
            bitmap_factory_class, decode_stream_method, image_stream);

    env->CallStaticVoidMethod(gl_utils_class, tex_image_2d_method, GL_TEXTURE_2D, 0,
                              image_obj, 0);


    glGenerateMipmap(GL_TEXTURE_2D);
  1. 绘制:
  //obj_program has a vertex shader and fragment shader attached.
  glUseProgram(obj_program_);

  std::array<float, 16> target_array = modelview_projection_target_.ToGlArray();
  glUniformMatrix4fv(obj_modelview_projection_param_, 1, GL_FALSE,
                     target_array.data());


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

  //DRAW
  glEnableVertexAttribArray(0);
  glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, Vertices_.data());

  glEnableVertexAttribArray(1);
  glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, Uv_.data());

  glDrawElements(GL_TRIANGLES, Indices_.size(), GL_UNSIGNED_SHORT,
                 Indices_.data());

结果

我最终得到一个纹理奇怪的立方体,我不确定是什么原因造成的。

我相信会有问题,所以我会尽力回答并提供任何有帮助的信息!

【问题讨论】:

  • 你的纹理坐标很奇怪。它们通常(几乎总是)范围为 0..0.99。
  • @3Dave 就是这样!显然,超出此范围的值用于重复纹理。在图像加载的顶部附近,您可以看到我使用了 GL_CLAMP_TO_EDGE。我将它切换到 GL_REPEAT 并且效果很好!

标签: c++ opengl-es google-cardboard


【解决方案1】:

问题是我的纹理需要重复。这两行是从

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

【讨论】:

    猜你喜欢
    • 2020-03-09
    • 2011-02-23
    • 2013-05-06
    • 1970-01-01
    • 2015-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多