-1

I am trying to load gltf 2.0 models in openGl. For 1st model it is works fine. But for 2nd model, Model is loading well but have same texture as previous one. I don't know how to apply different textures on different models and changing position of one model changes position of all models same way. I searched much online but very few examples of loading gltf in openGL. They also not show how to load 2nd or 3rd gltf model in same project (screen).

My code is using libraries to load gltf and to compile shaders. That are few line of code libraries have simple openGl code for loading gltf and compiling shaders.

Main.cpp

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;

#define GL_SILENCE_DEPRECATION
#include <glad/glad.h> // Extend OpenGL Specfication to version 4.5 for WIN64 and versions 4.1 for Apple (note: two different files).

#include <imgui/imgui.h>              // Load GUI library - Dear ImGui - https://github.com/ocornut/imgui
#include <imgui/imgui_impl_glfw.h>    // Platform ImGui using GLFW
#include <imgui/imgui_impl_opengl3.h> // Platform new OpenGL - aka better than 3.3 core version.

#include <GLFW/glfw3.h> // Add GLFW - library to launch a window and callback mouse and keyboard - https://www.glfw.org

//#include <tinygltf/tiny_gltf.h> // Model loading library - tiny gltf - https://github.com/syoyo/tinygltf
//#include "src/stb_image.hpp" // Add library to load images for textures

#define GLM_ENABLE_EXPERIMENTAL  // Enable all functions include non LTS
#include <glm/glm.hpp>           // Add helper maths library - GLM 0.9.9.9 - https://github.com/g-truc/glm - for example variables vec3, mat and operators.
#include <glm/gtx/transform.hpp> // Help us with transforms
using namespace glm;
 


//#include "src/Mesh.hpp" // Simplest mesh holder and OBJ loader - can update more - from https://github.com/BennyQBD/ModernOpenGLTutorial

#include "src/Pipeline.hpp"     // Setup pipeline and load shaders.
#include "src/Content.hpp"      // Setup content loader and drawing functions - https://github.com/KhronosGroup/glTF - https://github.com/syoyo/tinygltf 
#include "src/Debugger.hpp"     // Setup debugger functions.



// Main fuctions
void startup();
void update();
void render();
void ui();
void endProgram();

// HELPER FUNCTIONS OPENGL
void hintsGLFW();
//string readShader(string name);
//void checkErrorShader(GLuint shader);
inline void errorCallbackGLFW(int error, const char *description){cout << "Error GLFW: " << description << "\n";};
void debugGL();

void APIENTRY openGLDebugCallback(GLenum source,
                                  GLenum type,
                                  GLuint id,
                                  GLenum severity,
                                  GLsizei length,
                                  const GLchar *message,
                                  const GLvoid *userParam);
GLenum glCheckError_(const char *file, int line);
#define glCheckError() glCheckError_(__FILE__, __LINE__)

// Setup all the message loop callbacks - do this before Dear ImGui
// Callback functions for the window and interface devices
void onResizeCallback(GLFWwindow *window, int w, int h);
void onKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods);
void onMouseButtonCallback(GLFWwindow *window, int button, int action, int mods);
void onMouseMoveCallback(GLFWwindow *window, double x, double y);
void onMouseWheelCallback(GLFWwindow *window, double xoffset, double yoffset);

// VARIABLES
GLFWwindow *window;                                 // Keep track of the window
auto windowWidth = 800;                             // Window width                 
auto windowHeight =800;                             // Window height
auto running(true);                                 // Are we still running our main loop
mat4 projMatrix;                                    // Our Projection Matrix
vec3 cameraPosition = vec3(0.0f, 0.0f, 5.0f);       // Where is our camera
vec3 cameraFront = vec3(0.0f, 0.0f, -0.5f);         // Camera front vector
vec3 cameraUp = vec3(0.0f, 1.0f, 0.0f);             // Camera up vector

auto aspect = (float)windowWidth / (float)windowHeight; // Window aspect ration
auto fovy = 45.0f;                                  // Field of view (y axis)
bool keyStatus[1024];                               // Track key strokes
auto currentTime = 0.0f;                            // Framerate
auto deltaTime = 0.0f;                              // time passed
auto lastTime = 0.0f;                               // Used to calculate Frame rate

Pipeline pipeline;                                  // Add one pipeline plus some shaders.
Pipeline pipelinelegs;                                  // Add one pipeline plus some shaders.
Content content;                                    // Add one content loader (+drawing).
Content contentlegs;
GLuint texture, texture2;
//Pipeline pipelineClegs;                                   // Add one pipeline plus some shaders.
//Content contentClegs;                                 
Debugger debugger;                                  // Add one debugger to use for callbacks ( Win64 - openGLDebugCallback() ) or manual calls ( Apple - glCheckError() ) 

vec3 modelPosition;                                 // Model position
vec3 modelRotation;                                 // Model rotation


int main()
{
    cout << endl << "===" << endl << "3D Graphics and Animation - Running..." << endl;

    if (!glfwInit()) // Check if GLFW is working, if not then stop all
    {
        cout << "Could not initialise GLFW...";
        return -1;
    } 

    glfwSetErrorCallback(errorCallbackGLFW); // Setup a function callback to catch and display all GLFW errors.
    hintsGLFW();                             // Setup glfw with various hints.

    const GLFWvidmode *mode = glfwGetVideoMode(glfwGetPrimaryMonitor()); // Grab reference to monitor
    // windowWidth = mode->width; windowHeight = mode->height; //fullscreen
    // window = glfwCreateWindow(windowWidth, windowHeight, title.c_str(), glfwGetPrimaryMonitor(), NULL); // fullscreen

    // Create our Window
    const auto windowTitle = "My 3D Graphics and Animation OpenGL Application"s;
    window = glfwCreateWindow(windowWidth, windowHeight, windowTitle.c_str(), NULL, NULL);
    if (!window) // Test if Window or OpenGL context creation failed
    {
        cout << "Could not initialise GLFW...";
        glfwTerminate();
        return -1;
    } 

    glfwSetWindowPos(window, 10, 10); // Place it in top corner for easy debugging.
    glfwMakeContextCurrent(window);   // making the OpenGL context current

    // GLAD: Load OpenGL function pointers - aka update specs to newest versions - plus test for errors.
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD...";
        glfwMakeContextCurrent(NULL);
        glfwTerminate();
        return -1;
    }

    glfwSetWindowSizeCallback(window, onResizeCallback);       // Set callback for resize
    glfwSetKeyCallback(window, onKeyCallback);                 // Set Callback for keys
    glfwSetMouseButtonCallback(window, onMouseButtonCallback); // Set callback for mouse click
    glfwSetCursorPosCallback(window, onMouseMoveCallback);     // Set callback for mouse move
    glfwSetScrollCallback(window, onMouseWheelCallback);       // Set callback for mouse wheel.
    // glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);   // Set mouse cursor Fullscreen
    // glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); // Set mouse cursor FPS fullscreen.

    // Setup Dear ImGui and add context -   https://blog.conan.io/2019/06/26/An-introduction-to-the-Dear-ImGui-library.html
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO &io = ImGui::GetIO(); //(void)io;
                                  // io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
    // io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
    ImGui::StyleColorsLight(); // ImGui::StyleColorsDark();         // Setup Dear ImGui style

    // Setup Platform/Renderer ImGui backends
    ImGui_ImplGlfw_InitForOpenGL(window, true);
    const auto glsl_version = "#version 410";
    ImGui_ImplOpenGL3_Init(glsl_version);

    #if defined(__WIN64__)
        debugGL(); // Setup callback to catch openGL errors.    V4.2 or newer
    #elif(__APPLE__)
        glCheckError(); // Old way of checking for errors. Newest not implemented by Apple. Manually call function anywhere in code to check for errors.
    #endif

    glfwSwapInterval(1);             // Ony render when synced (V SYNC) - https://www.tomsguide.com/features/what-is-vsync-and-should-you-turn-it-on-or-off
    glfwWindowHint(GLFW_SAMPLES, 2); // Multisampling - covered in lectures - https://www.khronos.org/opengl/wiki/Multisampling

    startup(); // Setup all necessary information for startup (aka. load texture, shaders, models, etc).
    
    cout << endl << "Starting main loop and rendering..." << endl;  

    do{                                          // run until the window is closed
        auto currentTime = (float)glfwGetTime(); // retrieve timelapse
        deltaTime = currentTime - lastTime;      // Calculate delta time
        lastTime = currentTime;                  // Save for next frame calculations.

        glfwPollEvents();                       // poll callbacks

        update();                               // update (physics, animation, structures, etc)
        render();                               // call render function.
        ui();                                   // call function to render ui. 
        #if defined(__APPLE__)
            glCheckError();             // Manually checking for errors for MacOS, Windows has a callback.
        #endif

        glfwSwapBuffers(window);        // swap buffers (avoid flickering and tearing)

        running &= (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_RELEASE); // exit if escape key pressed
        running &= (glfwWindowShouldClose(window) != GL_TRUE);
    } while (running);

    endProgram(); // Close and clean everything up...
    
    // cout << "\nPress any key to continue...\n";
    // cin.ignore(); cin.get(); // delay closing console to read debugging errors.

    return 0;
}


void hintsGLFW(){
    
    auto majorVersion = 3; auto minorVersion = 3; // define OpenGL version - at least 3.3 for bare basic NEW OpenGL

    #if defined(__WIN64__)  
        majorVersion = 4; minorVersion = 5;                 // Recommended for Windows 4.5, but latest is 4.6 (not all drivers support 4.6 version).
        glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); // Create context in debug mode - for debug message callback
    #elif(__APPLE__)
        majorVersion = 4; minorVersion = 1;                 // Max support for OpenGL in MacOS
    #endif

    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);    // https://www.glfw.org/docs/3.3/window_guide.html
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, majorVersion); 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, minorVersion);
}

void endProgram()
{
    // Clean ImGui
    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImGui::DestroyContext();

    glfwMakeContextCurrent(NULL);   // destroys window handler
    glfwTerminate();                // destroys all windows and releases resources.
}

void startup()
{
    
    // string name = "assets/Fabric01_4K_BaseColor.png";
    // int iWidth, iHeight, iChannels; 
    // unsigned char *iData = stbi_load(name.c_str(),  &iWidth, &iHeight, &iChannels, 0);
    // glGenTextures(1, &texture);
    // //glActiveTexture(GL_TEXTURE0);
    // glBindTexture(GL_TEXTURE_2D, texture);

    // // glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, iWidth, iHeight);
    // // glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, iWidth, iHeight, GL_RGB, GL_UNSIGNED_BYTE, iData);

    // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    // if (iData)
    // {
    //  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    //  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
    //  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
    //  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
    //  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iWidth, iHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, iData);
    // }else
    // {
    //     std::cout << "Failed to load texture" << std::endl;
    // }
    // glGenerateMipmap(GL_TEXTURE_2D);
    // stbi_image_free(iData);
    // //glBindTexture(GL_TEXTURE_2D, 0);

    // string namea = "assets/metal.png";
    // int Width, Height, Channels; 
    // unsigned char *Data = stbi_load(namea.c_str(),  &Width, &Height, &Channels, 0);
    // glGenTextures(1, &texture2);
    // glBindTexture(GL_TEXTURE_2D, texture2);

    // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    // if (Data)
    // {
    //  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    //  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
    //  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
    //  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
    //  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Data);
    // }else
    // {
    //     std::cout << "Failed to load texture" << std::endl;
    // }
    // glGenerateMipmap(GL_TEXTURE_2D);
    // stbi_image_free(Data);
    //glBindTexture(GL_TEXTURE_2D, 0);
    

    cout << "VENDOR: " << (char *)glGetString(GL_VENDOR) << endl;
    cout << "VERSION: " << (char *)glGetString(GL_VERSION) << endl;
    cout << "RENDERER: " << (char *)glGetString(GL_RENDERER) << endl;   

    cout << endl << "Loading content..." << endl;
    
    content.LoadGLTF("assets/Model.gltf");
    content2.LoadGLTF("assets/Model2.gltf");
    
    pipeline.CreatePipeline();
    pipeline.LoadShaders("shaders/vs_model.glsl", "shaders/fs_model.glsl");

    
    
    modelPosition = glm::vec3(0.0f, 0.0f, 0.0f);
    modelRotation = glm::vec3(0.0f, 0.0f, 0.0f);

    // A few optimizations.
    glFrontFace(GL_CCW);
    glCullFace(GL_BACK);
    glEnable(GL_CULL_FACE);

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    // Get the correct size in pixels - E.g. if retina display or monitor scaling
    glfwGetFramebufferSize(window, &windowWidth, &windowHeight);

    // Calculate proj_matrix for the first time.
    aspect = (float)windowWidth / (float)windowHeight;
    projMatrix = glm::perspective(glm::radians(fovy), aspect, 0.1f, 1000.0f);
}

void update()
{
    
    // modelRotation.y += 0.05f;
    
    if (keyStatus[GLFW_KEY_LEFT]) modelRotation.y += 0.05f;
    if (keyStatus[GLFW_KEY_RIGHT]) modelRotation.y -= 0.05f;
    if (keyStatus[GLFW_KEY_UP]) modelRotation.x += 0.05f;
    if (keyStatus[GLFW_KEY_DOWN]) modelRotation.x -= 0.05f;
    if (keyStatus[GLFW_KEY_C] && keyStatus[GLFW_KEY_UP]) cameraPosition.y += 0.10f;
    if (keyStatus[GLFW_KEY_C] && keyStatus[GLFW_KEY_DOWN]) cameraPosition.y -= 0.10f;
    if (keyStatus[GLFW_KEY_C] && keyStatus[GLFW_KEY_RIGHT]) cameraPosition.x += 0.10f;
    if (keyStatus[GLFW_KEY_C] && keyStatus[GLFW_KEY_LEFT]) cameraPosition.x -= 0.10f;
    if (keyStatus[GLFW_KEY_C] && keyStatus[GLFW_KEY_I]) cameraPosition.z += 0.10f;
    if (keyStatus[GLFW_KEY_C] && keyStatus[GLFW_KEY_O]) cameraPosition.z -= 0.10f;
    if (keyStatus[GLFW_KEY_U] && keyStatus[GLFW_KEY_UP]) cameraUp.y += 0.10f;
    if (keyStatus[GLFW_KEY_U] && keyStatus[GLFW_KEY_DOWN]) cameraUp.y -= 0.10f;
    if (keyStatus[GLFW_KEY_U] && keyStatus[GLFW_KEY_RIGHT]) cameraUp.x += 0.10f;
    if (keyStatus[GLFW_KEY_U] && keyStatus[GLFW_KEY_LEFT]) cameraUp.x -= 0.10f;
    if (keyStatus[GLFW_KEY_U] && keyStatus[GLFW_KEY_I]) cameraUp.z += 0.10f;
    if (keyStatus[GLFW_KEY_U] && keyStatus[GLFW_KEY_O]) cameraUp.z -= 0.10f;
    if (keyStatus[GLFW_KEY_F] && keyStatus[GLFW_KEY_UP]) cameraFront.y += 0.10f;
    if (keyStatus[GLFW_KEY_F] && keyStatus[GLFW_KEY_DOWN]) cameraFront.y -= 0.10f;
    if (keyStatus[GLFW_KEY_F] && keyStatus[GLFW_KEY_RIGHT]) cameraFront.x += 0.10f;
    if (keyStatus[GLFW_KEY_F] && keyStatus[GLFW_KEY_LEFT]) cameraFront.x -= 0.10f;
    if (keyStatus[GLFW_KEY_F] && keyStatus[GLFW_KEY_I]) cameraFront.z += 0.10f;
    if (keyStatus[GLFW_KEY_F] && keyStatus[GLFW_KEY_O]) cameraFront.z -= 0.10f;

    if (keyStatus[GLFW_KEY_R]) pipeline.ReloadShaders();

    // Start the Dear ImGui frame
    ImGui_ImplOpenGL3_NewFrame();
    ImGui_ImplGlfw_NewFrame();
    ImGui::NewFrame();
}

void render()
{
    glViewport(0, 0, windowWidth, windowHeight);

    // Clear colour buffer
    glm::vec4 inchyraBlue = glm::vec4(0.345f, 0.404f, 0.408f, 1.0f);
    glm::vec4 backgroundColor = inchyraBlue;
    glClearBufferfv(GL_COLOR, 0, &backgroundColor[0]);

    // Clear deep buffer
    static const GLfloat one = 1.0f;
    glClearBufferfv(GL_DEPTH, 0, &one);

    // Enable blend
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
    // Use our shader programs
    glUseProgram(pipeline.pipe.program);
    //glUniform1i(glGetUniformLocation(pipeline.pipe.program, "texture1"), 0);
    
    

    // Setup camera
    glm::mat4 viewMatrix = glm::lookAt(cameraPosition,               // eye
                                       cameraPosition + cameraFront, // centre
                                       cameraUp);                    // up

    
    // Do some translations, rotations and scaling
    // glm::mat4 modelMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(modelPosition.x+rX, modelPosition.y+rY, modelPosition.z+rZ));
    glm::mat4 modelMatrix = glm::translate(glm::mat4(5.0f), glm::vec3(0.0f, 0.4f, 0.0f));
    modelMatrix = glm::rotate(modelMatrix, modelRotation.x, glm::vec3(1.0f, 0.0f, 0.0f));
    modelMatrix = glm::rotate(modelMatrix, modelRotation.y, glm::vec3(0.0f, 1.0f, 0.0f));
    modelMatrix = glm::scale(modelMatrix, glm::vec3(0.5f, 0.5f, 0.5f));

    glm::mat4 modelMatrix2 = glm::translate(glm::mat4(5.0f), glm::vec3(0.0f, -0.0f, 0.0f));
    modelMatrix2 = glm::rotate(modelMatrix2, modelRotation.x, glm::vec3(1.0f, 0.0f, 0.0f));
    modelMatrix2 = glm::rotate(modelMatrix2, modelRotation.y, glm::vec3(0.0f, 1.0f, 0.0f));
    modelMatrix2 = glm::scale(modelMatrix2, glm::vec3(0.5f, 0.5f, 0.5f));

    glm::mat4 mv_matrix = viewMatrix * modelMatrix;
    //glm::mat4 mv_matrixlegs = viewMatrix * modelMatrixlegs;
    
    glUniformMatrix4fv(glGetUniformLocation(pipeline.pipe.program, "model_matrix"), 1, GL_FALSE, &modelMatrix[0][0]);
    glUniformMatrix4fv(glGetUniformLocation(pipeline.pipe.program, "modelMatrix2"), 1, GL_FALSE, &modelMatrix2[0][0]);
    glUniformMatrix4fv(glGetUniformLocation(pipeline.pipe.program, "view_matrix"), 1, GL_FALSE, &viewMatrix[0][0]);
    glUniformMatrix4fv(glGetUniformLocation(pipeline.pipe.program, "proj_matrix"), 1, GL_FALSE, &projMatrix[0][0]);
    
    // glUniformMatrix4fv(glGetUniformLocation(pipeline.pipe.program, "modelMatrixlegs"), 1, GL_FALSE, &modelMatrixlegs[0][0]);
    // glUniformMatrix4fv(glGetUniformLocation(pipeline.pipe.program, "view_matrix"), 1, GL_FALSE, &viewMatrix[0][0]);
    // glUniformMatrix4fv(glGetUniformLocation(pipeline.pipe.program, "proj_matrix"), 1, GL_FALSE, &projMatrix[0][0]);

    content.DrawModel(content.vaoAndEbos, content.model);
    content2.DrawModel(content2.vaoAndEbos, content2.model);
    
    #if defined(__APPLE__)
        glCheckError();
    #endif
}

void ui()
{
    ImGuiIO &io = ImGui::GetIO();
    ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration; 
    window_flags |= ImGuiWindowFlags_AlwaysAutoResize;
    window_flags |= ImGuiWindowFlags_NoSavedSettings; 
    window_flags |= ImGuiWindowFlags_NoFocusOnAppearing; 
    window_flags |= ImGuiWindowFlags_NoNav;

    const auto PAD = 10.0f;
    const ImGuiViewport *viewport = ImGui::GetMainViewport();
    ImVec2 work_pos = viewport->WorkPos; // Use work area to avoid menu-bar/task-bar, if any!
    ImVec2 work_size = viewport->WorkSize;
    ImVec2 window_pos, window_pos_pivot;
    window_pos.x = work_pos.x + work_size.x - PAD;
    window_pos.y = work_pos.y + work_size.y - PAD;
    window_pos_pivot.x = 1.0f;
    window_pos_pivot.y = 1.0f;

    ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
    window_flags |= ImGuiWindowFlags_NoMove;

    ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
    bool *p_open = NULL;
    if (ImGui::Begin("Info", nullptr, window_flags)) {
        ImGui::Text("About: 3D Graphics and Animation 2022"); // ImGui::Separator();
        ImGui::Text("Performance: %.3fms/Frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
        ImGui::Text("Pipeline: %s", pipeline.pipe.error?"ERROR":"OK");
    }
    ImGui::End();

    // Rendering imgui
    ImGui::Render();
    ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}

void onResizeCallback(GLFWwindow *window, int w, int h)
{
    windowWidth = w;
    windowHeight = h;

    // Get the correct size in pixels
    glfwGetFramebufferSize(window, &windowWidth, &windowHeight);

    if (windowWidth > 0 && windowHeight > 0)
    { // Avoid issues when minimising window - it gives size of 0 which fails division.
        aspect = (float)w / (float)h;
        projMatrix = glm::perspective(glm::radians(fovy), aspect, 0.1f, 1000.0f);
    }
}

void onKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
{
    if (action == GLFW_PRESS)
        keyStatus[key] = true;
    else if (action == GLFW_RELEASE)
        keyStatus[key] = false;

    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GLFW_TRUE);
}

void onMouseButtonCallback(GLFWwindow *window, int button, int action, int mods)
{
}

void onMouseMoveCallback(GLFWwindow *window, double x, double y)
{
    int mouseX = static_cast<int>(x);
    int mouseY = static_cast<int>(y);
}

void onMouseWheelCallback(GLFWwindow *window, double xoffset, double yoffset)
{
    int yoffsetInt = static_cast<int>(yoffset);
}

void APIENTRY openGLDebugCallback(GLenum source,
                                  GLenum type,
                                  GLuint id,
                                  GLenum severity,
                                  GLsizei length,
                                  const GLchar *message,
                                  const GLvoid *userParam)  // Debugger callback for Win64 - OpenGL versions 4.2 or better.
{
    debugger.OpenGLDebugCallback(source, type, id, severity, length, message, userParam);
}

void debugGL() // Debugger function for Win64 - OpenGL versions 4.2 or better.
{
    // Enable Opengl Debug
    glEnable(GL_DEBUG_OUTPUT);
    glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
    glDebugMessageCallback((GLDEBUGPROC)openGLDebugCallback, nullptr);
    glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, true);
}

GLenum glCheckError_(const char *file, int line) // Debugger manual function for Apple - OpenGL versions 3.3 to 4.1.
{
    GLenum errorCode;
    while ((errorCode = glGetError()) != GL_NO_ERROR) debugger.GlGetError(errorCode, file, line);

    return errorCode;
}

FragmentShader.glsl

#version 430 core

out vec4 color;


in VS_OUT
{
    vec3 vertex;
    vec3 normals;
    vec2 tc;
} fs_in;

uniform sampler2D tex;

uniform sampler2D model_matrix;
uniform sampler2D modelMatrix2;

void main(void){
  
  color = texture(tex, fs_in.tc);
}

VertexShader.glsl

#version 410 core

layout (location = 0) in vec3 in_vertex;
layout (location = 1) in vec3 in_normals;
layout (location = 2) in vec2 in_tc;


out VS_OUT
{
    vec3 vertex;
    vec3 normals;
    vec2 tc;
} vs_out;

uniform mat4 model_matrix;
uniform mat4 modelMatrixlegs;
uniform mat4 view_matrix;
uniform mat4 proj_matrix;

void main(void)
{
    
    gl_Position = proj_matrix * view_matrix * model_matrix * vec4(in_vertex, 1.0);
    
    vs_out.vertex = in_vertex;
    vs_out.normals = in_normals;
    vs_out.tc = in_tc;
}

genpfault
  • 51,148
  • 11
  • 85
  • 139
  • I didn't look through all your code. Meshes and textures are pretty much separate in OpenGL. Did you bind the first texture before rendering the first mesh and bind the second texture before rendering the second mesh? – user253751 Nov 29 '22 at 22:12
  • of course. I did this. But let me re-phrase my question: how I can handle the values of position in vertex shader and values of color in fragment shader in for second gltf model? Because when I load second gltf mesh it sticks with 1st one. If I change the position, rotation or scaling value of 1st item (in main.cpp) then these changes also effect the second mesh or gltf model. – anonymous user Nov 30 '22 at 00:31
  • Also even I am binding texture each time before rendering each model. But texture shows on all items same. means texture of 1st items. I am loading textures using stb_image library. – anonymous user Nov 30 '22 at 02:38

1 Answers1

0

Models don't have positions or rotations or scaling values.

When you call glDrawArrays (or glDrawElements or glDrawElementsIndirect or whatever), then OpenGL renders the current model with the current texture and the current position and rotation and scaling value. Until that point they are separate. You have to realize this - you can draw the same model with different position/rotation/scaling, or the same model with different textures, or different models with the same texture, or so on. There's no need to link them together until you actually draw them and you shouldn't think they are linked together.

I don't see where DrawModel is defined, but I assume it calls glDrawArrays or glDrawElements. So it uses the texture and position and rotation and scaling value (a.k.a. the matrix) that are current when you call it.

So all you have to do is make model 1's matrix current before drawing model 1, and make model 2's matrix current before drawing model 2. Same for the textures.

i.e. probably something like this

glUniformMatrix4fv(glGetUniformLocation(pipeline.pipe.program, "model_matrix"),
    1, GL_FALSE, &modelMatrix[0][0]);
//                ^^^^^^^^^^^ model 1 matrix
glBindTexture(GL_TEXTURE_2D, texture);
//                           ^^^^^^^ model 1 texture
content.DrawModel(content.vaoAndEbos, content.model);
//^^^^^           ^^^^^^^             ^^^^^^^^^^^^^ model 1

glUniformMatrix4fv(glGetUniformLocation(pipeline.pipe.program, "model_matrix"),
    1, GL_FALSE, &modelMatrix2[0][0]);
//                ^^^^^^^^^^^^ model 2 matrix
glBindTexture(GL_TEXTURE_2D, texture2);
//                           ^^^^^^^^ model 2 texture
content2.DrawModel(content2.vaoAndEbos, content2.model);
//^^^^^^           ^^^^^^^^             ^^^^^^^^^^^^^^ model 2

You can delete the modelMatrixlegs variable from the shader because it's not actually doing anything.

user253751
  • 57,427
  • 7
  • 48
  • 90