3

我目前正在尝试用 C++ 编写一个 OpenGL 程序。当我尝试编译我的程序时,我得到未定义的引用,在我调用类的成员函数的任何地方,尽管我从成员函数调用这些函数......

这些是我收到的错误消息:

make clean && make
rm -f *.o *~ main
g++   -c main.cpp  -o main.o
g++   -c renderer.cpp  -o renderer.o
g++   -o main main.o renderer.o  -lglut -lGL -lGLEW
renderer.o: In function `Renderer::resize(int, int)':
renderer.cpp:(.text+0x299): undefined reference to `Renderer::Perspective(float*, float, float, float, float)'
renderer.o: In function `Renderer::setupShaders()':
renderer.cpp:(.text+0x43d): undefined reference to `Renderer::loadShaderSrc(char const*, int&)'
renderer.cpp:(.text+0x456): undefined reference to `Renderer::loadShaderSrc(char const*, int&)'
renderer.cpp:(.text+0x4e7): undefined reference to `Renderer::printShaderInfoLog(int)'
renderer.cpp:(.text+0x4fe): undefined reference to `Renderer::printShaderInfoLog(int)'
renderer.cpp:(.text+0x568): undefined reference to `Renderer::printProgramInfoLog(int)'
collect2: Fehler: ld gab 1 als Ende-Status zurück
make: *** [main] Fehler 1

这是我的源文件:

主.cpp:

#include "renderer.h"

static Renderer *renderer;

static void glutDisplay()
{
    renderer->display();
    glutSwapBuffers();
}

static void glutResize(int w, int h)
{
    renderer->resize(w, h);
}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(320, 320);
    glutCreateWindow("Title");

    GLenum res = glewInit();
    if(res != GLEW_OK)
        return -1;

    glutDisplayFunc(glutDisplay);
    glutReshapeFunc(glutResize);
    renderer = new Renderer;
    renderer->init();
    glutMainLoop();
    return 0;
}

渲染器.cpp:

#include "renderer.h"

Renderer::Renderer() : programID(0.0), vao(0), vbo(0), vertexLoc(0), colorLoc(0), projectionLoc(0), modelviewLoc(0)
{}

Renderer::~Renderer()
{
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    glDeleteProgram(programID);
    glDeleteShader(vertShaderID);
    glDeleteShader(fragShaderID);
}

void Renderer::init()
{
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_DEPTH);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    setupShaders();

    //glGenVertexArrays(1, vao);
    glGenBuffers(1, &vbo);

    float triangleVertexData[] = {
       0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
      -0.5f,-0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
       0.5f,-0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
    };

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertexData), triangleVertexData, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void Renderer::resize(int w, int h)
{
    glViewport(0, 0, w, h);
    Perspective(projection, 45.0f, (float)w/(float)h, 0.5f, 4.0f);
}

void Renderer::display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glUseProgram(programID);
    glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, projection);
    glUniformMatrix4fv(modelviewLoc, 1, GL_FALSE, modelview);

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glEnableVertexAttribArray(vertexLoc);
    glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), 0);
    glDisableVertexAttribArray(vertexLoc);
    glEnableVertexAttribArray(colorLoc);
    glVertexAttribPointer(colorLoc, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*) (3 * sizeof(float)));
    glDisableVertexAttribArray(colorLoc);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void Renderer::setupShaders()
{
    vertShaderID = glCreateShader(GL_VERTEX_SHADER);
    fragShaderID = glCreateShader(GL_FRAGMENT_SHADER);

    GLint vertlength, fraglength;
    const char* vertexshader = loadShaderSrc("shaders/simple.vert", vertlength);
    const char* fragmentshader = loadShaderSrc("shaders/simple.frag", fraglength);

    glShaderSource(vertShaderID, 1, &vertexshader, &vertlength);
    glShaderSource(fragShaderID, 1, &fragmentshader, &fraglength);

    free((char*) vertexshader);
    free((char*) fragmentshader);

    glCompileShader(vertShaderID);
    glCompileShader(fragShaderID);

    printShaderInfoLog(vertShaderID);
    printShaderInfoLog(fragShaderID);

    programID = glCreateProgram();
    glAttachShader(programID, vertShaderID);
    glAttachShader(programID, fragShaderID);

    glLinkProgram(programID);
    printProgramInfoLog(programID);

    vertexLoc = glGetAttribLocation(programID, "vertex_position");
    colorLoc = glGetAttribLocation(programID, "vertex_color");

    projectionLoc = glGetUniformLocation(programID, "projection");
    modelviewLoc = glGetUniformLocation(programID, "modelview");
}

void printShaderInfoLog(GLint obj)
{
    int infoLogLength = 0;
    int returnLength  = 0;
    char *infoLog;
    glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infoLogLength);
    if (infoLogLength > 0) {
      infoLog = (char *)malloc(infoLogLength);
      glGetShaderInfoLog(obj, infoLogLength, &returnLength, infoLog);
      printf("%s\n",infoLog);
      free(infoLog);
    }   
}

void printProgramInfoLog(GLint obj)
{
    int infoLogLength = 0;
    int returnLength  = 0;
    char *infoLog;
    glGetProgramiv(obj, GL_INFO_LOG_LENGTH,&infoLogLength);
    if (infoLogLength > 0) {
      infoLog = (char *)malloc(infoLogLength);
      glGetProgramInfoLog(obj, infoLogLength, &returnLength, infoLog);
      printf("%s\n",infoLog);
      free(infoLog);
    }
}

const char* loadShaderSrc(const char *filename, GLint &filesize)
{
    std::ifstream file(filename, std::ios::in);
    std::string shader( (std::istreambuf_iterator<char>(file) ),
                        (std::istreambuf_iterator<char>()     ) );
    filesize = (GLint) shader.length();
    return shader.c_str();
}

void Perspective(float *a, float fov, float aspect, float zNear, float zFar)
{
    float f = 1.0f / float(tan(fov / 2.0f * (PI / 180.0f)));
    for(int i = 0; i < 16; i++) a[i] = 0.0f;
    a[0] = f / aspect;
    a[1 * 4 + 1] = f;
    a[2 * 4 + 2] = (zNear + zFar) / (zNear - zFar);
    a[3 * 4 + 2] = 2.0f * zNear * zFar / (zNear - zFar);
    a[2 * 4 + 3] = -1.0f;
}

void Modelview(float *mv)
{
    for(int i = 0; i < 16; i++) mv[i] = 0.0f;
    for(int i = 0; i < 4; i++) mv[i * 4 + i] = 1.0f;
    mv[3 * 4 + 2] = -2.0f;
}

渲染器.h:

#include <cmath>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <GL/glew.h>
#include <GL/glut.h>

#define PI 3.14159

class Renderer {
    private:
        GLuint programID;
        GLuint vertShaderID;
        GLuint fragShaderID;
        GLuint vao;
        GLuint vbo;
        GLint vertexLoc;
        GLint colorLoc;
        GLint projectionLoc;
        GLint modelviewLoc;
        float projection[16];
        float modelview[16];
    public:
        Renderer();
        ~Renderer();
        void init();
        void resize(int w, int h);
        void display();
    private:
        void setupShaders();
        void printShaderInfoLog(GLint obj);
        void printProgramInfoLog(GLint obj);
        const char* loadShaderSrc(const char *filename, GLint &filesize);
        void Perspective(float *a, float fov, float aspect, float zNear, float zFar);
        void Modelview();
};

我使用这个 Makefile 编译(使用 g++ 和 linux):

CC = g++
CFLAGS = -Wall -g
INCLUDES = 
LFLAGS = 
LIBS = -lglut -lGL -lGLEW
SRCS = main.cpp renderer.cpp
OBJS = $(SRCS:.cpp=.o)
MAIN = main

all:        $(MAIN)

$(MAIN):    $(OBJS)
            $(CC) $(CLFAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS)

.cpp.o:     
            $(CC) $(CLFAGS) $(INCLUDES) -c $<  -o $@

clean:      
            $(RM) *.o *~ $(MAIN)

这可能只是一个愚蠢的初学者错误,但我找不到它。如果该函数在同一个文件中定义,我根本不明白如何获得对该函数的未定义引用。

我希望你能帮助我=)

4

1 回答 1

6

在您的cpp文件中,该Perspective函数被调用Perspective而不是Renderer::Perspective. 这意味着该Perspective方法实际上并未定义,即使现在有一个未使用的函数称为Perspective.

注意:您对班级的其他private方法也有同样的问题。Renderer

于 2013-06-30T01:32:42.707 回答