c++ - 简单的 OpenGL 应用程序

标签 c++ linux opengl g++

作为一名学生,我正在尝试学习 OpenGL。我花了很多时间试图弄清楚为什么这个简单的应用程序不起作用。这是我们教授给出的一个例子。 (我们在windows下用Visual Studio工作,但我别无选择,只能在家里使用Linux,这不是任性)。这是我编写的程序(在 Windows 上运行完美)并且仅显示黑色窗口(它应该显示三角形)。

//
//  main.cpp
//  OpenGL_Shader_Example_step1
//
//  Created by CGIS on 30/11/15.
//  Copyright © 2015 CGIS. All rights reserved.
//

#define GLEW_STATIC

#include <iostream>
#include "GL/glew.h"
#include "GLFW/glfw3.h"

#include <fstream>
#include <sstream>
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <vector>

int glWindowWidth = 640;
int glWindowHeight = 480;
int retina_width, retina_height;
GLFWwindow* glWindow = NULL;

GLuint shaderProgram;

GLfloat vertexCoordinates[] = {
                                0.0f, 0.5f, 0.0f,
                                0.5f, -0.5f, 0.0f,
                                -0.5f, -0.5f, 0.0f
                              };
GLuint verticesVBO;
GLuint triangleVAO;

void windowResizeCallback(GLFWwindow* window, int width, int height)
{
    fprintf(stdout, "window resized to width: %d , and height: %d\n", width, height);
    //TODO
}

void initObjects()
{
    //generate a unique ID corresponding to the verticesVBO
    glGenBuffers(1, &verticesVBO);
    //bind the verticesVBO buffer to the GL_ARRAY_BUFFER target,
    //any further buffer call made to GL_ARRAY_BUFFER will configure the
    //currently bound buffer, which is verticesVBO
    glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
    //copy data into the currently bound buffer, the first argument specify
    //the type of the buffer, the second argument specify the size (in bytes) of data,
    //the third argument is the actual data we want to send,
    //the last argument specify how should the graphic card manage the data
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoordinates), vertexCoordinates, GL_STATIC_DRAW);

    //generate a unique ID corresponding to the triangleVAO
    glGenVertexArrays(1, &triangleVAO);
    glBindVertexArray(triangleVAO);
    glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
    //set the vertex attributes pointers
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    glEnableVertexAttribArray(0);
    //unbind the triangleVAO
    glBindVertexArray(0);
}

bool initOpenGLWindow()
{
    if (!glfwInit()) {
        fprintf(stderr, "ERROR: could not start GLFW3\n");
        return false;
    }

    //for Mac OS X
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    glWindow = glfwCreateWindow(glWindowWidth, glWindowHeight, "OpenGL Shader Example", NULL, NULL);
    if (!glWindow) {
        fprintf(stderr, "ERROR: could not open window with GLFW3\n");
        glfwTerminate();
        return false;
    }

    glfwSetWindowSizeCallback(glWindow, windowResizeCallback);
    glfwMakeContextCurrent(glWindow);

    glfwWindowHint(GLFW_SAMPLES, 4);

    // start GLEW extension handler
    glewExperimental = GL_TRUE;
    glewInit();

    // get version info
    const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
    const GLubyte* version = glGetString(GL_VERSION); // version as a string
    printf("Renderer: %s\n", renderer);
    printf("OpenGL version supported %s\n", version);

    //for RETINA display
    glfwGetFramebufferSize(glWindow, &retina_width, &retina_height);

    return true;    
}

void renderScene()
{
    //clear the color and depth buffer before rendering the current frame
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //specify the background color
    glClearColor(0.8, 0.8, 0.8, 1.0);
    //specify the viewport location and dimension
    glViewport (0, 0, retina_width, retina_height);

    //process the keyboard inputs
    if (glfwGetKey(glWindow, GLFW_KEY_A)) {
    //TODO
    }

    if (glfwGetKey(glWindow, GLFW_KEY_D)) {
    //TODO
    }

    //bind the shader program, any further rendering call
    //will use this shader program
    glUseProgram(shaderProgram);

    //bind the VAO
    glBindVertexArray(triangleVAO);
    //specify the type of primitive, the starting index and
    //the number of indices to be rendered
    glDrawArrays(GL_TRIANGLES, 0, 3);
}

std::string readShaderFile(std::string fileName)
{
    std::ifstream shaderFile;
    std::string shaderString;

    //open shader file
    shaderFile.open(fileName.c_str());

    std::stringstream shaderStringStream;

    //read shader content into stream
    shaderStringStream << shaderFile.rdbuf();

    //close shader file
    shaderFile.close();

    //convert stream into GLchar array
    shaderString = shaderStringStream.str();
    return shaderString;
}

void shaderCompileLog(GLuint shaderId)
{
    GLint success;
    GLchar infoLog[512];

    //check compilation info
    glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(shaderId, 512, NULL, infoLog);
        std::cout << "Shader compilation error\n" << infoLog << std::endl;
    }
}

void shaderLinkLog(GLuint shaderProgramId)
{
    GLint success;
    GLchar infoLog[512];

    //check linking info
    glGetProgramiv(shaderProgramId, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "Shader linking error\n" << infoLog << std::endl;
    }
}

GLuint initBasicShader(std::string vertexShaderFileName, std::string fragmentShaderFileName)
{
    //read, parse and compile the vertex shader
 std::string v = readShaderFile(vertexShaderFileName);
 const GLchar* vertexShaderString = v.c_str();
 GLuint vertexShader;
 vertexShader = glCreateShader(GL_VERTEX_SHADER);
 glShaderSource(vertexShader, 1, &vertexShaderString, NULL);
 glCompileShader(vertexShader);
 //check compilation status
 shaderCompileLog(vertexShader);

 //read, parse and compile the vertex shader
 std::string f = readShaderFile(fragmentShaderFileName);
 const GLchar* fragmentShaderString = f.c_str();
 GLuint fragmentShader;
 fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
 glShaderSource(fragmentShader, 1, &fragmentShaderString, NULL);
 glCompileShader(fragmentShader);
 //check compilation status
 shaderCompileLog(fragmentShader);

 //attach and link the shader programs
 shaderProgram = glCreateProgram();
 glAttachShader(shaderProgram, vertexShader);
 glAttachShader(shaderProgram, fragmentShader);
 glLinkProgram(shaderProgram);
 glDeleteShader(vertexShader);
 glDeleteShader(fragmentShader);
 //check linking info
 shaderLinkLog(shaderProgram);

 return shaderProgram;
}

int main(int argc, const char * argv[]) 
{
    initOpenGLWindow();

    initObjects();

    shaderProgram = initBasicShader("shaders/shader.vert", "shaders/shader.frag");

    while (!glfwWindowShouldClose(glWindow)) {
        renderScene();

        glfwPollEvents();
        glfwSwapBuffers(glWindow);
    }

    //close GL context and any other GLFW resources
    glfwTerminate();

    return 0;
}

以下是着色器程序: 着色器.frag:

#version 300 es
precision mediump float;

in vec3 colour;
out vec4 frag_colour;

void main() {
    frag_colour = vec4 (colour, 1.0);
}

和shader.vert:

#version 300 es

layout (location = 0) in vec3 vertex_position;

out vec3 colour;

void main() {
    colour = vec3(1.0, 0.0, 0.0);
    gl_Position = vec4(vertex_position, 1.0);
}

这是用于编译程序的命令(我使用的是 Visual Studio 代码):

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "0.1.0",
    "command": "g++",
    "isShellCommand": true,
    "args": ["-g",
             "-Wall",
             "-o", "lab2.exe", 
             "main.cpp", 
             "-I/usr/include/c++/4.8.5", 
             "-I/usr/include/GL", 
             "-I/usr/include/glm", 
             "-I/usr/local/include/GLFW", 
             "-L/usr/local/lib", "-lGLEW", "-lGLU", "-lglfw3", "-lGL", "-lm", "-ldl", "-lXrender", "-ldrm", 
             "-lXdamage", "-lX11-xcb", "-lxcb-glx", "-lxcb-dri2", "-lxcb-dri3", "-lxcb-present", "-lxcb-sync", "-lxshmfence", "-lXxf86vm",
             "-lXfixes", "-lXext", "-lX11", "-lpthread", "-lxcb", "-lXau", "-lXdmcp",
             "-lXrandr", "-lXi", "-lXxf86vm", "-lXcursor"],
    "showOutput": "always"
}

args 参数被赋予 g++。 如果我遇到错误,我会有一个起点,但像这样我不知道该怎么办。

这是glxinfo | 的结果grep OpenGL命令:

OpenGL vendor string: Intel Open Source Technology Center
OpenGL renderer string: Mesa DRI Intel(R) Haswell Mobile 
OpenGL core profile version string: 3.3 (Core Profile) Mesa 11.2.0
OpenGL core profile shading language version string: 3.30
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 3.0 Mesa 11.2.0
OpenGL shading language version string: 1.30
OpenGL context flags: (none)
OpenGL extensions:

最佳答案

我建议使用 opengl/glsl 调试器来查看发生了什么。虽然已经有一段时间了,但我之前使用 glslDevil 取得了很多成功 - 它与 Linux 兼容,可以帮助您发现 opengl 错误 - 特别是您的硬件/平台上不受支持的功能。

关于c++ - 简单的 OpenGL 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40204051/

相关文章:

MySQL Workbench SSH 连接错误

c++ - 围绕 OpenGL 场景中的对象旋转有困难

Python显示.ply、.STL、.igs、.step图像

c++ - 奇怪的 OpenGL 片段着色器行为与 gl_PointCoord

c++ - 没有继承的公共(public)成员

c++ - 如何为动态矩阵重载运算符 [] 以返回值!? C++

linux - 条件移动问题

c++ - 如何提高文件的读取速度?

c++ - 如何在 gdb 中将 C++ std::vector 的大小设为 "watch"?

linux - Bash Printf 格式不正确