2

I want to make a program that shows the earth with a space texture as the background.

  • The earth is a 3D Uniform with a earth texture (.bmp).

  • The space with the stars is a texture (.bmp).

I have summarized what I have to do:

  • Create a new Model Matrix
  • Position it at the same place where the camera is
  • Disable depth test before drawing
  • Reverse culling

This is the Load function:

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

     }

This is the Draw function:

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

    }

Also I have two Fragment Shaders:

  • The first one returns this:

    fragColor = vec4(final_color, 1.0);
    
  • The second one returns this:

    fragColor = vec4(texture_color.xyz, 1.0);
    

Also the Vertex Shader returns the position of the vertex:

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

When I compile, it only shows the earth while it should show the earth and the space as background. I have reviewed the code several times but I can not find out what it is.

  • Suposed result:

suposed_result

  • My Result

my_result

Peter Palmer
  • 726
  • 11
  • 18
  • What does it mean that? @Rabbid76 – Peter Palmer Jan 08 '19 at 10:52
  • This may be interesting for you: [OpenGL SkyBox](http://ogldev.atspace.co.uk/www/tutorial25/tutorial25.html). For our software, we have also a sky box texture with stars and a planet (found in web) but I believe it's totally fictitious. ;-) – Scheff's Cat Jan 08 '19 at 11:11
  • 1
    Might I suggest it may be simpler to write and debug if you drop the matrix for drawing the background? It's just a rect between (-1,-1) and (1,1), it doesn't need any transformation. – Andrea Jan 08 '19 at 11:27

1 Answers1

5
  1. If I see it right among other things you are wrongly binding textures

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

    should be:

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

    but I prefer that last set active units is 0 ...

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

    that will save you a lot of troubles when you start combine code with single texture unit code ... Also hope you are properly unbinding the used texture units for the same reasons...

  2. You got ugly seam on the edge 0/360deg of longitude

    this might be caused by wrongly computed normal for lighting, wrong not seamless texture or just by forgeting to duplicate the edge points with correct texture coordinates for the last patch. See:

    You can also add atmosphere,bump map, clouds to your planet:

  3. Andrea is right...

    set matrices as unit matrix and render (+/-)1.0 rectangle at z=0.0 +/- aspect ratio correction without depth test, face culling and depth write ... That way you will avoid jitter and flickering stuff due to floating point errors.

  4. Skybox is better but there are also other options to enhance

    and all the sublinks in there especially stars. You can combine skybox and stellar catalog together and much much more...

Spektre
  • 49,595
  • 11
  • 110
  • 380
  • When I bind the textures as you told me, then displays nothing, I don't know why. – Peter Palmer Jan 08 '19 at 19:01
  • @PedroGarcía-Mauriño I do not see the shaders are you sure you're using or even if should multitexturing for this? unless you are doing environment reflections you do not need 2 texture units. You claim you got 2 shaders. you can run only one at a time so you should bind program1 , set its uniforms and config the GL with texture1 (Unit0) render obj1, then bind program 2 set its uniforms and config the GL with texture2 (also to unit0) and render obj2... In case of multitexturing you would have just one shader and 2 texture units but the rendered primitive would most likely not be a sphere. – Spektre Jan 08 '19 at 19:40
  • @PedroGarcía-Mauriño after that bind program `0` (unbind) unbind also texture units used and that is it ... I did not examine your code in depth just had a glance at it but I am afraid I do not see the proper or at least expected order of the GL calls ... I see just single `glUseProgram` call so I expect multitexturing hence what mesh is in your VBO? if just sphere then do not expect background. If rectangle covering screen then you got bug in shaders ... either discard instead of fetching the background texture or wrong condition or god knows as I do not see the code used... – Spektre Jan 08 '19 at 19:47