OpenGL 未解析的外部符号 VS 2013

OpenGL unresolved External Symbol VS 2013

2013 年 Visual Studio 弹出一个链接器错误,我不明白为什么它会抛给我。

我已经看到很多关于此的问题,但 none 似乎适合这里。

背景:我正在使用 OpenGl 绘制一个小三角形。

错误:

Fehler 1 error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: struct glm::tmat4x4 __thiscall Transform::getModel(void)const " (?getModel@Transform@@QBE?AU?$tmat4x4@M[=15=]A@@glm@@XZ)" in Funktion ""public: void __thiscall Shader::Update(class Transform const &)" (?Update@Shader@@QAEXABVTransform@@@Z)". D:\Arbeit\Prog\CPPprojects \OpenGLTutorial\OpenGlTut\OpenGlTut\Shader.obj

因此,正如我所见,链接器找不到 glm::mat4 的符号。 Symbol 像往常一样在 headers 中定义,并由库实现。

以下是我添加到项目中的所有库:

在我添加 class 转换并编辑 class 着色器以将其纳入之前,所有项目都运行良好。

代码如下:

Shader.h

#ifndef SHADER_H
#define SHADER_H

#include <string>
#include <glew\GL\glew.h>
#include "Transform.h"

class Shader
{
    enum
    {
        TRANSFORM_U,

        NUM_UNIFORM
    };

    static const unsigned int NUM_SHADER = 2;
    GLuint program;
    GLuint shaders[NUM_SHADER];
    GLuint uniforms[NUM_UNIFORM];

public:
    Shader(const std::string& filename);
    ~Shader();
    void Bind();
    void Update(const Transform& transform);
};
#endif

Shader.cpp:

#include "Shader.h"
#include <iostream>
#include <fstream>
#include <exception>


static void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string& errorMessage);
static std::string LoadShader(const std::string& filename);
static GLuint CreateShader(const std::string& text, GLenum shaderType);


Shader::Shader(const std::string& filename)
{
    program = glCreateProgram();
    shaders[0] = CreateShader(LoadShader(filename+".vs") , GL_VERTEX_SHADER);
    shaders[1] = CreateShader(LoadShader(filename+".fs"), GL_FRAGMENT_SHADER);

    for (unsigned int i = 0; i < NUM_SHADER; i++)
    {
        glAttachShader(program, shaders[i]);
    }

    glBindAttribLocation(program, 0, "position");
    glBindAttribLocation(program, 1, "texCoord");

    glLinkProgram(program);
    CheckShaderError(program, GL_LINK_STATUS, true, "Error: Program linking failed :");

    glValidateProgram(program);
    CheckShaderError(program, GL_VALIDATE_STATUS, true, "Error: Program is invalid :");

    uniforms[TRANSFORM_U] = glGetUniformLocation(program, "transform");
}


Shader::~Shader()
{

    for (unsigned int i = 0; i < NUM_SHADER; i++)
    {
        glDetachShader(program, shaders[i]);
        glDeleteShader(shaders[i]);
    }

    glDeleteProgram(program);
}

void Shader::Bind()
{
    glUseProgram(program);
}

void Shader::Update(const Transform& transform)
{
    glm::mat4 model = transform.getModel();

    glUniformMatrix4fv(uniforms[TRANSFORM_U], 1, GL_FALSE, &model[0][0]);
}



static GLuint CreateShader(const std::string& text, GLenum shaderType)
{
    GLuint shader = glCreateShader(shaderType);
    if (shader == 0)
    {
        throw std::runtime_error("Error: Shader creation failed !");
    }
    const GLchar* shaderSourceStrings[1];
    GLint shaderSourceStringLengths[1];

    shaderSourceStrings[0] = text.c_str();
    shaderSourceStringLengths[0] = text.length();

    glShaderSource(shader, 1 ,shaderSourceStrings, shaderSourceStringLengths);
    glCompileShader(shader);

    CheckShaderError(shader, GL_COMPILE_STATUS, false, "Error: Shader compilation failed: ");

    return shader;
}

static std::string LoadShader(const std::string& filename)
{
    std::ifstream file;
    file.open((filename).c_str());

    std::string output;
    std::string line;

    if (file.is_open())
    {
        while (file.good())
        {
            getline(file, line);
            output.append(line + "\n");
        }
    }
    else
    {
        throw std::runtime_error("Unable to load Shader :" + filename);
    }

    return output;
}

static void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string& errorMessage)
{
    GLint success = 0;
    GLchar error[1024] = { 0 };

    if (isProgram)
        glGetProgramiv(shader, flag, &success);
    else
        glGetShaderiv(shader, flag, &success);

    if (success == GL_FALSE)
    {
        if (isProgram)
        {
            glGetProgramInfoLog(shader, sizeof(error), NULL, error);
        }
        else glGetShaderInfoLog(shader, sizeof(error), NULL, error);

        throw std::runtime_error(errorMessage + ": " + error + "\n");
    }

}

Transform.h:

#ifndef TRANSFORM_H
#define TRANSFORM_H


#include <glm\gtx\transform.hpp>
#include <glm\glm.hpp>


class Transform
{
    glm::vec3 pos, rot, scale;

public: 
    inline const glm::vec3& getPos() const;
    inline const glm::vec3& getRot() const;
    inline const glm::vec3& getScale() const;

    inline void setPos(glm::vec3& pos);
    inline void setRot(glm::vec3& rot);
    inline void setScale(glm::vec3& Scale);

    Transform(const glm::vec3& pos = glm::vec3(), const glm::vec3& rot = glm::vec3(), const glm::vec3& scale = glm::vec3(1.0f, 1.0f, 1.0f));
    ~Transform();

    inline glm::mat4 getModel() const;
};

#endif

Transform.cpp:

#include "Transform.h"


Transform::Transform(const glm::vec3& pos, const glm::vec3& rot, const glm::vec3& scale) :
pos(pos),
rot(rot),
scale(scale)
{
}


Transform::~Transform()
{
}


inline const glm::vec3& Transform::getPos() const { return pos; }
inline const glm::vec3& Transform::getRot() const { return rot; }
inline const glm::vec3& Transform::getScale() const { return scale; }

inline void Transform::setPos(glm::vec3& pos){ this->pos = pos; }
inline void Transform::setRot(glm::vec3& rot){ this->rot = rot; }
inline void Transform::setScale(glm::vec3& Scale){ this->scale = scale; }


inline glm::mat4 Transform::getModel() const 
{
    glm::mat4 posMatrix = glm::translate(pos);
    glm::mat4 rotXMatrix = glm::rotate(rot.x, glm::vec3(1, 0, 0));
    glm::mat4 rotYMatrix = glm::rotate(rot.y, glm::vec3(0, 1, 0));
    glm::mat4 rotZMatrix = glm::rotate(rot.z, glm::vec3(0, 0, 1));
    glm::mat4 scaleMatrix = glm::scale(scale);

    glm::mat4 rotMatrix = rotZMatrix * rotYMatrix * rotXMatrix;             //multiply them in reverse order

    return posMatrix * rotMatrix * scaleMatrix;                             // first scale them right , then turn them, then move them the right spot
}   

main.cpp:

#include <iostream>

#include "SDLGuard.h"
#include "Display.h"
#include <glew\GL\glew.h>
#include "Mesh.h"
#include "Shader.h"
#include "Texture.h"
#include "Transform.h"


#undef main

void run()
{
    Display display(800, 600, "HelloWorld !");

    Vertex vertices[] = { 
        Vertex(glm::vec3(-0.5, -0.5, 0.0), glm::vec2(0.0,0.0)),
        Vertex(glm::vec3(0.0, 0.5, 0.0),   glm::vec2(0.5, 1.0)),
        Vertex(glm::vec3(0.5, -0.5, 0.0),  glm::vec2(1.0, 0.0)),
    };

    Mesh mesh(vertices, sizeof(vertices) / sizeof(vertices[0]));

    Shader shader("./res/basicShader");

    Texture texture("./res/testTexture.jpg");

    Transform transform;


    while (!display.isClosed())
    {
        display.clear(0.30f, 0.0f, 0.05f, 1.0f);
        shader.Bind();
        texture.bind();
        shader.Update(transform);
        mesh.draw();
        display.update();
    }
}

int main(int argc, char *argv[])
{
    SDLGuard sdlguard;          //initialize SDL and quit it before quiting program throoug self written guard
    try{
        run();
    }
    catch (std::runtime_error &re)
    {
        std::cout << re.what() << std::endl;
        getchar();
    }
    return 0;
}

因为所有库都在那里并且包含 headers 我不知道链接时出了什么问题。 也许现在有人看到了我忽略了几个小时的问题。

提前致谢!

你的问题出在这个声明里面transform.cpp

inline glm::mat4 Transform::getModel() const {...}

删除 inline 因为它强制该函数只能在该编译单元内看到。