如何在OpenGL中将纹理设置为背景?

时间:2019-01-08 10:20:34

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

我想制作一个程序,以空间纹理为背景,显示地球

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

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

我总结了要做的事情:

  • 创建一个新的模型矩阵
  • 将其放在相机所在的位置
  • 在绘制之前禁用深度测试
  • 反向淘汰

这是 Load 函数:

     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);

     }

这是 Draw 函数:

    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);
    

顶点着色器还返回顶点的位置:

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

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

  • 预期结果:

suposed_result

  • 我的结果

my_result

1 个答案:

答案 0 :(得分:5)

  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)是对的...

    将矩阵设置为单位矩阵,并在(+/-)1.0 +/-纵横比校正下渲染z=0.0矩形,而无需进行深度测试,面部剔除和深度写入...这样,您将避免由于抖动和闪烁而产生的东西浮点错误。

  4. Skybox更好,但还有其他增强功能

    以及其中的所有子链接,尤其是星星。您可以将skybox和星表合并在一起,还有更多...