2
votes

I don't have very much experience with OpenGL, GLFW, or GLEW so my troubleshooting ability with these libraries is slim to none. I have managed to render a triangle ([-1, -1, 0], [1, -1, 0], [0, 1, 0]) but when using the vertex attribute coordinates for a cube, along with color attributes it seems to not render. There could be a lot wrong with my code, the shaders, and my matrix operations. I wish I had a clearer understanding of what I'm doing so I could give a more descriptive account of my error. Currently the above code only renders the window. I followed https://learnopengl.com/ initially and got the first tutorials working, the following code is my "testing" file where I've attempted to reimplement some of the elements myself. There are lots of copy pasted portions that may be shared with that tutorial if it helps at all.

Any insight or suggestions would be appreciated very much.

Main Source

#include "global.hpp"

using namespace std;
using namespace glm;

static const GLfloat g_color_buffer_data[] = {
    0.583f,  0.771f,  0.014f,
    0.609f,  0.115f,  0.436f,
    0.327f,  0.483f,  0.844f,
    0.822f,  0.569f,  0.201f,
    0.435f,  0.602f,  0.223f,
    0.310f,  0.747f,  0.185f,
    0.597f,  0.770f,  0.761f,
    0.559f,  0.436f,  0.730f,
    0.359f,  0.583f,  0.152f,
    0.483f,  0.596f,  0.789f,
    0.559f,  0.861f,  0.639f,
    0.195f,  0.548f,  0.859f,
    0.014f,  0.184f,  0.576f,
    0.771f,  0.328f,  0.970f,
    0.406f,  0.615f,  0.116f,
    0.676f,  0.977f,  0.133f,
    0.971f,  0.572f,  0.833f,
    0.140f,  0.616f,  0.489f,
    0.997f,  0.513f,  0.064f,
    0.945f,  0.719f,  0.592f,
    0.543f,  0.021f,  0.978f,
    0.279f,  0.317f,  0.505f,
    0.167f,  0.620f,  0.077f,
    0.347f,  0.857f,  0.137f,
    0.055f,  0.953f,  0.042f,
    0.714f,  0.505f,  0.345f,
    0.783f,  0.290f,  0.734f,
    0.722f,  0.645f,  0.174f,
    0.302f,  0.455f,  0.848f,
    0.225f,  0.587f,  0.040f,
    0.517f,  0.713f,  0.338f,
    0.053f,  0.959f,  0.120f,
    0.393f,  0.621f,  0.362f,
    0.673f,  0.211f,  0.457f,
    0.820f,  0.883f,  0.371f,
    0.982f,  0.099f,  0.879f
};
static const GLfloat g_vertex_buffer_data[] = {
    -1.0f,-1.0f,-1.0f, // triangle 1 : begin
    -1.0f,-1.0f, 1.0f,
    -1.0f, 1.0f, 1.0f, // triangle 1 : end
    1.0f, 1.0f,-1.0f, // triangle 2 : begin
    -1.0f,-1.0f,-1.0f,
    -1.0f, 1.0f,-1.0f, // triangle 2 : end
    1.0f,-1.0f, 1.0f,
    -1.0f,-1.0f,-1.0f,
    1.0f,-1.0f,-1.0f,
    1.0f, 1.0f,-1.0f,
    1.0f,-1.0f,-1.0f,
    -1.0f,-1.0f,-1.0f,
    -1.0f,-1.0f,-1.0f,
    -1.0f, 1.0f, 1.0f,
    -1.0f, 1.0f,-1.0f,
    1.0f,-1.0f, 1.0f,
    -1.0f,-1.0f, 1.0f,
    -1.0f,-1.0f,-1.0f,
    -1.0f, 1.0f, 1.0f,
    -1.0f,-1.0f, 1.0f,
    1.0f,-1.0f, 1.0f,
    1.0f, 1.0f, 1.0f,
    1.0f,-1.0f,-1.0f,
    1.0f, 1.0f,-1.0f,
    1.0f,-1.0f,-1.0f,
    1.0f, 1.0f, 1.0f,
    1.0f,-1.0f, 1.0f,
    1.0f, 1.0f, 1.0f,
    1.0f, 1.0f,-1.0f,
    -1.0f, 1.0f,-1.0f,
    1.0f, 1.0f, 1.0f,
    -1.0f, 1.0f,-1.0f,
    -1.0f, 1.0f, 1.0f,
    1.0f, 1.0f, 1.0f,
    -1.0f, 1.0f, 1.0f,
    1.0f,-1.0f, 1.0f
};

extern const char* VertexShader = R"(
#version 330 core

layout(location = 0) in vec3 vertexPosition_modelspace;

layout(location = 1) in vec3 vertexColor;

uniform mat4 MVP;
  
out vec3 fragmentColor;
 
//out vec2 UV;
  
void main(){
  gl_Position =  MVP * vec4(vertexPosition_modelspace,1);
  
  //UV = vertexUV;
  
  fragmentColor = vertexColor;
}
)";

extern const char* FragmentShader = R"(
#version 330 core
in vec3 fragmentColor;
out vec3 color;
void main(){
  //color = vec3(1,0,0);
  color = fragmentColor;
}
)";

static const float tri_vertex_array[] = {
    -.8, .8, 0,
    -.8, -.8, 0,
    .8, -.8, 0
};

int main()
{
    if (!glfwInitFull()) {
        printf("Unable To Init\n");
        return 1;
    }

    uint width = 1200, height = 720;
    GLFWwindow* window = glfwCreateWindow(width, height, "ME", 0, 0);

    if (!window)
        return -1;

    glfwMakeContextCurrent(window);
    if (glewInit() != GLEW_OK)
        return 0;

    //
    GLuint VertexArrayId;
    glGenVertexArrays(1, &VertexArrayId);
    glBindVertexArray(VertexArrayId);
    //

    GLuint vertexBuffer;
    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);

    //glBufferData(GL_ARRAY_BUFFER, sizeof(tri_vertex_array), tri_vertex_array, GL_STATIC_DRAW);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);


    GLuint colorBuffer;
    glGenBuffers(1, &colorBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);


    GLuint vertexShaderId = compileShader(VertexShader, GL_VERTEX_SHADER);
    GLuint fragmentShaderId = compileShader(FragmentShader, GL_FRAGMENT_SHADER);

    GLuint programId = glCreateProgram();

    linkShader(programId, vertexShaderId);
    linkShader(programId, fragmentShaderId);

    // maybe nessacary?
    //glMatrixMode(GL_PROJECTION);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LESS);
    glEnable(GL_CULL_FACE);
    glViewport(0, 0, width, height);

    //vec3 cameraPos = vec3(0.f, 0.f, 3.f);
    //vec3 cameraTarget = vec3(0.f, 0.f, 0.f);
    //vec3 cameraDirection = normalize(cameraPos - cameraTarget);
    //
    //vec3 up = vec3(0.f, 1.f, 0.f);
    //vec3 right = normalize(
    //    cross(
    //        up,
    //        cameraDirection
    //    )
    //);
    //
    //vec3 cameraUp = cross(cameraDirection, right);
    //
    //mat4 view = lookAt(
    //    vec3(4.f, 3.f, 3.f),
    //    vec3(0.f, 0.f, 0.f),
    //    vec3(0.f, 1.f, 0.f)
    //);

    mat4 projection = perspective(radians(45.f), width / (float)height, .1f, 100.f);
    mat4 view = lookAt(
        vec3(4, 3, -3),
        vec3(0, 0, 0),
        vec3(0, 1, 0)
    );

    mat4 model = mat4(1.0f); // identity
    mat4 mvp = projection * view * model;

    GLuint mvpId = glGetUniformLocation(programId, "MVP");

    do {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glClearColor(0.f, 0.f, .4f, 0.f);

        glUseProgram(programId);

        //gluLookAt(
        //    4, 3, 3,
        //    0, 0, 0,
        //    0, 1, 0
        //);

        glUniformMatrix4fv(mvpId, 1, 0, &mvp[0][0]);

        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
        glVertexAttribPointer(
            0,
            3,
            GL_FLOAT,
            GL_FALSE,
            0,
            NULL
        );

        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
        glVertexAttribPointer(
            1,          
            3,          
            GL_FLOAT,   
            GL_FALSE,   
            0,          
            (void*)0    
        );

        glDrawArrays(GL_TRIANGLES, 0, 3*12);

        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);

        glfwSwapBuffers(window);
        glfwPollEvents();
    } while (
        !glfwWindowShouldClose(window)
        &&
        !glfwGetKey(window, GLFW_KEY_ESCAPE)
    );

    glfwTerminate();
}

global.hpp

#ifndef _glfw3_h_
// opengl extensions
#include <GL/glew.h>

// opengl utility / wrapper
#include <GLFW/glfw3.h>

// operations in space
#include <glm/glm.hpp>

#include <glm/gtc/matrix_transform.hpp>

#endif // !_glfw3_h_


#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <vector>
#include <fstream>

#include <random>
#include <ctime>
#include <cmath>

static void glfwErrorCb(int errorCode, const char* error) {
    printf("GLFW Error Thrown\n -> %d\n%s\n", errorCode, error);
}

static bool glfwInitFull() {
    srand(time(0));

    if (!glfwInit())
        return 0;

    glfwSetErrorCallback(glfwErrorCb);
    glewExperimental = true;

    glfwWindowHint(GLFW_SAMPLES, 4); // anti-aliasing
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // version
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // version
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // no-old-gl

    return 1;
}

static GLuint compileShader(const char* content, GLenum type) {
    GLuint shaderId = glCreateShader(type);
    GLint returnValBuf;

    glShaderSource(shaderId, 1, &content, NULL);
    glCompileShader(shaderId);

    glGetShaderiv(shaderId, GL_COMPILE_STATUS, &returnValBuf);

    if (returnValBuf == GL_FALSE) {
        printf("Unable To Compile Shader\n```\n%s\n```\n\nInfo Log:\n", content);
        
        GLint logLen;
        glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &logLen);

        if (logLen <= 0)
            return 0;

        char* infoBuffer = new char[logLen + 1];
        infoBuffer[logLen] = '\0';
            
        glGetShaderInfoLog(shaderId, logLen, &returnValBuf, infoBuffer);
        printf("%s\n", infoBuffer);

        delete[] infoBuffer;
        return 0;
    }
    
    return shaderId;
}

static GLuint linkShader(GLuint programId, GLuint shaderId) {
    glAttachShader(programId, shaderId);
    glLinkProgram(programId);

    GLint returnValBuf;
    glGetProgramiv(programId, GL_LINK_STATUS, &returnValBuf);
    
    if (returnValBuf == GLFW_FALSE) {
        printf("Unable To Link Shader\nInfo Log:\n");

        GLint logLen;
        glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &logLen);

        if (logLen <= 0)
            return 0;

        char* infoBuffer = new char[logLen + 1];
        infoBuffer[logLen] = '\0';

        glGetProgramInfoLog(programId, logLen, &returnValBuf, infoBuffer);
        printf("%s\n", infoBuffer);

        delete[] infoBuffer;
    }

    glDetachShader(programId, shaderId);
    glDeleteShader(shaderId);

    return programId;
}

typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned long long ullong;

#pragma once
1
If I was to guess there is an issue with my perspective and how I am viewing my render in the vertex shader.Nathan Morris
This doesn't cause the issue but glEnable(GL_LESS) should be glDepthFunc (GL_LESS).Rabbid76
The issue is caused because linkShader is called twice.Rabbid76

1 Answers

1
votes

The problem is that you call linkShader separately for each shader. It is possible to link a program multiple times. The function linkShader, however, attaches the shader to the program, linkes the program and detaches the shader from the program. Hence, the vertex and the fragment shader are never attached at the same time.

Attach the vertex and fragment shader and call linkShader once:

static GLuint linkShader(GLuint programId) {
    glLinkProgram(programId);

    GLint returnValBuf;
    glGetProgramiv(programId, GL_LINK_STATUS, &returnValBuf);

    if (returnValBuf == GLFW_FALSE) {
        printf("Unable To Link Shader\nInfo Log:\n");

        GLint logLen;
        glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &logLen);

        if (logLen <= 0)
            return 0;

        char* infoBuffer = new char[logLen + 1];
        infoBuffer[logLen] = '\0';

        glGetProgramInfoLog(programId, logLen, &returnValBuf, infoBuffer);
        printf("%s\n", infoBuffer);

        delete[] infoBuffer;
    }

    return programId;
}
int main()
{
    // [...]

    GLuint vertexShaderId = compileShader(VertexShader, GL_VERTEX_SHADER);
    GLuint fragmentShaderId = compileShader(FragmentShader, GL_FRAGMENT_SHADER);

    GLuint programId = glCreateProgram();
    glAttachShader(programId, vertexShaderId);
    glAttachShader(programId, fragmentShaderId);

    linkShader(programId);
    
    glDetachShader(programId, vertexShaderId);
    glDeleteShader(vertexShaderId);
    glDetachShader(programId, fragmentShaderId);
    glDeleteShader(fragmentShaderId);

    // [...]
}