带有 SDL 和 GLEW 的 OpenGL,错误:48

Posted

技术标签:

【中文标题】带有 SDL 和 GLEW 的 OpenGL,错误:48【英文标题】:OpenGL with SDL and GLEW, error:48 【发布时间】:2016-01-04 23:08:16 【问题描述】:

我开始按照这个教程制作一个小的 OpenGL 程序:

https://www.youtube.com/watch?v=I4az5VDpxVw&index=14&list=PLSPw4ASQYyymu3PfG9gxywSPghnSMiOAW

在我学习教程 11 之前一切正常。从那时起,它确实构建得很好,但是当我想运行编译后的程序时,它只是输出

    error: 48

在控制台中并立即关闭。

所以我做了一些研究,但我没有发现其他人有这个问题,我发现的只是:

msdn.microsoft.com/en-us/library/aa232611(v=vs.60).aspx

我什至不确定这是否与我的问题有关。

奇怪的是,这从来没有发生过,这个问题第一次出现,当我来到播放列表中的教程 11 时,添加了 picoPNG 并编写了代码来为我加载 png 文件。在添加 picoPNG 时,我也遇到了一些错误,提示“尚未声明 size_t”,但我通过添加该行修复了该问题

    #include <stddef.h>

在 picoPNG.cpp 的顶部。

我在 Windows 10 上使用 Eclipse CDT 8.8.0 和 MinGW w32 20150801、glew 1.13.0(我用 MinGW 编译了源代码)和 SDL2 2.0.4。

我用 MinGW 编译 GLEW 的命令是:

    gcc -DGLEW_NO_GLU -O2 -Wall -W -Iinclude  -DGLEW_BUILD -o src/glew.o -c src/glew.c
    gcc -shared -Wl,-soname,libglew32.dll -Wl,--out-implib,lib/libglew32.dll.a    -o lib/glew32.dll src/glew.o -L/mingw/lib -lglu32 -lopengl32 -lgdi32 -luser32 -lkernel32
    ar cr lib/libglew32.a src/glew.o

    gcc -DGLEW_NO_GLU -DGLEW_MX -O2 -Wall -W -Iinclude  -DGLEW_BUILD -o src/glew.mx.o -c src/glew.c
    gcc -shared -Wl,-soname,libglew32mx.dll -Wl,--out-implib,lib/libglew32mx.dll.a -o lib/glew32mx.dll src/glew.mx.o -L/mingw/lib -lglu32 -lopengl32 -lgdi32 -luser32 -lkernel32
    ar cr lib/libglew32mx.a src/glew.mx.o

(我使用位于 glew-1.13.0 文件夹中的批处理文件执行此操作)

我实际上遵循了教程播放列表,我在上面放置了教程 12 的链接,这就是我再次构建程序并在它一切正常之后第一次启动它的地方。

为什么会这样?该输出背后的问题可能是什么?

编辑:这是我所有的代码

main.cpp

#include <iostream>
#include <SDL.h>
#include <glew.h>
#include <MainGame.h>

using namespace std;

int main(int argc, char* argv[])

    MainGame mainGame;
    mainGame.Run("Game Engine");
    return 0;

GLSLProgram.h

#ifndef CLASSES_GLSLPROGRAM_H_
#define CLASSES_GLSLPROGRAM_H_

#include <string>
#include <glew.h>

class GLSLProgram

public:
    GLSLProgram();
    virtual ~GLSLProgram();

    void CompileShaders(const std::string& filePath);
    void AddAttribute(const std::string& attributeName);
    void LinkShaders();
    void UseProgram();
    void UnUseProgram();
    GLint GetUniformLocation(const std::string& uniformName);

private:
    GLuint m_programID;
    GLuint m_vertexShaderID;
    GLuint m_fragmentShaderID;
    int m_numAttributes;

    void GetShader(const std::string& filePath, const std::string& shaderType, GLuint& shaderID);
;

#endif /* CLASSES_GLSLPROGRAM_H_ */

GLSLProgram.cpp

#include <GLSLProgram.h>
#include <fstream>
#include <vector>
#include "..\Headers\JPKErrors.hpp"

GLSLProgram::GLSLProgram() :
m_programID(0),
m_vertexShaderID(0),
m_fragmentShaderID(0),
m_numAttributes(0)



GLSLProgram::~GLSLProgram()

    if(m_vertexShaderID != 0)
        glDeleteShader(m_vertexShaderID);
    if(m_fragmentShaderID != 0)
        glDeleteShader(m_fragmentShaderID);

    if(m_programID != 0)
        glDeleteProgram(m_programID);


void GLSLProgram::CompileShaders(const std::string& filePath)

    m_programID = glCreateProgram();

    m_vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    if(m_vertexShaderID == 0)
        jpk::FatalError("Vertex shader could not be created!");

    m_fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
    if(m_fragmentShaderID == 0)
        jpk::FatalError("Fragment Shader could not be created!");

    GetShader(filePath + ".vsh", "Vertex", m_vertexShaderID);
    GetShader(filePath + ".fsh", "Fragment", m_fragmentShaderID);


void GLSLProgram::AddAttribute(const std::string& attributeName)

    glBindAttribLocation(m_programID, m_numAttributes++, attributeName.c_str());


void GLSLProgram::LinkShaders()

    glAttachShader(m_programID, m_vertexShaderID);
    glAttachShader(m_programID, m_fragmentShaderID);

    glLinkProgram(m_programID);

    GLint isLinked = 0;
    glGetProgramiv(m_programID, GL_LINK_STATUS, (int*)&isLinked);
    glDetachShader(m_programID, m_vertexShaderID);
    glDetachShader(m_programID, m_fragmentShaderID);

    if(isLinked == GL_FALSE)
    
        GLint maxLength = 0;
        glGetProgramiv(m_programID, GL_INFO_LOG_LENGTH, &maxLength);

        std::vector<char> errorLog(maxLength);
        glGetProgramInfoLog(m_programID, maxLength, &maxLength, &errorLog[0]);

        printf("%s\n", &errorLog[0]);

        jpk::FatalError("Shader program failed to link!\nDetails:");
    


void GLSLProgram::GetShader(const std::string& filePath, const std::string& shaderType, GLuint& shaderID)

    std::ifstream shaderFile(filePath);
    if(shaderFile.fail())
        jpk::FatalError(shaderType + " shader file " + filePath + " could not be opened!", false, true, filePath);

    std::string fileContents("");
    std::string line;

    while(getline(shaderFile, line))
        fileContents += line + "\n";

    shaderFile.close();

    const char* charFileContents = fileContents.c_str();
    glShaderSource(shaderID, 1, &charFileContents, nullptr);
    glCompileShader(shaderID);
    GLint success = 0;
    glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success);
    if(success == GL_FALSE)
    
        GLint maxLength = 0;
        glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &maxLength);

        std::vector<char> errorLog(maxLength);
        glGetShaderInfoLog(shaderID, maxLength, &maxLength, &errorLog[0]);
        printf("%s\n", &errorLog[0]);
        jpk::FatalError(shaderType + " shader file " + filePath + " failed to compile!\nDetails:");
    



void GLSLProgram::UseProgram()

    glUseProgram(m_programID);
    for(int i=0; i < m_numAttributes ;i++)
        glEnableVertexAttribArray(i);


void GLSLProgram::UnUseProgram()

    glUseProgram(0);
    for(int i=0; i < m_numAttributes ;i++)
        glDisableVertexAttribArray(i);


GLint GLSLProgram::GetUniformLocation(const std::string& uniformName)

    GLint location = glGetUniformLocation(m_programID, uniformName.c_str());
    if(location == (GLint)GL_INVALID_INDEX)
        jpk::FatalError("Uniform \"" + uniformName + "\" was not found in shaders!");
    return location;

ImageLoader.h

#ifndef IMAGELOADER_H
#define IMAGELOADER_H
#include "..\Headers\GLTexture.hpp"
#include <string>

class ImageLoader 
public:
    static GLTexture LoadPNG(const std::string& filePath);
;

#endif /* IMAGELOADER_H */

ImageLoader.cpp

#include <ImageLoader.h>
#include "..\Headers\picoPNG.hpp"
#include "..\Headers\JPKErrors.hpp"
#include "IOManager.h"
#include <iostream>

GLTexture ImageLoader::LoadPNG(const std::string& filePath)

    GLTexture texture = ;

    std::vector<unsigned char> out, in;
    unsigned long width, height;

    if(!IOManager::ReadFileToBuffer(filePath, in))
    
        jpk::FatalError("Failed to load .png file \"" + filePath + "\" to buffer!");
    

    int errorCode = decodePNG(out, width, height, &in[0], in.size());
    if(errorCode != 0)
    
        jpk::FatalError("Could not decode the .png file \"" + filePath + "\" with error code: " + std::to_string(errorCode));
    

    glGenTextures(1, &texture.ID);

    glBindTexture(GL_TEXTURE_2D, texture.ID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.width, texture.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &out[0]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

    glGenerateMipmap(GL_TEXTURE_2D);

    glBindTexture(GL_TEXTURE_2D, 0);

    texture.width = width;
    texture.height = height;

    return texture;

IOManager.h

#ifndef IOMANAGER_H
#define IOMANAGER_H

#include <vector>
#include <string>

class IOManager

public:
    static bool ReadFileToBuffer(const std::string& filePath, std::vector<unsigned char>& buffer);
;

#endif /* IOMANAGER_H */

IOManager.cpp

#include <IOManager.h>
#include <fstream>

bool IOManager::ReadFileToBuffer(const std::string& filePath, std::vector<unsigned char>& buffer)

    std::ifstream file(filePath, std::ios::binary);
    if(file.fail())
    
        perror(filePath.c_str());
        return false;
    

    file.seekg(0, std::ios::end);
    int fileSize = file.tellg();
    file.seekg(0, std::ios::beg);

    buffer.resize(fileSize);
    file.read((char*)&buffer[0], fileSize);

    file.close();
    return true;

MainGame.h

#ifndef MAINGAME_H
#define MAINGAME_H

#include <SDL.h>
#include "Sprite.h"
#include "GLSLProgram.h"
#include "..\Headers\GLTexture.hpp"

class MainGame

public:
    MainGame();
    MainGame(int width, int height);
    virtual ~MainGame();

    void Run(const char* windowTitle);

private:
    enum class GameState PLAY, EXIT;
    SDL_Window* m_window;
    int m_windowWidth;
    int m_windowHeight;
    float m_time;

    Sprite m_sprite;
    GLSLProgram m_colorProgram;
    GLTexture m_playerTexture;

    void InitSystems(const char* windowTitle);
    void GameLoop();
    void ProcessInput();
    void DrawGame();
    void InitShaders();

    GameState m_currentGameState;
;

#endif /* MAINGAME_H_ */

MainGame.cpp

#include "MainGame.h"

#include <iostream>
#include <string>
#include <glew.h>
#include <conio.h>
#include "..\Headers\JPKErrors.hpp"
#include <ImageLoader.h>

MainGame::MainGame() :
m_window(nullptr),
m_windowWidth(800),
m_windowHeight(600),
m_time(0),
m_currentGameState(GameState::PLAY)



MainGame::MainGame(int width, int height) :
m_window(nullptr),
m_windowWidth(width),
m_windowHeight(height),
m_time(0),
m_currentGameState(GameState::PLAY)



MainGame::~MainGame()

    m_window = nullptr;
    SDL_Quit();


void MainGame::Run(const char* windowTitle)

    InitSystems(windowTitle);
    GameLoop();


void MainGame::InitSystems(const char* windowTitle)

    SDL_Init(SDL_INIT_EVERYTHING);
    m_window = SDL_CreateWindow(windowTitle, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_windowWidth, m_windowHeight, SDL_WINDOW_OPENGL);
    if(m_window == nullptr)
        jpk::FatalError("SDL Window could not be created!", true);

    SDL_GLContext glContext = SDL_GL_CreateContext(m_window);
    if(glContext == nullptr)
        jpk::FatalError("SDL GL Context could not be created out of m_window!", true);

    GLenum error = glewInit();
    if(error != GLEW_OK)
        jpk::FatalError("CLEW could not be initialized!");

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

    m_sprite.Init(-0.75, -0.75, 1.5, 1.5);

    m_playerTexture = ImageLoader::LoadPNG("./Files/Images/JimmyJumpPack/PNG/CharacterRight_Standing.png");

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    InitShaders();


void MainGame::ProcessInput()

    SDL_Event sdlEvent;
    while(SDL_PollEvent(&sdlEvent))
    
        switch(sdlEvent.type)
        
            case SDL_QUIT: m_currentGameState = GameState::EXIT; break;
            case SDL_MOUSEMOTION:
                std::cout << sdlEvent.motion.x << " " << sdlEvent.motion.y << std::endl;
        
    


void MainGame::GameLoop()

    while(m_currentGameState != GameState::EXIT)
    
        try
        
        ProcessInput();
        m_time += 0.01;
        DrawGame();
        
        catch(jpk::FatalErrorException& e)
        
            m_currentGameState = GameState::EXIT;
        
    


void MainGame::DrawGame()

    glClearDepth(1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    m_colorProgram.UseProgram();

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_playerTexture.ID);
    GLint textureLocation = m_colorProgram.GetUniformLocation("textureSampler");
    glUniform1i(textureLocation, 0);

    m_sprite.Draw();

    glBindTexture(GL_TEXTURE_2D, 0);

    m_colorProgram.UnUseProgram();

    SDL_GL_SwapWindow(m_window);


void MainGame::InitShaders()

    m_colorProgram.CompileShaders("./Files/Shaders/textureShader"); 
    m_colorProgram.AddAttribute("vertexPosition");
    m_colorProgram.AddAttribute("vertexColor");
    m_colorProgram.AddAttribute("vertexUV");
    m_colorProgram.LinkShaders();

Sprite.h

#ifndef SPRITE_H_
#define SPRITE_H_

#include <glew.h>

class Sprite

public:
    Sprite();
    virtual ~Sprite();

    void Init(float x, float y, float width, float height);
    void Draw();

private:
    float m_x;
    float m_y;
    float m_width;
    float m_height;
    GLuint m_vertexBufferObjectID;
;

#endif /* SPRITE_H_ */

Sprite.cpp

#include "Sprite.h"
#include "../Headers/JPKVertex.hpp"
#include <cstddef>

Sprite::Sprite() :
m_x(0),
m_y(0),
m_width(0),
m_height(0)

    m_vertexBufferObjectID = 0;


Sprite::~Sprite()

    if(m_vertexBufferObjectID != 0)
        glDeleteBuffers(1, &m_vertexBufferObjectID);


void Sprite::Init(float x, float y, float width, float height)

    m_x = x;
    m_y = y;
    m_width = width;
    m_height = height;

    if(m_vertexBufferObjectID == 0)
    
        glGenBuffers(1, &m_vertexBufferObjectID);
    

    jpk::Vertex vertexData[6];

    vertexData[0].SetPosition(x+width, y+height);
    vertexData[0].SetUV(1.0f, 1.0f);

    vertexData[1].SetPosition(x, y+height);
    vertexData[1].SetUV(0.0f, 1.0f);

    vertexData[2].SetPosition(x, y);
    vertexData[2].SetUV(0.0f, 0.0f);

    vertexData[3].SetPosition(x, y);
    vertexData[3].SetUV(0.0f, 0.0f);

    vertexData[4].SetPosition(x+width, y);
    vertexData[4].SetUV(1.0f, 0.0f);

    vertexData[5].SetPosition(x+width, y+height);
    vertexData[5].SetUV(1.0f, 1.0f);

    for(int i=0; i < 6 ;i++)
    
        vertexData[i].SetColor(255, 0, 255, 255);
    

    vertexData[1].SetColor(0, 0, 255, 255);
    vertexData[4].SetColor(0, 255, 0, 255);

    glBindBuffer(GL_ARRAY_BUFFER, m_vertexBufferObjectID);

    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, 0);


void Sprite::Draw()

    glBindBuffer(GL_ARRAY_BUFFER, m_vertexBufferObjectID);

    glEnableVertexAttribArray(0);

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(jpk::Vertex), (void*)offsetof(jpk::Vertex, position));
    glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(jpk::Vertex), (void*)offsetof(jpk::Vertex, color));
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(jpk::Vertex), (void*)offsetof(jpk::Vertex, uv));

    glDrawArrays(GL_TRIANGLES, 0, 6);

    glDisableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

GLTexture.hpp

#ifndef GLTEXTURE_HPP
#define GLTEXTURE_HPP

#include <glew.h>

struct GLTexture

    GLuint ID;
    int width;
    int height;
;

#endif /* GLTEXTURE_HPP */

JPKErrors.hpp

#ifndef JPKERRORS_HPP
#define JPKERRORS_HPP

#include <string>
#include "JPKExceptions.hpp"

namespace jpk

    void FatalError(const std::string& errorString, bool isSDLRelated = false, bool usePError = false, const std::string& file = "   ");

#endif  //JPKERRORS_HPP

JPKErrors.cpp

#include "JPKErrors.hpp"
#include <iostream>
#include <conio.h>
#include <SDL.h>
#include <missingmingw\mingw.thread.h>

namespace jpk

    extern void FatalError(const std::string& errorString, bool isSDLRelated, bool usePError, const std::string& file)
    
        std::cerr << "Fatal Error: " << errorString << std::endl;
        if(isSDLRelated)
            std::cerr << "SDL Error: " << SDL_GetError();
        if(usePError && file != "   ")
        
            std::cout << "Error Details: ";
            perror(file.c_str());
            std::cout << std::endl;
        
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
        std::cout << "This application will now close..." << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(3));
        throw FatalErrorException();
    

JPKExceptions.hpp

namespace jpk

    class FatalErrorException;

JPKVertex.hpp

#ifndef JPKVERTEX_H
#define JPKVERTEX_H

#include <glew.h>

namespace jpk

    struct VertexPosition
    
        float x;
        float y;
    ;

    struct VertexColor
    
        GLubyte r;
        GLubyte g;
        GLubyte b;
        GLubyte a;
    ;

    struct VertexUV
    
        float u;
        float v;
    ;

    struct Vertex
    
        VertexPosition position;
        VertexColor color;
        VertexUV uv;

        void SetColor(GLubyte r, GLubyte g, GLubyte b, GLubyte a)
        
            color.r = r;
            color.g = g;
            color.b = b;
            color.a = a;
        

        void SetPosition(float x, float y)
        
            position.x = x;
            position.y = y;
        

        void SetUV(float u, float v)
        
            uv.u = u;
            uv.v = v;
        
    ;


#endif /* JPKVERTEX_H */

picoPNG.hpp

#ifndef PICOPNG_HPP
#define PICOPNG_HPP

#include <vector>
#include <stddef.h>

extern int decodePNG(std::vector<unsigned char>& out_image, unsigned long& image_width, unsigned long& image_height, const unsigned char* in_png, size_t in_size, bool convert_to_rgba32 = true);

#endif /* PICOPNG_HPP */

而且 picoPNG.cpp 太大而无法放入此处,因此,这里是我下载 picoPNG 的链接:

http://lodev.org/lodepng/

我自己也做了一些调试,添加了一行

    std::cout << "Test" << std::endl;

在所有其他代码之前的 int main() 顶部。即使那没有被放到控制台中,只是我上面描述的错误消息。

【问题讨论】:

您好,欢迎来到 ***。请直接在您的问题中添加一些代码,以促进问题的解决。否则你会被否决。 你试过在调试器中运行它吗? @Mr_Pouet 是的,当然,但它的代码相当多 @AdrianKrupa 出于某种奇怪的原因,Eclipse CDT 中的内置调试器不起作用,所以我必须自己进行调试。但我这样做了,正如我现在在问题中所描述的那样。 【参考方案1】:

你好像用过ImageLoader::LoadPNG("./Files/Images/JimmyJumpPack/PNG/CharacterRight_Standing.png");

尝试使用对我有用的完整文件路径。 (loadPNG("C:\\Users\\...\\filename.png");)

如果您查看picopng.cpp,您会发现为什么会出现错误:第 259 行的 48: if(size == 0 || in == 0) error = 48; return; //the given data is empty

所以它肯定没有找到文件。

【讨论】:

【参考方案2】:

picoPNG.cpp 中有一个main 函数!这将与您自己的main 函数发生冲突。所以打开picoPNG.cpp 并注释掉它的main 函数。

【讨论】:

以上是关于带有 SDL 和 GLEW 的 OpenGL,错误:48的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL 深度测试不工作 (GLEW/SDL2)

Qt Creator 中的 Glew 链接问题?

使用SDL和GLEW设置Visual Studio项目

GLEW glGenBuffers 段错误

如何使用 GLEW、OpenGL 或 SDL2 以椭圆运动围绕另一个圆圈旋转一个圆圈?

无法初始化 OpenGL