【问题标题】:How to set a texture as background in OpenGL?如何在OpenGL中将纹理设置为背景?
【发布时间】:2019-06-03 00:30:32
【问题描述】:

我想制作一个程序,以 space 纹理为背景显示 earth

  • 地球是具有地球纹理 (.bmp) 的 3D 制服。

  • 带有星星的空间是一个纹理 (.bmp)。

我已经总结了我要做的事情:

  • 创建一个新的模型矩阵
  • 将其放置在摄像头所在的同一位置
  • 绘图前禁用深度测试
  • 反向剔除

这是加载函数:

     void load(){

    //Load The Shader
    Shader simpleShader("src/shader.vert", "src/shader.frag");
    g_simpleShader = simpleShader.program;

    // Create the VAO where we store all geometry (stored in g_Vao)
    g_Vao = gl_createAndBindVAO();

    //Create vertex buffer for positions, colors, and indices, and bind them to shader
    gl_createAndBindAttribute(&(shapes[0].mesh.positions[0]), shapes[0].mesh.positions.size() * sizeof(float), g_simpleShader, "a_vertex", 3);
    gl_createIndexBuffer(&(shapes[0].mesh.indices[0]), shapes[0].mesh.indices.size() * sizeof(unsigned int));
    gl_createAndBindAttribute(uvs, uvs_size, g_simpleShader, "a_uv", 2);
    gl_createAndBindAttribute(normal, normal_size, g_simpleShader, "a_normal", 2);

    //Unbind Everything
    gl_unbindVAO();

    //Store Number of Triangles (use in draw())
    g_NumTriangles = shapes[0].mesh.indices.size() / 3;

    //Paths of the earth and space textures
    Image* image = loadBMP("assets/earthmap1k.bmp");
    Image* space = loadBMP("assets/milkyway.bmp");

    //Generate Textures
    glGenTextures(1, &texture_id);
    glGenTextures(1, &texture_id2);

    //Bind Textures
    glBindTexture(GL_TEXTURE_2D, texture_id);
    glBindTexture(GL_TEXTURE_2D, texture_id2);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    //We assign your corresponding data
    glTexImage2D(GL_TEXTURE_2D,1,GL_RGB,image->width, image->height,GL_RGB,GL_UNSIGNED_BYTE,image->pixels);
    glTexImage2D(GL_TEXTURE_2D,1,GL_RGB,space->width, space->height,GL_RGB,GL_UNSIGNED_BYTE,space->pixels);

     }

这是绘图函数:

    void draw(){

    //1. Enable/Disable
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glDisable(GL_DEPTH_TEST);   
    glEnable(GL_CULL_FACE);     
    glCullFace(GL_FRONT);   

    //2. Shader Activation
    glUseProgram(g_simpleShader); 

    //3. Get All Uniform Locations

    //Space:
    GLuint model_loc2 = glGetUniformLocation (g_simpleShader, "u_model");
    GLuint u_texture2 = glGetUniformLocation(g_simpleShader, "u_texture2");
    GLuint u_light_dir2 = glGetUniformLocation(g_simpleShader,"u_light_dir2");

    //Earth
    GLuint model_loc = glGetUniformLocation(g_simpleShader, "u_model"); 
    GLuint projection_loc = glGetUniformLocation(g_simpleShader, "u_projection");
    GLuint view_loc = glGetUniformLocation(g_simpleShader, "u_view");
    GLuint u_texture = glGetUniformLocation(g_simpleShader, "u_texture");
    GLuint u_light_dir = glGetUniformLocation(g_simpleShader, "u_light_dir");

    //4. Get Values From All Uniforms
    mat4 model_matrix2 = translate(mat4(1.0f), vec3(1.0f,-3.0f,1.0f));
    mat4 model_matrix = translate(mat4(1.0f),vec3(0.0f,-0.35f,0.0f);
    mat4 projection_matrix = perspective(60.0f,1.0f,0.1f,50.0f);
    mat4 view_matrix = lookAt(vec3( 1.0f, -3.0f,  1.0f),vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f)glm::vec3(0,1,0));

     //5. Upload Uniforms To Shader
     glUniformMatrix4fv(model_loc2, 1, GL_FALSE, glm::value_ptr(model_matrix2));

    glUniformMatrix4fv(model_loc, 1, GL_FALSE, glm::value_ptr(model_matrix));
    glUniformMatrix4fv(projection_loc, 1, GL_FALSE, glm::value_ptr(projection_matrix));
    glUniformMatrix4fv(view_loc, 1, GL_FALSE, glm::value_ptr(view_matrix));

    glUniform1i(u_texture, 0);
    glUniform3f(u_light_dir, g_light_dir.x, g_light_dir.y, g_light_dir.z);

    glUniform1i(u_texture2, 1);
    glUniform3f(u_light_dir2, g_light_dir.x, g_light_dir.y, g_light_dir.z);

    //6. Activate Texture Unit 0 and Bind our Texture Object
    glActiveTexture(GL_TEXTURE0);
    glActiveTexture(GL_TEXTURE1);

    glBindTexture(GL_TEXTURE_2D, texture_id);
    glBindTexture(GL_TEXTURE_2D, texture_id2);

    //7. Bind VAO
    gl_bindVAO(g_Vao);

    //8. Draw Elements
    glDrawElements(GL_TRIANGLES, 3 * g_NumTriangles, GL_UNSIGNED_INT, 0);

    }

我还有两个片段着色器

  • 第一个返回这个:

    fragColor = vec4(final_color, 1.0);
    
  • 第二个返回这个:

    fragColor = vec4(texture_color.xyz, 1.0);
    

Vertex Shader也返回顶点的位置:

    gl_Position = u_projection * u_view * u_model * vec4( a_vertex , 1.0 );

当我编译时,它只显示地球,而它应该显示地球和空间作为背景。我已经检查了几次代码,但我找不到它是什么。

  • 推测结果:

  • 我的结果

【问题讨论】:

  • 这是什么意思? @Rabbid76
  • 这对您来说可能很有趣:OpenGL SkyBox。对于我们的软件,我们还有一个带有星星和行星的天空盒纹理(在网络上找到),但我相信这完全是虚构的。 ;-)
  • 我是否可以建议如果您删除用于绘制背景的矩阵,编写和调试可能会更简单?它只是一个介于 (-1,-1) 和 (1,1) 之间的矩形,不需要任何转换。

标签: c++ visual-studio opengl visual-studio-2017


【解决方案1】:
  1. 如果我认为它是正确的,那么你错误地绑定了纹理

    glActiveTexture(GL_TEXTURE0);
    glActiveTexture(GL_TEXTURE1);
    
    glBindTexture(GL_TEXTURE_2D, texture_id);
    glBindTexture(GL_TEXTURE_2D, texture_id2);
    

    应该是:

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture_id);
    
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, texture_id2);
    

    但我更喜欢最后设置的活动单位是0 ...

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, texture_id2);
    
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture_id);
    

    当您开始将代码与单个纹理单元代码组合时,这将为您省去很多麻烦...也希望您出于同样的原因正确地取消绑定使用的纹理单元...

  2. 你在经度 0/360 度的边缘有丑陋的接缝

    这可能是由于计算错误的光照法线、错误的非无缝纹理或只是忘记为最后一个补丁复制具有正确纹理坐标的边缘点。见:

    您还可以为您的星球添加大气、凹凸地图、云:

  3. Andrea 是对的……

    将矩阵设置为单位矩阵并在z=0.0 上渲染(+/-)1.0 矩形@ +/- 纵横比校正,无需深度测试、面部剔除和深度写入……这样您就可以避免因浮点错误而导致的抖动和闪烁.

  4. Skybox 更好,但还有其他选项可以增强

    以及其中的所有子链接,尤其是星星。您可以将天空盒和恒星目录组合在一起等等...

【讨论】:

  • 当我按照你说的绑定纹理,然后什么都不显示,我不知道为什么。
  • @PedroGarcía-Mauriño 我没有看到着色器,你确定你正在使用,或者是否应该为此使用多重纹理?除非您进行环境反射,否则您不需要 2 个纹理单元。你声称你有 2 个着色器。您一次只能运行一个,因此您应该绑定 program1 ,设置其制服并使用纹理 1(Unit0)渲染 obj1 配置 GL,然后绑定程序 2 设置其制服并使用纹理 2(也为 unit0)配置 GL 并渲染 obj2 ...在多纹理的情况下,您将只有一个着色器和 2 个纹理单元,但渲染的图元很可能不是球体。
  • @PedroGarcía-Mauriño 在绑定程序 0 (unbind) 之后也取消绑定使用的纹理单元,就是这样......我没有深入检查你的代码,只是看了一眼,但我恐怕我看不到 GL 调用的正确或至少是预期的顺序......我只看到单个 glUseProgram 调用,所以我希望多纹理因此你的 VBO 中有什么网格?如果只是球体,那么不要指望背景。如果矩形覆盖屏幕,那么您在着色器中遇到错误......要么丢弃而不是获取背景纹理或错误条件,要么上帝知道,因为我没有看到使用的代码......
猜你喜欢
  • 1970-01-01
  • 2011-05-01
  • 2016-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多