現在、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
これは私のソースファイルです:
main.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;
}
renderer.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;
}
renderer.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 を使用してコンパイルします (Linux で g++ を使用):
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)
それはおそらく愚かな初心者の間違いですが、私はそれを見つけることができません。関数が同じファイルで定義されている場合、関数への未定義の参照を取得する方法がわかりません。
あなたが私を助けてくれることを願っています=)