Jump to content
  • Advertisement
Sign in to follow this  
Larry Sellers

OpenGL Shaders and keyboard input seem to have stopped working...

This topic is 1506 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So I had a program where I displayed a bunny to the screen, then shaded it with Phong shading, and make it rotate/scale with up/down/left/right.

After I finished that I decided to make it so that it was a class that could display multiple objects that were loaded into it. Somehow I have broken the program and I can't figure out what went wrong.

As of right now it will display the outline of the bunny, but that's it. The controls don't work, the shading doesn't work. Just the bunny outline.

Here is my code:

OpenGLView.h

Code :
#pragma once
 
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include "glm\glm.hpp"
 
#include <string>
#include <vector>
 
class OpenGLView
{
public:
    OpenGLView();
    struct Asset
    {
        GLuint shaderProgramID;
        GLuint vertexArray;
        GLuint vertexBuffer;
        GLuint normalBuffer;
        GLuint elementBuffer;
        GLint elementsSize;
 
        Asset()
        {
            shaderProgramID = -1;
            vertexArray = -1;
            GLuint vertexBuffer = -1;
            GLuint normalBuffer = -1;
            GLuint elementBuffer = -1;
            GLint elementsSize = -1;
        }
    };
 
    struct AssetInstance
    {
        Asset asset;
        glm::vec3 position;
        glm::vec3 scale;
        glm::vec3 materialColor;
        glm::vec3 materialSpecularColor;
        GLfloat materialShininess;
    };
 
    void run();
    bool loadObjSimple(
        std::string path,
        std::vector<glm::vec3>& vertices,
        std::vector<glm::vec3>& normals,
        std::vector<unsigned int>& elements);
    bool initializeAndSetupWindow(GLint windowWidth, GLint windowHeight, std::string windowTitle);
    GLuint loadShaders(const char * vertex_file_path, const char * fragment_file_path);
    void loadBunnyAsset();
    void loadUniforms(AssetInstance asset);
private:
    struct Light
    {
        glm::vec3 position;
        glm::vec3 intensities;
        GLfloat attenuation;
        GLfloat ambientCoefficient;
    } light;
    Asset bunny;
    GLFWwindow * window;
    //glm::mat4 model;
    //glm::mat4 view;
    glm::vec3 cameraPosition;
    void OpenGLView::getKeys(/*GLFWwindow* window, int key, int scancode, int action, int mods*/);
    glm::mat4 translate(glm::vec3 position);
    glm::mat4 scale(glm::vec3 size);
};

OpenGLView.cpp

Code :
//Portions of this code have been taken from:
//http://www.opengl-tutorial.org
//http://www.tomdalling.com/blog/modern-opengl/
//Shen Chen's Assignment 1 & 2 tutorial
 
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define MIN(x,y) ((x) < (y) ? (x) : (y))
 
#include <iostream>
#include "glm\gtc\matrix_transform.hpp"
#include "OpenGLView.h"
#include "controls.h"
 
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
 
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define FILE_PATH "bunny.obj"
 
 
OpenGLView::OpenGLView()
{
    light.position = glm::vec3(0.0f, 7.0f, 3.0f);
    light.intensities = glm::vec3(0.3f, 0.3, 0.3f);
    light.attenuation = 0.3f;
    light.ambientCoefficient = 0.005f;
 
    cameraPosition = glm::vec3(5.0f, 3.0f, 8.0f);
}
 
bool OpenGLView::loadObjSimple(
    std::string path,
    std::vector<glm::vec3>& vertices,
    std::vector<glm::vec3>& normals,
    std::vector<unsigned int>& elements) {
        std::ifstream in(path, std::ios::in);
        if (!in) { std::cerr << "Cannot open " << path << std::endl; return false; }
        std::vector<int> nb_seen;
 
        std::cout << "Loading .obj file..." << std::endl;
        std::string line;
        while (std::getline(in, line)) {
            if (line.substr(0, 2) == "v ") {
                std::istringstream s(line.substr(2));
                glm::vec3 v; s >> v.x; s >> v.y; s >> v.z;
                vertices.push_back(v);
            }
            else if (line.substr(0, 2) == "f ") {
                std::istringstream s(line.substr(2));
                GLuint a, b, c;
                s >> a; s >> b; s >> c;
                a--; b--; c--;
                elements.push_back(a); elements.push_back(b); elements.push_back(c);
            }
            else if (line[0] == '#') {}
            else {}
        }
 
        normals.resize(vertices.size(), glm::vec3(0.0, 0.0, 0.0));
        nb_seen.resize(vertices.size(), 0);
 
        for (unsigned int i = 0; i < elements.size(); i += 3) {
            GLuint ia = elements;
            GLuint ib = elements[i + 1];
            GLuint ic = elements[i + 2];
 
 
            //compute vertex normal
            if (glm::cross(
                glm::vec3(vertices[ib]) - glm::vec3(vertices[ia]),
                glm::vec3(vertices[ic]) - glm::vec3(vertices[ia])) != glm::vec3(0.0, 0.0, 0.0)) {
                    glm::vec3 normal = glm::normalize(glm::cross(
                        glm::vec3(vertices[ib]) - glm::vec3(vertices[ia]),
                        glm::vec3(vertices[ic]) - glm::vec3(vertices[ia])));
                    int v[3]; v[0] = ia; v[1] = ib; v[2] = ic;
                    for (int j = 0; j < 3; j++) {
                        GLuint cur_v = v[j];
                        nb_seen[cur_v]++;
                        if (nb_seen[cur_v] == 1) {
                            normals[cur_v] = normal;
                        }
                        else {
                            normals[cur_v].x = normals[cur_v].x * (1.0 - 1.0 / nb_seen[cur_v]) + normal.x * 1.0 / nb_seen[cur_v];
                            normals[cur_v].y = normals[cur_v].y * (1.0 - 1.0 / nb_seen[cur_v]) + normal.y * 1.0 / nb_seen[cur_v];
                            normals[cur_v].z = normals[cur_v].z * (1.0 - 1.0 / nb_seen[cur_v]) + normal.z * 1.0 / nb_seen[cur_v];
                            normals[cur_v] = glm::normalize(normals[cur_v]);
                        }
                    }
            }
        }
        std::cout << FILE_PATH << " loaded." << std::endl;
        return true;
}
 
GLuint OpenGLView::loadShaders(const char * vertex_file_path, const char * fragment_file_path){
 
    // Create the shaders
    GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
 
    // Read the Vertex Shader code from the file
    std::string VertexShaderCode;
    std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
    if (VertexShaderStream.is_open())
    {
        std::string Line = "";
        while (getline(VertexShaderStream, Line))
            VertexShaderCode += "\n" + Line;
        VertexShaderStream.close();
    }
 
    // Read the Fragment Shader code from the file
    std::string FragmentShaderCode;
    std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
    if (FragmentShaderStream.is_open()){
        std::string Line = "";
        while (getline(FragmentShaderStream, Line))
            FragmentShaderCode += "\n" + Line;
        FragmentShaderStream.close();
    }
 
    GLint Result = GL_FALSE;
    int InfoLogLength;
 
    // Compile Vertex Shader
    printf("Compiling shader : %s\n", vertex_file_path);
    char const * VertexSourcePointer = VertexShaderCode.c_str();
    glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL);
    glCompileShader(VertexShaderID);
 
    // Check Vertex Shader
    glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> VertexShaderErrorMessage(InfoLogLength);
    glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
    fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
 
    // Compile Fragment Shader
    printf("Compiling shader : %s\n", fragment_file_path);
    char const * FragmentSourcePointer = FragmentShaderCode.c_str();
    glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL);
    glCompileShader(FragmentShaderID);
 
    // Check Fragment Shader
    glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
    glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
    fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);
 
    // Link the program
    fprintf(stdout, "Linking program\n");
    GLuint ProgramID = glCreateProgram();
    glAttachShader(ProgramID, VertexShaderID);
    glAttachShader(ProgramID, FragmentShaderID);
    glLinkProgram(ProgramID);
 
    // Check the program
    glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> ProgramErrorMessage(MAX(InfoLogLength, int(1)));
    glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
    fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
 
    glDeleteShader(VertexShaderID);
    glDeleteShader(FragmentShaderID);
 
    return ProgramID;
}
 
bool OpenGLView::initializeAndSetupWindow(GLint windowWidth, GLint windowHeight, std::string windowTitle)
{
    if (!glfwInit())
    {
        std::cerr << "Error initializing glfw!" << std::endl;
        return false;
    }
 
    std::cout << "GLFW initialized!" << std::endl;
 
    glfwWindowHint(GLFW_SAMPLES, 8);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
 
    window = glfwCreateWindow(windowWidth, windowHeight, "Triangle", nullptr, nullptr);
    if (window == nullptr)
    {
        std::cerr << "Failed to create a window!" << std::endl;
        return nullptr;
    }
 
    std::cout << "Window created!" << std::endl;
 
    glfwMakeContextCurrent(window);
    glewExperimental = true;
    if (glewInit() != GLEW_OK)
    {
        std::cerr << "Failed to initialize GLEW!";
        return nullptr;
    }
 
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
 
    std::cout << "GLEW initialized!" << std::endl;
 
    std::cout << "You are running OpenGL: " << glfwGetVersionString() << std::endl;
 
    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
    glfwSetKeyCallback(window, key_callback);
 
    return true;
}
 
void OpenGLView::loadBunnyAsset()
{
    std::vector<glm::vec3> vertices, normals;
    std::vector<GLuint> elements;
 
    loadObjSimple(FILE_PATH, vertices, normals, elements);
 
    bunny.shaderProgramID = loadShaders("vertexShader.txt", "fragmentShader.txt");
 
    glGenVertexArrays(1, &bunny.vertexArray);
    glBindVertexArray(bunny.vertexArray);
 
    glGenBuffers(1, &bunny.vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, bunny.vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
 
    glGenBuffers(1, &bunny.normalBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, bunny.normalBuffer);
    glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0], GL_STATIC_DRAW);
 
    glGenBuffers(1, &bunny.elementBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bunny.elementBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, elements.size() * sizeof(unsigned int), &elements[0], GL_STATIC_DRAW);
 
    bunny.elementsSize = elements.size();
}
 
glm::mat4 OpenGLView::translate(glm::vec3 position)
{
    return glm::translate(glm::mat4(), position);
}
 
glm::mat4 OpenGLView::scale(glm::vec3 size)
{
    return glm::scale(glm::mat4(), size);
}
 
void OpenGLView::loadUniforms(AssetInstance assetInstance)
{
    Asset* asset = &assetInstance.asset;
 
    glUseProgram(asset->shaderProgramID);
    glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 1000.0f);
    glm::mat4 camera = Projection * getViewMatrix();
    glm::mat4 model = translate(assetInstance.position) * scale(assetInstance.scale);
 
    GLuint cameraID = glGetUniformLocation(asset->shaderProgramID, "camera");
    GLuint modelID = glGetUniformLocation(asset->shaderProgramID, "model");
    GLuint cameraPositionID = glGetUniformLocation(asset->shaderProgramID, "cameraPosition");
    GLuint lightPositionID = glGetUniformLocation(asset->shaderProgramID, "light.position");
    GLuint lightIntensitiesID = glGetUniformLocation(asset->shaderProgramID, "light.intensities");
    GLuint lightAttenuationID = glGetUniformLocation(asset->shaderProgramID, "light.attenuation");
    GLuint lightAmbientCoefficientID = glGetUniformLocation(asset->shaderProgramID, "light.ambientCoefficient");
    GLuint materialColorID = glGetUniformLocation(asset->shaderProgramID, "materialColor");
    GLuint materialShininessID = glGetUniformLocation(asset->shaderProgramID, "materialShininess");
    GLuint materialSpecularColorID = glGetUniformLocation(asset->shaderProgramID, "materialSpecularColor");
 
    glUniformMatrix4fv(cameraID, 1, GL_FALSE, &camera[0][0]);
    glUniformMatrix4fv(modelID, 1, GL_FALSE, &model[0][0]);
    glUniform3fv(cameraPositionID, 1, &cameraPosition[0]);
    glUniform3fv(lightPositionID, 1, &light.position[0]);
    glUniform3fv(lightIntensitiesID, 1, &light.intensities[0]);
    glUniform1f(lightAttenuationID, light.attenuation);
    glUniform1f(lightAmbientCoefficientID, light.ambientCoefficient);
    glUniform3fv(materialColorID, 1, &assetInstance.materialColor[0]);
    glUniform1f(materialShininessID, assetInstance.materialShininess);
    glUniform3fv(materialSpecularColorID, 1, &assetInstance.materialSpecularColor[0]);
}
/*
void OpenGLView::getKeys()
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
        glfwSetWindowShouldClose(window, GL_TRUE);
    }
    if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) {
        model = glm::rotate(model, 1.5f, glm::vec3(0, 1, 0));
    }
    if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS) {
        model = glm::rotate(model, -1.5f, glm::vec3(0, 1, 0));
    }
    if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) {
        model = glm::scale(model, glm::vec3(1.5, 1.5, 1.5));
    }
    if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) {
        model = glm::scale(model, glm::vec3(0.95, 0.95, 0.95));
    }
}*/
 
 
void OpenGLView::run()
{    
    initializeAndSetupWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "PhongBunny");
    glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
 
    loadBunnyAsset();
 
    AssetInstance bunny1;
    bunny1.asset = bunny;
    bunny1.position = glm::vec3(0.0f, 0.0f, 0.0f);
    bunny1.scale = glm::vec3(1.0f, 1.0f, 1.0f);
 
 
    do{
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
        loadUniforms(bunny1);
 
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, bunny.vertexBuffer);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
 
        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, bunny.normalBuffer);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
 
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bunny.elementBuffer);
 
        glDrawElements(GL_TRIANGLES, bunny.elementsSize, GL_UNSIGNED_INT, (void*)0);
 
        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);
 
        glfwSwapBuffers(window);
        glfwPollEvents();
    } while (!glfwWindowShouldClose(window));
 
    glfwDestroyWindow(window);
    glfwTerminate();
}

my vertex shader:
 

Code :
#version 330 core
 
uniform mat4 camera;
uniform mat4 model;
 
layout(location = 0) in vec3 vert;
layout(location = 1) in vec3 vertNormal;
 
out vec3 fragVert;
out vec3 fragNormal;
 
void main() {
// Pass some variables to the fragment shader
fragNormal = vertNormal;
fragVert = vert;
 
// Apply all matrix transformations to vert
gl_Position = camera * model * vec4(vert, 1);
}

my fragment shader:
 

Code :
#version 150 core
 
uniform mat4 model;
uniform vec3 cameraPosition;
 
// material settings
uniform float materialShininess;
uniform vec3 materialSpecularColor;
uniform vec3 materialColor;
 
uniform struct Light {
vec3 position;
vec3 intensities; //a.k.a the color of the light
float attenuation;
float ambientCoefficient;
} light;
 
in vec3 fragNormal;
in vec3 fragVert;
 
out vec4 finalColor;
 
void main() {
vec3 normal = normalize(transpose(inverse(mat3(model))) * fragNormal);
vec3 surfacePos = vec3(model * vec4(fragVert, 1));
vec4 surfaceColor = vec4(materialColor, 1);
vec3 surfaceToLight = normalize(light.position - surfacePos);
vec3 surfaceToCamera = normalize(cameraPosition - surfacePos);
 
//ambient
vec3 ambient = light.ambientCoefficient * surfaceColor.rgb * light.intensities;
 
//diffuse
float diffuseCoefficient = max(0.0, dot(normal, surfaceToLight));
vec3 diffuse = diffuseCoefficient * surfaceColor.rgb * light.intensities;
 
//specular
float specularCoefficient = 0.0;
if(diffuseCoefficient > 0.0)
specularCoefficient = pow(max(0.0, dot(surfaceToCamera, reflect(-surfaceToLight, normal))), materialShininess);
vec3 specular = specularCoefficient * materialSpecularColor * light.intensities;
 
//attenuation
float distanceToLight = length(light.position - surfacePos);
float attenuation = 1.0 / (1.0 + light.attenuation * pow(distanceToLight, 2));
 
//linear color (color before gamma correction)
vec3 linearColor = ambient + attenuation*(diffuse + specular);
 
//final color (after gamma correction)
vec3 gamma = vec3(1.0/2.2);
finalColor = vec4(pow(linearColor, gamma), surfaceColor.a);
}

and finally my controls implementation:
 

Code :
#include "controls.h"
 
glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 View = glm::lookAt(
    glm::vec3(5, 3, 8),
    glm::vec3(0, 0, 0),
    glm::vec3(0, 1, 0));
 
glm::mat4 getModelMatrix() {
 
    return Model;
}
glm::mat4 getViewMatrix() {
 
    return View;
}
 
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
        glfwSetWindowShouldClose(window, GL_TRUE);
    }
    if (key == GLFW_KEY_LEFT) {
        Model = glm::rotate(Model, 1.5f, glm::vec3(0, 1, 0));
    }
    if (key == GLFW_KEY_RIGHT) {
        Model = glm::rotate(Model, -1.5f, glm::vec3(0, 1, 0));
    }
    if (key == GLFW_KEY_UP) {
        Model = glm::scale(Model, glm::vec3(1.05, 1.05, 1.05));
    }
    if (key == GLFW_KEY_DOWN) {

 

Share this post


Link to post
Share on other sites
Advertisement

That's a lot of code, but I can't seem to actually find your main runtime code. It seems to just be your class functions and definitions. Including that would likely help pinpoint things.

 

It does look like your run() function doesn't actually call your getKeys() function, just a do/while loop rendering opengl while the window is open, which should just keep you locked in there until you close the window. There are probably multiple ways to do things, but generally I think you want to update key input (and whatever other game functions you need to update), then render.

 

I don't want to complicate things with a timestep or anything, but a simplified version would look like:

void::Render()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    loadUniforms(bunny1);
 
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, bunny.vertexBuffer);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
 
    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, bunny.normalBuffer);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bunny.elementBuffer);
 
    glDrawElements(GL_TRIANGLES, bunny.elementsSize, GL_UNSIGNED_INT, (void*)0);
 
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
 
    glfwSwapBuffers(window);
        
}
void OpenGLView::run()
{    
    initializeAndSetupWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "PhongBunny");
    glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
 
    loadBunnyAsset();
 
    AssetInstance bunny1;
    bunny1.asset = bunny;
    bunny1.position = glm::vec3(0.0f, 0.0f, 0.0f);
    bunny1.scale = glm::vec3(1.0f, 1.0f, 1.0f);
    do{
        glfwPollEvents();
        getKeys();
        Render();
    } while (!glfwWindowShouldClose(window));
 
    glfwDestroyWindow(window);
    glfwTerminate();
} 

(by the way, the little <> in the post menu will let you add code, it formats it a little cleaner smile.png)

 

I could be off here though, it's a lot of jumbled code, and I'm running out the door in a minute here. Hopefully someone else has time to go through it. I'll check back in a bit later tonight and see if that helped at all.

 

Also, welcome :)

Edited by Misantes

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!