0
\$\begingroup\$

enter image description hereI have looked for a solution for a little while now however I'm not sure if other people have encountered my same problem. I am trying to draw a skybox in a blank opengl window, I have camera controls and I can zoom out and see the skybox is there but not being textured correctly/ at all. I have used code from opengl and I have only tried to implement it into a class.

Skybox.h

#pragma once

#include "wrapper_glfw.h"
#include <vector>
#include <glm/glm.hpp>
#include <vector>
#include <string>
#include "shader_m.h"
#include "camera.h"



class Skybox
{
public:
    Skybox();
    ~Skybox();
  
  void init(GLWrapper *glw);
  void makeSkybox();
  void drawSkybox(Camera camera, glm::mat4 projection);
  void setFaces(std::string skyboxPath);
  unsigned int loadCubemap();
 
    private:
    std::vector<std::string> faces
    {
        "../src/images/skybox/default/right.jpg",
        "../src/images/skybox/default/left.jpg",
        "../src/images/skybox/default/top.jpg",
        "../src/images/skybox/default/bottom.jpg",
        "../src/images/skybox/default/front.jpg",
        "../src/images/skybox/default/back.jpg"
    };
    
    unsigned int cubemapTexture;
    unsigned int skyboxVAO, skyboxVBO;
    GLuint skyboxShader;

    //skybox, model, view, projection
    GLuint skyboxID, modelID, viewID, projectionID;
;

};

Skybox.cpp

#include "skybox.h"
#include <iostream>
#include <filesystem>

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"


Skybox::Skybox() 
{
}
Skybox::~Skybox()
{
  glDeleteVertexArrays(1, &skyboxVAO);
  glDeleteBuffers(1, &skyboxVBO);
}

void Skybox::init(GLWrapper *glw)
{
  skyboxShader = glw->LoadShader("shaders/skyboxShader/skybox.vert", "shaders/skyboxShader/skybox.frag");
  skyboxID = glGetUniformLocation(skyboxShader, "skybox");
  projectionID = glGetUniformLocation(skyboxShader, "projection");
  viewID = glGetUniformLocation(skyboxShader, "view");
  glUseProgram(skyboxShader);
}

void Skybox::makeSkybox()
{

float skyboxVertices[] = {
    // positions          
    -5.0f,  5.0f, -5.0f,
    -5.0f, -5.0f, -5.0f,
     5.0f, -5.0f, -5.0f,
     5.0f, -5.0f, -5.0f,
     5.0f,  5.0f, -5.0f,
    -5.0f,  5.0f, -5.0f,

    -5.0f, -5.0f,  5.0f,
    -5.0f, -5.0f, -5.0f,
    -5.0f,  5.0f, -5.0f,
    -5.0f,  5.0f, -5.0f,
    -5.0f,  5.0f,  5.0f,
    -5.0f, -5.0f,  5.0f,

     5.0f, -5.0f, -5.0f,
     5.0f, -5.0f,  5.0f,
     5.0f,  5.0f,  5.0f,
     5.0f,  5.0f,  5.0f,
     5.0f,  5.0f, -5.0f,
     5.0f, -5.0f, -5.0f,

    -5.0f, -5.0f,  5.0f,
    -5.0f,  5.0f,  5.0f,
     5.0f,  5.0f,  5.0f,
     5.0f,  5.0f,  5.0f,
     5.0f, -5.0f,  5.0f,
    -5.0f, -5.0f,  5.0f,

    -5.0f,  5.0f, -5.0f,
     5.0f,  5.0f, -5.0f,
     5.0f,  5.0f,  5.0f,
     5.0f,  5.0f,  5.0f,
    -5.0f,  5.0f,  5.0f,
    -5.0f,  5.0f, -5.0f,

    -5.0f, -5.0f, -5.0f,
    -5.0f, -5.0f,  5.0f,
     5.0f, -5.0f, -5.0f,
     5.0f, -5.0f, -5.0f,
    -5.0f, -5.0f,  5.0f,
     5.0f, -5.0f,  5.0f
}; 
  
  // skybox VAO
  glGenVertexArrays(1, &skyboxVAO);
  glGenBuffers(1, &skyboxVBO);
  glBindVertexArray(skyboxVAO);
  glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
  glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
  glEnableVertexAttribArray(0);
  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); 
    
  cubemapTexture = loadCubemap();

  // glUniform1ui(skyboxID, 0);
  glGetError();
}

void Skybox::drawSkybox(Camera camera, glm::mat4 projection)
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  // draw skybox as last
  glDepthFunc(GL_LEQUAL);  // change depth function so depth test passes when values are equal to depth buffer's content
 
  glUniformMatrix4fv(viewID, 1, GL_FALSE, &camera.getView()[0][0]);
    glUniformMatrix4fv(projectionID, 1, GL_FALSE, &projection[0][0]); 
 
  // skybox cube
  glBindVertexArray(skyboxVAO);
  glActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
  glDrawArrays(GL_TRIANGLES, 0, 36);
  glBindVertexArray(0);
  glDepthFunc(GL_LESS); // set depth function back to default
  glUniform1ui(skyboxID, cubemapTexture);
  glGetError();
}



unsigned int Skybox::loadCubemap()
{
    unsigned int textureID;
    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);

    int width, height, nrChannels;
    for (unsigned int i = 0; i < faces.size(); i++)
    {
        unsigned char *data = stbi_load(faces[i].c_str(), &width, &height, &nrChannels, 0);
        if (data)
        {
            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
            stbi_image_free(data);
        }
        else
        {
            std::cout << "Cubemap texture failed to load at path: " << faces[i] << std::endl;
            stbi_image_free(data);
        }
    }
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

    return textureID;
}

skyboxShader.frag:

#version 410 core
out vec4 FragColor;

in vec3 TexCoords;

uniform samplerCube skybox;

void main()
{    
    FragColor = texture(skybox, TexCoords);
}

skyboxShader.vert:

#version 410 core
layout (location = 0) in vec3 aPos;

out vec3 TexCoords;

uniform mat4 projection;
uniform mat4 view;

void main()
{
    TexCoords = aPos;
    vec4 pos = projection * view * vec4(aPos, 1.0);
    gl_Position = pos.xyww;
}  

I am using an M2 Macbook and I do not have a shader class like I have seen a lot of people use, I implement my shaders the way my lecturer has done so. I hope I have provided enough and thank you in advance if anyone can help!

\$\endgroup\$
4
  • \$\begingroup\$ If you replace your fragment shader with something like FragColor = vec4(abs(fract(TexCooords)), 1);, what do you see? This can help us diagnose whether there's an issue with sampling the texture of if the cube itself is being drawn wrong somehow. \$\endgroup\$
    – DMGregory
    Nov 25, 2023 at 20:24
  • \$\begingroup\$ @DMGregory When I use that I get the same result. My skybox is almost black with circles I believe on each face, they are quite hard to see but I think they are there. \$\endgroup\$
    – Ben Duguid
    Nov 25, 2023 at 20:33
  • \$\begingroup\$ Can you show us a picture? It would be very strange for that code to show all black. \$\endgroup\$
    – DMGregory
    Nov 25, 2023 at 21:55
  • \$\begingroup\$ @DMGregory ofcourse! I will add it now \$\endgroup\$
    – Ben Duguid
    Nov 25, 2023 at 22:07

1 Answer 1

1
\$\begingroup\$

There were two mistakes I made which led to my skybox not texturing properly:

  1. Init function was never called.... I'm sorry
  2. glUseProgram(skyboxShader) should have been called in drawSkybox i.e. calling in the display loop. Thank you to everyone who replied and to anyone who had a look, feel free to steal my code if it is of any use to anyone
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .