C++ undefined reference though function is defined in the same file - c++

I'm currently trying to write a OpenGL program in C++. When I try to compile my program I get undefined references, everywhere where i call member functions of my class, although I call these functions from member functions...
These are the error messages I get:
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
This are my source files:
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();
};
I compile using this Makefile (using g++ with 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)
It's probably just a stupid beginner mistake but I cant find it. I simply don't understand how I can get a undefined reference to a function if that function is defined in the same file.
I hope you can help me =)

In your cpp file the Perspective function is called Perspective rather than Renderer::Perspective. This means that the Perspective method is not actually defined, even though there is now an unused function called Perspective.
Note: you have the same issue with other private methods of your Renderer class.

Related

two window share context object, do not work correctly on fedora36

I try to learn OpenGL context object sharing so I write a demo about object sharing:
#include <unistd.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include<iostream>
using namespace std;
const char* vertex_shader_text =
"#version 330 core\n"
"layout(location = 0) in vec2 vPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(vPos, 1, 1);\n"
"}\n";
const char* fragment_shader_text =
"#version 330 core\n"
"uniform vec3 color;\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(color,1.0);\n"
"}\n";
GLuint loadShader(const char* vs, const char* fs) {
const GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vs, NULL);
glCompileShader(vertex_shader);
const GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fs, NULL);
glCompileShader(fragment_shader);
const GLuint programID = glCreateProgram();
glAttachShader(programID, vertex_shader);
glAttachShader(programID, fragment_shader);
glLinkProgram(programID);
return programID;
}
float colors[2][3] = {
{1.0, 1.0, 0.0}, {1.0, 0.0, 1.0}
};
static void key_callback(GLFWwindow* window, int key, int scancode, int action,
int mods) {
if (action == GLFW_PRESS && key == GLFW_KEY_ESCAPE)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
void character_callback(GLFWwindow* window, unsigned int codepoint) {
printf("character_callback: %p, codepoint:%c\n", window,codepoint);
float r[3] = {1.0f, 0.0f, 0.0f};
float g[3] = {0.0f, 1.0f, 0.0f};
float b[3] = {0.0f, 0.0f, 1.0f};
if (codepoint == '1') {
for (int i = 0; i < 3; i++) {
colors[1][i] = r[i];
}
} else if (codepoint == '2') {
for (int i = 0; i < 3; i++) {
colors[1][i] = g[i];
}
}
if (codepoint == '3') {
for (int i = 0; i < 3; i++) {
colors[1][i] = b[i];
}
}
}
int main(int argc, char** argv) {
const char* description;
GLFWwindow* windows[2];
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
{
windows[0] = glfwCreateWindow(300, 300, "window1", NULL, NULL);
glfwSetCharCallback(windows[0], character_callback);
glfwMakeContextCurrent(windows[0]);
gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
}
GLuint vao[2];
glGenVertexArrays(1, &vao[0]);
GLuint vbo;
glGenBuffers(1, &vbo);
const GLfloat vertices[] = {-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f};
const GLuint program = loadShader(vertex_shader_text, fragment_shader_text);
{
glUseProgram(program);
glBindVertexArray(vao[0]);
{
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(0);
}
// glBindVertexArray(0);
}
// window2
{
windows[1] = glfwCreateWindow(300, 300, "window2", nullptr, windows[0]);
glfwSetCharCallback(windows[1], character_callback);
glfwMakeContextCurrent(windows[1]);
{
glUseProgram(program);
glGenVertexArrays(1, &vao[1]);
glBindVertexArray(vao[1]);
{
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(0);
}
// glBindVertexArray(0);
}
}
for (int i = 0; i < 2; i++) {
glfwSetKeyCallback(windows[i], key_callback);
glfwMakeContextCurrent(windows[i]);
glClearColor(colors[0][0], colors[0][1], colors[0][2], 1.0);
for (int k = 0; k < 3; k++) {
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(windows[i]);
}
}
int color_pos = glGetUniformLocation(program, "color");
glfwMakeContextCurrent(0);
// ==========step 2============
while (!glfwWindowShouldClose(windows[0]) &&
!glfwWindowShouldClose(windows[1])) {
for (int i = 0; i < 2; i++) {
glfwPollEvents();
glfwMakeContextCurrent(windows[i]);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao[i]);
glUniform3f(color_pos, colors[1][0], colors[1][1], colors[1][2]); //??? I change two window triangle color, why only one window work when i click the button 1,2,3 ?
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(windows[i]);
glBindVertexArray(0);
glfwMakeContextCurrent(0);
}
}
glfwTerminate();
exit(EXIT_SUCCESS);
}
I expect the each window draw the same triangle with same color, when I click key 1,2 and 3, the two window will change color to red,green and blue at the same time.
It's working on ubuntu20.04, but not working on fedora36, only one window will change the color, the other one do not.
Why does only one window's triangle color change and the another one not?
I try to use gdb to debug the program, but it's seem too difficult to figure out.
My environment is:
jack#fedora
------------
OS: Fedora release 36 (Thirty Six) x86_64
Host: 20FBA05VCD ThinkPad X1 Carbon 4th
Kernel: 5.19.8-200.fc36.x86_64
Uptime: 11 days, 14 hours, 17 mins
Packages: 6001 (rpm), 58 (flatpak), 12 (snap)
Shell: bash 5.1.16
Resolution: 1920x1080
DE: GNOME 42.5
WM: Mutter
WM Theme: Adwaita
Theme: Adwaita [GTK2/3]
Icons: Adwaita [GTK2/3]
Terminal: gnome-terminal
CPU: Intel i5-6200U (4) # 2.800GHz
GPU: Intel Skylake GT2 [HD Graphics 520]
Memory: 6008MiB / 6866MiB

Why don't these GLSL shaders work?

I'm trying to render a spiral as all red using the shaders to override the colours. For some reason they compile and link but do nothing.
See the following code
fragmentshader.glsl
#version 430
out vec4 outColor;
in vec4 color;
void main(){
outColor = color;
}
vertexshader.glsl
#version 430
in layout(location=0) vec2 position;
out vec4 color;
void main(){
gl_Position = vec4(position, 0.0, 1.0);
color = vec4(1.0, 0.0f, 0.0f, 1.0f);
}
Window.cpp
#include <GL\glew.h>
#include <glm\glm.hpp>
#include <glm\gtc\matrix_transform.hpp>
#include "MeGLWindow.h"
#include <iostream>
#include <fstream>
#define Pi 3.14159265358979
#define E 2.718281828F
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
#define MAX_SPIRAL 25000
std::string readFile(const char* relPath);
void installShaders();
bool checkShaderStatus(GLuint shaderID);
bool checkProgramStatus(GLuint programID);
GLuint programID;
void MeGLWindow::initializeGL() {
glewInit();
glEnable(GL_DEPTH_TEST);
installShaders();
const int verts_num = MAX_SPIRAL * 2;
GLfloat verts[50000];
GLuint myBufferID;
float a = 0.06f;
float b = 0.06f;
float cx = 0.0;
float cy = 0.0;
int z = 0;
for (int i = 0; i < MAX_SPIRAL; i++) {
float ang = (Pi / 720) * i;
float factor = pow(E, b * ang);
float x = cx + (a * (cos(ang)) * factor);
float y = cy - (a * (sin(ang)) * factor);
verts[2 * i] = x;
verts[(2 * i) + 1] = y;
}
glGenBuffers(1, &myBufferID);
glBindBuffer(GL_ARRAY_BUFFER, myBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
}
void MeGLWindow::paintGL() {
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glViewport(0, 0, width(), height());
glDrawArrays(GL_POINTS, 0, 2*25000);
}
void installShaders() {
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
const char* adapter[1];
std::string file = readFile("vertexshader.glsl");
const char* vertexFile = file.c_str();
adapter[0] = vertexFile;
glShaderSource(vertexShaderID, 1, adapter, 0);
file = readFile("fragmentshader.glsl");
const char* fragmentFile = file.c_str();
adapter[0] = fragmentFile;
glShaderSource(fragmentShaderID, 1, adapter, 0);
glCompileShader(vertexShaderID);
glCompileShader(fragmentShaderID);
if (!checkShaderStatus(vertexShaderID) || !checkShaderStatus(fragmentShaderID)) {
return;
}
programID = glCreateProgram();
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
if (!checkProgramStatus(programID)) {
return;
}
glUseProgram(programID);
}
main.cpp
#include <Qt\qapplication.h>
#include "MeGLWindow.h"
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
MeGLWindow meWindow;
meWindow.show();
return app.exec();
}
The vertices in the spiral should be red according to the linked shaders! What am i doing wrong? Please help!
No error checking on the shader program. Or rather, you check for errors, but don't signal the application that the program creation failed in any way.
You don't provide the source for checkProgramStatus, but if you checking for GL_LINK_STATUS, you're doing so before you link the problem.
It's not clear how you're initializing OpenGL from the code provided, but you're not setting a VAO, which is required for the core profile.

GLSL demo failed with Linker Error: failed with code 1

I just download this demo, create a cocoa project, add frameworks OpenGL, GLKit, GLUT, now it can compile, but I got the linker error:
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Any thoughts??
Here is the cpp file I added to the project (and I didn't do anything to the files the project already had, like ViewController.* , AppDelegate.*) :
//
// geometryFeedback.cpp
//
//
#include "stdio.h"
#include <OpenGL/gl3.h>
#include <GLUT/glut.h>
// Shader macro
#define GLSL(src) "#version 400 core\n" #src
// Vertex shader
const GLchar* vertexShaderSrc = GLSL(
in float inValue;
out float geoValue;
void main() {
geoValue = sqrt(inValue);
}
);
// Geometry shader
const GLchar* geoShaderSrc = GLSL(
layout(points) in;
layout(triangle_strip, max_vertices = 3) out;
in float[] geoValue;
out float outValue;
void main() {
for (int i = 0; i < 3; i++) {
outValue = geoValue[0] + i;
EmitVertex();
}
EndPrimitive();
}
);
int main() {
// Window
// Compile shaders
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSrc, nullptr);
glCompileShader(vertexShader);
GLuint geoShader = glCreateShader(GL_GEOMETRY_SHADER);
glShaderSource(geoShader, 1, &geoShaderSrc, nullptr);
glCompileShader(geoShader);
// Create program and specify transform feedback variables
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, geoShader);
const GLchar* feedbackVaryings[] = { "outValue" };
glTransformFeedbackVaryings(program, 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
glLinkProgram(program);
glUseProgram(program);
// Create VAO
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create input VBO and vertex format
GLfloat data[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
GLint inputAttrib = glGetAttribLocation(program, "inValue");
glEnableVertexAttribArray(inputAttrib);
glVertexAttribPointer(inputAttrib, 1, GL_FLOAT, GL_FALSE, 0, 0);
// Create transform feedback buffer
GLuint tbo;
glGenBuffers(1, &tbo);
glBindBuffer(GL_ARRAY_BUFFER, tbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(data) * 3, nullptr, GL_STATIC_READ);
// Perform feedback transform
glEnable(GL_RASTERIZER_DISCARD);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo);
glBeginTransformFeedback(GL_TRIANGLES);
glDrawArrays(GL_POINTS, 0, 5);
glEndTransformFeedback();
glDisable(GL_RASTERIZER_DISCARD);
glFlush();
// Fetch and print results
GLfloat feedback[15];
glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(feedback), feedback);
for (int i = 0; i < 15; i++) {
printf("%f\n", feedback[i]);
}
return 0;
}
The Linker Information:
Ld /Users/WY/Library/Developer/Xcode/DerivedData/TransformFeedback-apcdjlohrayxsdeuvwzbzxatazbc/Build/Products/Debug/TransformFeedback.app/Contents/MacOS/TransformFeedback normal x86_64
cd /Users/WY/Documents/3DPrinting/code/TransformFeedback
export MACOSX_DEPLOYMENT_TARGET=10.11
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -L/Users/WY/Library/Developer/Xcode/DerivedData/TransformFeedback-apcdjlohrayxsdeuvwzbzxatazbc/Build/Products/Debug -F/Users/WY/Library/Developer/Xcode/DerivedData/TransformFeedback-apcdjlohrayxsdeuvwzbzxatazbc/Build/Products/Debug -filelist /Users/WY/Library/Developer/Xcode/DerivedData/TransformFeedback-apcdjlohrayxsdeuvwzbzxatazbc/Build/Intermediates/TransformFeedback.build/Debug/TransformFeedback.build/Objects-normal/x86_64/TransformFeedback.LinkFileList -Xlinker -rpath -Xlinker #executable_path/../Frameworks -mmacosx-version-min=10.11 -fobjc-arc -fobjc-link-runtime -stdlib=libc++ -framework GLKit -framework QTKit -framework OpenGL -framework GLUT -framework Cocoa -Xlinker -dependency_info -Xlinker
/Users/WY/Library/Developer/Xcode/DerivedData/TransformFeedback-apcdjlohrayxsdeuvwzbzxatazbc/Build/Intermediates/TransformFeedback.build/Debug/TransformFeedback.build/Objects-normal/x86_64/TransformFeedback_dependency_info.dat -o /Users/WY/Library/Developer/Xcode/DerivedData/TransformFeedback-apcdjlohrayxsdeuvwzbzxatazbc/Build/Products/Debug/TransformFeedback.app/Contents/MacOS/TransformFeedback
duplicate symbol _main in:
/Users/WY/Library/Developer/Xcode/DerivedData/TransformFeedback-apcdjlohrayxsdeuvwzbzxatazbc/Build/Intermediates/TransformFeedback.build/Debug/TransformFeedback.build/Objects-normal/x86_64/geometryFeedback.o
/Users/WY/Library/Developer/Xcode/DerivedData/TransformFeedback-apcdjlohrayxsdeuvwzbzxatazbc/Build/Intermediates/TransformFeedback.build/Debug/TransformFeedback.build/Objects-normal/x86_64/main.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Issue with time variable conflict in OpenGL 4.3 program Ubuntu 14.04 x64

So I am getting a strange error when compiling an OpenGL 4.3 program and was hoping someone could help. I have been working on one of the recipes in the OpenGL Development Cookbook for a RippleDeformer. I am running into a compile error and am not sure how to fix it.
It seems like there is a variable in the main.cpp program named time and also one of the OpenGL libraries also involves the time.h header, so that causes a problem with the declaration. I tried to change the name of the variable in the program and it compiles, but it gives me a different error when I run the executable.
I tried to compile using the following commands:
g++ -o mycc main.cpp GLSLShader.cpp -lglut -lGLEW -lGL -lm -lglm
So let me give you the message and then the actual main.cpp and shader program:
Error Message
^
main.cpp: At global scope:
main.cpp:62:7: error: ‘float time’ redeclared as different kind of symbol
float time = 0;
^
In file included from /usr/include/pthread.h:24:0,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/gthr-default.h:35,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/gthr.h:148,
from /usr/include/c++/4.8/ext/atomicity.h:35,
from /usr/include/c++/4.8/bits/ios_base.h:39,
from /usr/include/c++/4.8/ios:42,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from main.cpp:3:
/usr/include/time.h:192:15: error: previous declaration of ‘time_t time(time_t*)’
extern time_t time (time_t *__timer) __THROW;
^
main.cpp: In function ‘void OnRender()’:
main.cpp:198:7: error: assignment of function ‘time_t time(time_t*)’
time = glutGet(GLUT_ELAPSED_TIME)/1000.0f * SPEED;
^
main.cpp:198:7: error: cannot convert ‘float’ to ‘time_t(time_t*)throw () {aka long int(long int*)throw
()}’ in assignment
main.cpp:213:35: error: cannot convert ‘time_t (*)(time_t*)throw () {aka long int (*)(long int*)throw ()}’ to ‘GLfloat {aka float}’ in argument passing
glUniform1f(shader("time"), time);
^
main.cpp
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "GLSLShader.h"
#define GL_CHECK_ERRORS assert(glGetError()== GL_NO_ERROR);
#ifdef _DEBUG
#pragma comment(lib, "glew_static_x86_d.lib")
#pragma comment(lib, "freeglut_static_x86_d.lib")
#pragma comment(lib, "SOIL_static_x86_d.lib")
#else
#pragma comment(lib, "glew_static_x86.lib")
#pragma comment(lib, "freeglut_static_x86.lib")
#pragma comment(lib, "SOIL_static_x86.lib")
#endif
using namespace std;
//screen size
const int WIDTH = 1280;
const int HEIGHT = 960;
//shader reference
GLSLShader shader;
//vertex array and vertex buffer object IDs
GLuint vaoID;
GLuint vboVerticesID;
GLuint vboIndicesID;
const int NUM_X = 40; //total quads on X axis
const int NUM_Z = 40; //total quads on Z axis
const float SIZE_X = 4; //size of plane in world space
const float SIZE_Z = 4;
const float HALF_SIZE_X = SIZE_X/2.0f;
const float HALF_SIZE_Z = SIZE_Z/2.0f;
//ripple displacement speed
const float SPEED = 2;
//ripple mesh vertices and indices
glm::vec3 vertices[(NUM_X+1)*(NUM_Z+1)];
const int TOTAL_INDICES = NUM_X*NUM_Z*2*3;
GLushort indices[TOTAL_INDICES];
//projection and modelview matrices
glm::mat4 P = glm::mat4(1);
glm::mat4 MV = glm::mat4(1);
//camera transformation variables
int state = 0, oldX=0, oldY=0;
float rX=25, rY=-40, dist = -7;
//current time
float time = 0;
//mouse click handler
void OnMouseDown(int button, int s, int x, int y)
{
if (s == GLUT_DOWN)
{
oldX = x;
oldY = y;
}
if(button == GLUT_MIDDLE_BUTTON)
state = 0;
else
state = 1;
}
//mosue move handler
void OnMouseMove(int x, int y)
{
if (state == 0)
dist *= (1 + (y - oldY)/60.0f);
else
{
rY += (x - oldX)/5.0f;
rX += (y - oldY)/5.0f;
}
oldX = x;
oldY = y;
glutPostRedisplay();
}
//OpenGL initialization
void OnInit() {
//set the polygon mode to render lines
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
GL_CHECK_ERRORS
//load shader
shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert");
shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/shader.frag");
//compile and link shader
shader.CreateAndLinkProgram();
shader.Use();
//add shader attribute and uniforms
shader.AddAttribute("vVertex");
shader.AddUniform("MVP");
shader.AddUniform("time");
shader.UnUse();
GL_CHECK_ERRORS
//setup plane geometry
//setup plane vertices
int count = 0;
int i=0, j=0;
for( j=0;j<=NUM_Z;j++) {
for( i=0;i<=NUM_X;i++) {
vertices[count++] = glm::vec3( ((float(i)/(NUM_X-1)) *2-1)* HALF_SIZE_X, 0, ((float(j)/(NUM_Z-1))*2-1)*HALF_SIZE_Z);
}
}
//fill plane indices array
GLushort* id=&indices[0];
for (i = 0; i < NUM_Z; i++) {
for (j = 0; j < NUM_X; j++) {
int i0 = i * (NUM_X+1) + j;
int i1 = i0 + 1;
int i2 = i0 + (NUM_X+1);
int i3 = i2 + 1;
if ((j+i)%2) {
*id++ = i0; *id++ = i2; *id++ = i1;
*id++ = i1; *id++ = i2; *id++ = i3;
} else {
*id++ = i0; *id++ = i2; *id++ = i3;
*id++ = i0; *id++ = i3; *id++ = i1;
}
}
}
GL_CHECK_ERRORS
//setup plane vao and vbo stuff
glGenVertexArrays(1, &vaoID);
glGenBuffers(1, &vboVerticesID);
glGenBuffers(1, &vboIndicesID);
glBindVertexArray(vaoID);
glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID);
//pass plane vertices to array buffer object
glBufferData (GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW);
GL_CHECK_ERRORS
//enable vertex attrib array for position
glEnableVertexAttribArray(shader["vVertex"]);
glVertexAttribPointer(shader["vVertex"], 3, GL_FLOAT, GL_FALSE,0,0);
GL_CHECK_ERRORS
//pass the plane indices to element array buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices[0], GL_STATIC_DRAW);
GL_CHECK_ERRORS
cout<<"Initialization successfull"<<endl;
}
//release all allocated resources
void OnShutdown() {
//Destroy shader
shader.DeleteShaderProgram();
//Destroy vao and vbo
glDeleteBuffers(1, &vboVerticesID);
glDeleteBuffers(1, &vboIndicesID);
glDeleteVertexArrays(1, &vaoID);
cout<<"Shutdown successfull"<<endl;
}
//resize event handler
void OnResize(int w, int h) {
//set the viewport size
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
//setup the projection matrix
P = glm::perspective(45.0f, (GLfloat)w/h, 1.f, 1000.f);
}
//idle event callback
void OnIdle() {
glutPostRedisplay();
}
//display callback
void OnRender() {
//get the elapse time
time = glutGet(GLUT_ELAPSED_TIME)/1000.0f * SPEED;
//clear the colour and depth buffers
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//set teh camera viewing transformation
glm::mat4 T = glm::translate(glm::mat4(1.0f),glm::vec3(0.0f, 0.0f, dist));
glm::mat4 Rx = glm::rotate(T, rX, glm::vec3(1.0f, 0.0f, 0.0f));
glm::mat4 MV = glm::rotate(Rx, rY, glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 MVP = P*MV;
//bind the shader
shader.Use();
//set the shader uniforms
glUniformMatrix4fv(shader("MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
glUniform1f(shader("time"), time);
//draw the mesh triangles
glDrawElements(GL_TRIANGLES, TOTAL_INDICES, GL_UNSIGNED_SHORT, 0);
//unbind the shader
shader.UnUse();
//swap front and back buffers to show the rendered result
glutSwapBuffers();
}
int main(int argc, char** argv) {
//freeglut initialization calls
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitContextVersion (3, 3);
glutInitContextFlags (GLUT_CORE_PROFILE | GLUT_DEBUG);
glutInitWindowSize(WIDTH, HEIGHT);
glutCreateWindow("Ripple deformer - OpenGL 3.3");
//glew initialization
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err) {
cerr<<"Error: "<<glewGetErrorString(err)<<endl;
} else {
if (GLEW_VERSION_3_3)
{
cout<<"Driver supports OpenGL 3.3\nDetails:"<<endl;
}
}
err = glGetError(); //this is to ignore INVALID ENUM error 1282
GL_CHECK_ERRORS
//print information on screen
cout<<"\tUsing GLEW "<<glewGetString(GLEW_VERSION)<<endl;
cout<<"\tVendor: "<<glGetString (GL_VENDOR)<<endl;
cout<<"\tRenderer: "<<glGetString (GL_RENDERER)<<endl;
cout<<"\tVersion: "<<glGetString (GL_VERSION)<<endl;
cout<<"\tGLSL: "<<glGetString (GL_SHADING_LANGUAGE_VERSION)<<endl;
GL_CHECK_ERRORS
//opengl initialization
OnInit();
//callback hooks
glutCloseFunc(OnShutdown);
glutDisplayFunc(OnRender);
glutReshapeFunc(OnResize);
glutMouseFunc(OnMouseDown);
glutMotionFunc(OnMouseMove);
glutIdleFunc(OnIdle);
//main loop call
glutMainLoop();
return 0;
}
And finally the shader code:
GLSLShader.cpp
#include "GLSLShader.h"
#include <iostream>
GLSLShader::GLSLShader(void)
{
_totalShaders=0;
_shaders[VERTEX_SHADER]=0;
_shaders[FRAGMENT_SHADER]=0;
_shaders[GEOMETRY_SHADER]=0;
_attributeList.clear();
_uniformLocationList.clear();
}
GLSLShader::~GLSLShader(void)
{
_attributeList.clear();
_uniformLocationList.clear();
}
void GLSLShader::DeleteShaderProgram() {
glDeleteProgram(_program);
}
void GLSLShader::LoadFromString(GLenum type, const string& source) {
GLuint shader = glCreateShader (type);
const char * ptmp = source.c_str();
glShaderSource (shader, 1, &ptmp, NULL);
//check whether the shader loads fine
GLint status;
glCompileShader (shader);
glGetShaderiv (shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
GLint infoLogLength;
glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *infoLog= new GLchar[infoLogLength];
glGetShaderInfoLog (shader, infoLogLength, NULL, infoLog);
cerr<<"Compile log: "<<infoLog<<endl;
delete [] infoLog;
}
_shaders[_totalShaders++]=shader;
}
void GLSLShader::CreateAndLinkProgram() {
_program = glCreateProgram ();
if (_shaders[VERTEX_SHADER] != 0) {
glAttachShader (_program, _shaders[VERTEX_SHADER]);
}
if (_shaders[FRAGMENT_SHADER] != 0) {
glAttachShader (_program, _shaders[FRAGMENT_SHADER]);
}
if (_shaders[GEOMETRY_SHADER] != 0) {
glAttachShader (_program, _shaders[GEOMETRY_SHADER]);
}
//link and check whether the program links fine
GLint status;
glLinkProgram (_program);
glGetProgramiv (_program, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
GLint infoLogLength;
glGetProgramiv (_program, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *infoLog= new GLchar[infoLogLength];
glGetProgramInfoLog (_program, infoLogLength, NULL, infoLog);
cerr<<"Link log: "<<infoLog<<endl;
delete [] infoLog;
}
glDeleteShader(_shaders[VERTEX_SHADER]);
glDeleteShader(_shaders[FRAGMENT_SHADER]);
glDeleteShader(_shaders[GEOMETRY_SHADER]);
}
void GLSLShader::Use() {
glUseProgram(_program);
}
void GLSLShader::UnUse() {
glUseProgram(0);
}
void GLSLShader::AddAttribute(const string& attribute) {
_attributeList[attribute]= glGetAttribLocation(_program, attribute.c_str());
}
//An indexer that returns the location of the attribute
GLuint GLSLShader::operator [](const string& attribute) {
return _attributeList[attribute];
}
void GLSLShader::AddUniform(const string& uniform) {
_uniformLocationList[uniform] = glGetUniformLocation(_program, uniform.c_str());
}
GLuint GLSLShader::operator()(const string& uniform){
return _uniformLocationList[uniform];
}
#include <fstream>
void GLSLShader::LoadFromFile(GLenum whichShader, const string& filename){
ifstream fp;
fp.open(filename.c_str(), ios_base::in);
if(fp) {
string line, buffer;
while(getline(fp, line)) {
buffer.append(line);
buffer.append("\r\n");
}
//copy to source
LoadFromString(whichShader, buffer);
} else {
cerr<<"Error loading shader: "<<filename<<endl;
}
}
Debug 1 [RESOLVED]
Ahh, so I did what #KimKulling suggested and made the variable into elapsedTime instead of just time. So the file does compile to an executable mycc, but when I run it I get the following error:
Inconsistency detected by ld.so: dl-version.c: 224: _dl_check_map_versions: Assertion `needed != ((void *)0)' failed!
The line that it points to: 224 is just the first line of the main function int main() . . ..
I worked on it some more and discovered this issue has to do with an existing bug associated with dynamic library inconsistencies with OpenGL/C++. There is an existing bug filed on this issue.
https://bugs.launchpad.net/ubuntu/+source/nvidia-graphics-drivers-319/+bug/1248642
The good news is that someone found a workaround.
error running a compiled C++ file (uses OpenGL). Error: “Inconsistency detected by ld.so: dl-version.c: 224”
All I had to do was use different compile settings. It was really not intuitive.
I had to add a directory link to the video driver. Here is what worked:
g++ -L/usr/lib/nvidia-340/ main.cpp GLSLShader.cpp -lglut -lGLEW -lGL
The compiler seems to be right. There is already a symbol named time, so you have to change the name for something like
float elapsedTime = 0.0f;
When other errors occurres afterwards you have to fix them as well of course. But I thing the reason for them are a little bit different, so try to investigate the reasons and fix them step by step.
Maybe posting the next error could be a beginning :-).

BillBoarding Implementation

I am trying to implement soft particles in my projects.
Everything is fine , I implement the texture also. But when the mouse is moved to a certain angle,
the particles get distorted. The particle is generated in view space.
So, I would like to know how could I implement the billboard in my project so that every particles seem uniform.Here is my code:
bool CETSmokeRenderer::InitBuffers()
{
size_t vertexSize = 3 * 4 * m_NumVertex * sizeof(float);
size_t colorSize = 4 * 4 * m_NumVertex * sizeof(float);
size_t texCoordSize = 2 * 4 * m_NumVertex * sizeof(float);
if(!vertexBuffer)
{
glDeleteBuffersARB(1, &vertexBuffer);
glDeleteBuffersARB(1, &colorBuffer);
glDeleteBuffersARB(1, &texCoordBuffer);
}
glGenBuffersARB(1, &vertexBuffer);
glGenBuffersARB(1, &colorBuffer);
glGenBuffersARB(1, &texCoordBuffer);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexSize, NULL, GL_STREAM_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, colorBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, colorSize, NULL, GL_STREAM_DRAW_ARB);
// Creates the static texture data
size_t len = 2 * 4 * m_NumVertex;
if(0 > m_NumVertex)
{
return false;
}
else if(0 == m_NumVertex)
{
return true;
}
float *texCoords = new float[len];
{
size_t i = 0;
while(i < len)
{
// u v
texCoords[i++] = 0.0f; texCoords[i++] = 0.0f;
texCoords[i++] = 1.0f; texCoords[i++] = 0.0f;
texCoords[i++] = 1.0f; texCoords[i++] = 1.0f;
texCoords[i++] = 0.0f; texCoords[i++] = 1.0f;
}
}
glBindBufferARB(GL_ARRAY_BUFFER_ARB, texCoordBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, texCoordSize, (void*)texCoords, GL_STATIC_DRAW_ARB);
delete texCoords;
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
return 0;
}
void CETSmokeRenderer::Draw(Camera &cam, bool useTex)
{
if(useTex)
glBindTexture(GL_TEXTURE_2D, texID);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
mBaseView->SetupViewingTransform();
size_t len = particleStore.size();
std::vector<SimpleSmokeParticle> toDraw;
for(size_t i = 0; i < len; i++)
{
SimpleSmokeParticle sp;
sp.transP = particleStore[i].p;
sp.index = i;
toDraw.push_back(sp);
}
//std::sort(toDraw.begin(), toDraw.end(), ParticleCmp);
#ifdef USE_VBO
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, 3 * 4 * m_NumVertex * sizeof(float), NULL, GL_STREAM_DRAW_ARB);
float *vertexPtr = (float*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
assert(vertexPtr);
for(size_t i = 0, count = 0; count < len; count++)
{
SmokeParticle &prt = particleStore[ toDraw[count].index ];
Point3f &p = toDraw[count].transP;
float w = prt.w / 0.5f;
float h = prt.h / 1.0f;
vertexPtr[i++] = p.x - w; vertexPtr[i++] = p.y - h; vertexPtr[i++] = p.z;
vertexPtr[i++] = p.x + w; vertexPtr[i++] = p.y - h; vertexPtr[i++] = p.z;
vertexPtr[i++] = p.x + w; vertexPtr[i++] = p.y + h; vertexPtr[i++] = p.z;
vertexPtr[i++] = p.x - w; vertexPtr[i++] = p.y + h; vertexPtr[i++] = p.z;
}
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, colorBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, 4 * 4 * m_NumVertex * sizeof(float), NULL, GL_STREAM_DRAW_ARB);
float *colorPtr = (float*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
assert(colorBuffer);
for(size_t i = 0, count = 0; count < len; count++)
{
SmokeParticle &prt = particleStore[ toDraw[count].index ];
// r g b a
colorPtr[i++] = prt.r; colorPtr[i++] = prt.g; colorPtr[i++] = prt.b; colorPtr[i++] = prt.alpha;
colorPtr[i++] = prt.r; colorPtr[i++] = prt.g; colorPtr[i++] = prt.b; colorPtr[i++] = prt.alpha;
colorPtr[i++] = prt.r; colorPtr[i++] = prt.g; colorPtr[i++] = prt.b; colorPtr[i++] = prt.alpha;
colorPtr[i++] = prt.r; colorPtr[i++] = prt.g; colorPtr[i++] = prt.b; colorPtr[i++] = prt.alpha;
}
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
// Draws buffered data
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, colorBuffer);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_FLOAT, 0, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, texCoordBuffer);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glDrawArrays(GL_QUADS, 0, (GLsizei)len *4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
#else
{..}
glPopMatrix();
}
void CETSmokeRenderer::Render()
{
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Renders depth information
if(useSoftParticles)
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_FALSE);
glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, GL_FALSE);
glClampColorARB(GL_CLAMP_READ_COLOR_ARB, GL_FALSE);
glClearColor(FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX);
glClear(GL_COLOR_BUFFER_BIT);;
glUseProgramObjectARB(0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_TRUE);
glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, GL_TRUE);
glClampColorARB(GL_CLAMP_READ_COLOR_ARB, GL_TRUE);
glBindTexture(GL_TEXTURE_2D, 0);
// renders the soft particles
glUseProgramObjectARB(particleShader);
// Sets texture data
GLint texloc = glGetUniformLocationARB(particleShader, "tex");
GLint depthTexloc = glGetUniformLocationARB(particleShader, "depthInfo");
GLint powerloc = glGetUniformLocationARB(particleShader, "power");
glUniform1fARB(powerloc, (float)softParticlePower);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, TextureID());
glUniform1iARB(texloc, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, depthTex);
glUniform1iARB(depthTexloc, 1);
Draw(m_pCamera, false);
// Unbinds shader and textures
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgramObjectARB(0);
}
else
{
glUseProgramObjectARB(particleShader);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, TextureID());
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, depthTex);
Draw(m_pCamera, true);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgramObjectARB(0);
}
}
One way of achieving what you are looking for is to utilise point sprites, I have attached some code below that illustrates this in a simple way, hope this helps:
main.cpp
/*
Simple point-sprite particle demo - renders particles using spheres
Requirements:
GLM maths library
Freeglut
*/
#include <gl/glew.h>
#include <gl/freeglut.h>
#include <iostream>
#include "GLSLShader.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_projection.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <cassert>
#define GL_CHECK_ERRORS assert(glGetError()== GL_NO_ERROR)
using namespace std;
class Screen
{
public:
int width, height;
string title;
unsigned int displayFlags, contextFlags;
Screen(string ititle, int iwidth = 1024, int iheight = 768){
Screen(ititle, (GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA), (GLUT_CORE_PROFILE | GLUT_DEBUG), iwidth, iheight)
}
Screen(string ititle, unsigned int disFlags, unsigned int contFlags, int iwidth = 1024, int iheight = 768){
title = ititle; width = iwidth; height = iheight;
displayFlags = disFlags;
contextFlags = contFlags;
}
};
const int TOTAL= 9;
GLfloat positions[3*TOTAL]={-1,0,-1, 0,0,-1, 1,0,-1,-1,0, 0, 0,0, 0, 1,0, 0,-1,0, 1, 0,0, 1, 1,0,1};
GLuint vboID, vaoID;
GLsizei stride = sizeof(GLfloat)*3;
GLSLShader shader;
int filling=1;
// Absolute rotation values (0-359 degrees) and rotiation increments for each frame
float rotation_x=0, rotation_x_increment=0.1f;
float rotation_y=0, rotation_y_increment=0.05f;
float rotation_z=0, rotation_z_increment=0.03f;
glm::mat4 P; //projection matrix;
bool bRotate=true;
void InitShaders(void)
{
shader.LoadFromFile(GL_VERTEX_SHADER, "shader.vert");
shader.LoadFromFile(GL_FRAGMENT_SHADER, "shader.frag");
shader.CreateAndLinkProgram();
shader.Use();
shader.AddAttribute("vVertex");
shader.AddUniform("Color");
shader.AddUniform("lightDir");
shader.AddUniform("MVP");
glUniform3f(shader("lightDir"), 0,0,1);
glUniform3f(shader("Color"),1,0,0);
shader.UnUse();
GL_CHECK_ERRORS;
}
void InitVAO() {
GL_CHECK_ERRORS;
//Create vao and vbo stuff
glGenVertexArrays(1, &vaoID);
glGenBuffers (1, &vboID);
GL_CHECK_ERRORS;
glBindVertexArray(vaoID);
glBindBuffer (GL_ARRAY_BUFFER, vboID);
glBufferData (GL_ARRAY_BUFFER, sizeof(positions), &positions[0], GL_STATIC_DRAW);
GL_CHECK_ERRORS;
glEnableVertexAttribArray(shader["vVertex"]);
glVertexAttribPointer (shader["vVertex"], 3, GL_FLOAT, GL_FALSE,stride,0);
glBindVertexArray(0);
GL_CHECK_ERRORS;
}
void SetupGLBase() {
glGetError();
GL_CHECK_ERRORS;
glClearColor(0.0f,0.0f,0.2f,0.0f);
GL_CHECK_ERRORS;
InitShaders();
InitVAO();
glEnable(GL_DEPTH_TEST); // We enable the depth test (also called z buffer)
GL_CHECK_ERRORS;
glPointSize(50);
}
void OnRender() {
GL_CHECK_ERRORS;
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
//setup matrices
glm::mat4 T = glm::translate(glm::mat4(1.0f),glm::vec3(0.0f, 0.0f, -5));
glm::mat4 Rx = glm::rotate(T, rotation_x, glm::vec3(1.0f, 0.0f, 0.0f));
glm::mat4 Ry = glm::rotate(Rx, rotation_y, glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 MV = glm::rotate(Ry, rotation_z, glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 MVP = P*MV;
//draw the points
shader.Use();
glUniformMatrix4fv(shader("MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
glBindVertexArray(vaoID);
glDrawArrays(GL_POINTS, 0, TOTAL);
glBindVertexArray(0);
shader.UnUse();
glutSwapBuffers();
}
void OnResize(int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
//setup the projection matrix
P = glm::perspective(45.0f, (GLfloat)w/h, 1.f, 1000.f);
}
void OnShutdown() {
glDeleteBuffers(1, &vboID);
glDeleteVertexArrays(1, &vaoID);
}
void OnKey(unsigned char key, int x, int y)
{
switch (key)
{
case ' ': bRotate=!bRotate; break;
case 'r': case 'R':
if (filling==0)
{
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); // Filled Polygon Mode
filling=1;
}
else
{
glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); // Outline Polygon Mode
filling=0;
}
break;
}
}
void OnSpecialKey(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_UP: rotation_x_increment = rotation_x_increment +0.005f; break;
case GLUT_KEY_DOWN: rotation_x_increment = rotation_x_increment -0.005f; break;
case GLUT_KEY_LEFT: rotation_y_increment = rotation_y_increment +0.005f; break;
case GLUT_KEY_RIGHT: rotation_y_increment = rotation_y_increment -0.005f; break;
}
}
void OnIdle() {
if(bRotate) {
rotation_x = rotation_x + rotation_x_increment;
rotation_y = rotation_y + rotation_y_increment;
rotation_z = rotation_z + rotation_z_increment;
}
if (rotation_x > 359) rotation_x = 0;
if (rotation_y > 359) rotation_y = 0;
if (rotation_z > 359) rotation_z = 0;
glutPostRedisplay();
}
void glTestAndInfo(GLEnum glewInitResponse)
{
if (GLEW_OK != glewInitResponse) {
cerr<<"Error: "<<glewGetErrorString(glewInitResponse)<<endl;
} else {
if (GLEW_VERSION_3_3)
{
cout<<"Driver supports OpenGL 3.3 or greater.\nDetails:"<<endl;
}
}
cout<<"Using GLEW "<<glewGetString(GLEW_VERSION)<<endl;
cout<<"Vendor: "<<glGetString (GL_VENDOR)<<endl;
cout<<"Renderer: "<<glGetString (GL_RENDERER)<<endl;
cout<<"Version: "<<glGetString (GL_VERSION)<<endl;
cout<<"GLSL: "<<glGetString (GL_SHADING_LANGUAGE_VERSION)<<endl;
}
void main(int argc, char** argv) {
Screen *screen = news Screen("Point sprites as spheres in OpenGL 3.3");
atexit(OnShutdown);
glutInit(&argc, argv);
glutInitDisplayMode(screen->displayFlags);
glutInitContextVersion (3, 3);
glutInitContextFlags (screen->contextFlags);
glutInitWindowSize(screen->width, screen->height);
glutCreateWindow(screen->title);
glewExperimental = GL_TRUE;
glTestAndInfo(glewInit());
SetupGLBase();
glutDisplayFunc(OnRender);
glutReshapeFunc(OnResize);
glutKeyboardFunc(OnKey);
glutSpecialFunc(OnSpecialKey);
glutIdleFunc(OnIdle);
glutMainLoop();
}
GLSLShader.h
#pragma once
#ifndef GLSL_SHADER_H
#define GLSL_SHADER_H
#include <GL/glew.h>
#include <map>
#include <string>
using namespace std;
class GLSLShader
{
public:
GLSLShader(void);
~GLSLShader(void);
void LoadFromString(GLenum whichShader, const string source);
void LoadFromFile(GLenum whichShader, const string filename);
void CreateAndLinkProgram();
void Use();
void UnUse();
void AddAttribute(const string attribute);
void AddUniform(const string uniform);
GLuint operator[](const string attribute);// indexer: returns the location of the named attribute
GLuint operator()(const string uniform);
private:
enum ShaderType {VERTEX_SHADER, FRAGMENT_SHADER, GEOMETRY_SHADER};
GLuint _program;
int _totalShaders;
GLuint _shaders[3];//0 vertexshader, 1 fragmentshader, 2 geometryshader
map<string,GLuint> _attributeList;
map<string,GLuint> _uniformLocationList;
};
#endif
GLSLShader.cpp
/*
Really basic glsl shader class
*/
#include "GLSLShader.h"
#include <iostream>
#include <fstream>
// constructor
GLSLShader::GLSLShader(void)
{
_totalShaders=0;
_shaders[VERTEX_SHADER]=0;
_shaders[FRAGMENT_SHADER]=0;
_shaders[GEOMETRY_SHADER]=0;
_attributeList.clear();
_uniformLocationList.clear();
}
// destructor
GLSLShader::~GLSLShader(void)
{
_attributeList.clear();
_uniformLocationList.clear();
glDeleteProgram(_program);
}
// loader functions
void GLSLShader::LoadFromString(GLenum type, const string source) {
GLuint shader = glCreateShader (type);
const char * ptmp = source.c_str();
glShaderSource (shader, 1, &ptmp, NULL);
//check whether the shader loads fine
GLint status;
glCompileShader (shader);
glGetShaderiv (shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
GLint infoLogLength;
glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *infoLog= new GLchar[infoLogLength];
glGetShaderInfoLog (shader, infoLogLength, NULL, infoLog);
cerr<<"Compile log: "<<infoLog<<endl;
delete [] infoLog;
}
_shaders[_totalShaders++]=shader;
}
void GLSLShader::LoadFromFile(GLenum whichShader, const string filename){
ifstream fp;
fp.open(filename.c_str(), ios_base::in);
if(fp) {
string line, buffer;
while(getline(fp, line)) {
buffer.append(line);
buffer.append("\r\n");
}
//copy to source
LoadFromString(whichShader, buffer);
} else {
cerr<<"Error loading shader: "<<filename<<endl;
}
}
// utilitarian functions
void GLSLShader::CreateAndLinkProgram() {
_program = glCreateProgram ();
if (_shaders[VERTEX_SHADER] != 0) {
glAttachShader (_program, _shaders[VERTEX_SHADER]);
}
if (_shaders[FRAGMENT_SHADER] != 0) {
glAttachShader (_program, _shaders[FRAGMENT_SHADER]);
}
if (_shaders[GEOMETRY_SHADER] != 0) {
glAttachShader (_program, _shaders[GEOMETRY_SHADER]);
}
//link and check whether the program links fine
GLint status;
glLinkProgram (_program);
glGetProgramiv (_program, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
GLint infoLogLength;
glGetProgramiv (_program, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *infoLog= new GLchar[infoLogLength];
glGetProgramInfoLog (_program, infoLogLength, NULL, infoLog);
cerr<<"Link log: "<<infoLog<<endl;
delete [] infoLog;
}
glDeleteShader(_shaders[VERTEX_SHADER]);
glDeleteShader(_shaders[FRAGMENT_SHADER]);
glDeleteShader(_shaders[GEOMETRY_SHADER]);
}
void GLSLShader::Use() {
glUseProgram(_program);
}
void GLSLShader::UnUse() {
glUseProgram(0);
}
void GLSLShader::AddAttribute(const string attribute) {
_attributeList[attribute]= glGetAttribLocation(_program, attribute.c_str());
}
// indexer: returns the location of the named attribute
GLuint GLSLShader::operator [](const string attribute) {
return _attributeList[attribute];
}
void GLSLShader::AddUniform(const string uniform) {
_uniformLocationList[uniform] = glGetUniformLocation(_program, uniform.c_str());
}
GLuint GLSLShader::operator()(const string uniform){
return _uniformLocationList[uniform];
}
This code is pretty old and I have no way to test rendering here (no distinct GFX card) so if there are any issues let me know and I can fix it once at my GFX dev machine.
Addendum:
Shaders may help too (dont know how I forgot them, old age maybe catching up on me!) so here they are:
Vertex shader (shader.vert)
#version 330 // set this to whatever minimum version you want to support
in vec3 vVertex;
uniform mat4 MVP;
void main()
{
gl_Position = MVP*vec4(vVertex,1);
}
Fragment shader (shader.frag)
#version 330
out vec4 vFragColour;
uniform vec3 Colour;
uniform vec3 lightDirection;
void main(void)
{
// calculate normal from texture coordinates
vec3 N;
N.xy = gl_PointCoord* 2.0 - vec2(1.0);
float mag = dot(N.xy, N.xy);
if (mag > 1.0) discard; // kill pixels outside the circle we want
N.z = sqrt(1.0-mag); // this might be expensive depending on your hardware
float diffuse = max(0.0, dot(lightDirection, N)); // calculate lighting
vFragColour = vec4(Colour,1) * diffuse;
}
Addendum 2:
To add the freeglut libraries to your build and resolve LNK 1104 errors simply go to *Project >> Properties >> VC++ Directories* and add the directories where your freeglut includes, source libraries and dlls are stored, for example for lib files go to
Add the folders as follows:
DLL Directories: add to Executable Directories
.h file Directories(include folder): add to Include Directories
.cpp file Directories: add to Source Directories
.lib file Directories: add to Library Directories
Hope this helps:)