Type 'GLchar' could not be resolved - c++

I'm using Eclipse, MinGW, and I have compiled freeglut and glew and copied their libraries, DLLs, and header files into the proper locations (MinGW/include/GL, MinGW/lib, Windows/SysWOW64). I have also linked the libraries (freeglut64, opengl32, glew32, glu32) in Eclipse under the MinGW C++ Linker. Here is my code...
--CharGame.cpp--
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include "CharGame.h"
#define WINDOW_TITLE "CharGame"
int CurrentWidth = 800,
CurrentHeight = 600,
WindowHandle = 0;
unsigned FrameCount = 0;
GLuint VertexShaderId,
FragmentShaderId,
ProgramId,
VaoId,
VboId,
ColorBufferId;
int main(int argc, char* argv[]) {
Initialize(argc, argv);
glutMainLoop();
exit(EXIT_SUCCESS);
}
const GLchar* VertexShader =
{
"#version 400\n"\
"layout(location=0) in vec4 in_Position;\n"\
"layout(location=1) in vec4 in_Color;\n"\
"out vec4 ex_Color;\n"\
"void main(void)\n"\
"{\n"\
" gl_Position = in_Position;\n"\
" ex_Color = in_Color;\n"\
"}\n"
};
const GLchar* FragmentShader =
{
"#version 400\n"\
"in vec4 ex_Color;\n"\
"out vec4 out_Color;\n"\
"void main(void)\n"\
"{\n"\
" out_Color = ex_Color;\n"\
"}\n"
};
void Initialize(int argc, char* argv[]) {
glutInit(&argc, argv);
glutInitContextVersion(4, 0);
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
glutInitWindowSize(CurrentWidth, CurrentHeight);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
WindowHandle = glutCreateWindow(WINDOW_TITLE);
if (WindowHandle < 1) {
fprintf(stderr, "Error: Could not create a render window.\n");
exit(EXIT_FAILURE);
}
glutReshapeFunc(Resize);
glutDisplayFunc(Render);
glutIdleFunc(Idle);
glutTimerFunc(0, Timer, 0);
fprintf(stdout, "Info: OpenGL Version: %s\n", glGetString(GL_VERSION));
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
void Resize(int width, int height) {
CurrentHeight = height;
CurrentWidth = width;
glViewport(0, 0, CurrentWidth, CurrentHeight);
}
void Render(void) {
++FrameCount;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
glutSwapBuffers();
glutPostRedisplay();
}
void Idle(void) {
glutPostRedisplay();
}
void Timer(int value) {
if (0 != value) {
char* TempString = (char*) malloc(512 + strlen(WINDOW_TITLE));
sprintf(TempString, "%s: %d Frames Per Second # %d x %d", WINDOW_TITLE, FrameCount*4, CurrentWidth, CurrentHeight);
glutSetWindowTitle(TempString);
free(TempString);
}
FrameCount = 0;
glutTimerFunc(250, Timer, 1);
}
--End CharGame.cpp--
--CharGame.h--
#ifndef CHARGAME_H_
#define CHARGAME_H_
void Initialize(int, char*[]);
void InitWindow(int, char*[]);
void Resize(int,int);
void Render(void);
void Timer(int);
void Idle(void);
#endif
--End CharGame.h--
I believe I have done everything right, however, Eclipse throws the error "Type 'GLchar' could not be resolved" on VertexShader and FragmentShader. Did I make a mistake in my code or miss a required step?

You're not declaring string constants the right way. You don't need curly braces there. And watch out for empty lines betwreen the strings - either remove them (see below) or add the "\" there.
Include the "GL/GL.h" file before "glew.h", this might help also.
Use this with ordinary chars:
const char* VertexShader =
"#version 400\n"\
"layout(location=0) in vec4 in_Position;\n"\
"layout(location=1) in vec4 in_Color;\n"\
"out vec4 ex_Color;\n"\
"void main(void)\n"\
"{\n"\
" gl_Position = in_Position;\n"\
" ex_Color = in_Color;\n"\
"}\n";
const char* FragmentShader =
"#version 400\n"\
"in vec4 ex_Color;\n"\
"out vec4 out_Color;\n"\
"void main(void)\n"\
"{\n"\
" out_Color = ex_Color;\n"\
"}\n";

This is just expanding on my comment on another answer:
const char* VertexShader =
R"(#version 400
layout(location=0) in vec4 in_Position;
layout(location=1) in vec4 in_Color;
out vec4 ex_Color;
void main(void)
{
gl_Position = in_Position;
ex_Color = in_Color;
}
)";

Related

A Simple Gradient Effect

I need to code the fragment shader so that the triangle has a simple gradient effect. That is, so that its transparency decreases from left to right.
I tried this but it fails:
#version 120
uniform float startX = gl_FragCoord.x;
void main(void) {
gl_FragColor[0] = 0.0;
gl_FragColor[1] = 0.0;
gl_FragColor[2] = 1.0;
gl_FragColor[3] = startX / gl_FragCoord.x;
}
The full code:
#include <cstdlib>
#include <iostream>
using namespace std;
#include <GL/glew.h>
#include <SDL.h>
GLuint program;
GLint attribute_coord2d;
bool init_resources(void)
{
GLint compile_ok, link_ok = GL_FALSE;
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
const char* vs_source = R"(
#version 120
attribute vec2 coord2d;
void main(void) {
gl_Position = vec4(coord2d, 0.0, 1.0);
}
)";
glShaderSource(vs, 1, &vs_source, NULL);
glCompileShader(vs);
glGetShaderiv(vs, GL_COMPILE_STATUS, &compile_ok);
if (!compile_ok) {
cerr << "Error in vertex shader" << endl;
return false;
}
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
const char* fs_source = R"(
#version 120
uniform float startX = gl_FragCoord.x;
void main(void) {
gl_FragColor[0] = 0.0;
gl_FragColor[1] = 0.0;
gl_FragColor[2] = 1.0;
gl_FragColor[3] = startX / gl_FragCoord.x;
}
)";
glShaderSource(fs, 1, &fs_source, NULL);
glCompileShader(fs);
glGetShaderiv(fs, GL_COMPILE_STATUS, &compile_ok);
if (!compile_ok) {
cerr << "Error in fragment shader" << endl;
return false;
}
program = glCreateProgram();
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &link_ok);
if (!link_ok) {
cerr << "Error in glLinkProgram" << endl;
return false;
}
const char* attribute_name = "coord2d";
attribute_coord2d = glGetAttribLocation(program, attribute_name);
if (attribute_coord2d == -1) {
cerr << "Could not bind attribute " << attribute_name << endl;
return false;
}
return true;
}
void render(SDL_Window* window)
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
glEnableVertexAttribArray(attribute_coord2d);
GLfloat triangle_vertices[] = {
0.0, 0.8,
-0.8, -0.8,
0.8, -0.8,
};
glVertexAttribPointer(attribute_coord2d, 2, GL_FLOAT, GL_FALSE, 0, triangle_vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(attribute_coord2d);
SDL_GL_SwapWindow(window);
}
void free_resources()
{
glDeleteProgram(program);
}
void mainLoop(SDL_Window* window)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
while (true)
{
SDL_Event ev;
while (SDL_PollEvent(&ev))
{
if (ev.type == SDL_QUIT)
return;
}
render(window);
}
}
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("My First Triangle", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL);
SDL_GL_CreateContext(window);
GLenum glew_status = glewInit();
if (glew_status != GLEW_OK) {
cerr << "Error: glewInit: " << glewGetErrorString(glew_status) << endl;
return EXIT_FAILURE;
}
if (!init_resources())
return EXIT_FAILURE;
mainLoop(window);
free_resources();
return EXIT_SUCCESS;
}
How to do it right?
vYou can not initialize a uniform with gl_FragCoord.x. A uniform initialization is determined at link time.
uniform float startX = gl_FragCoord.x;
uniform float startX;
You have to set the unform with glUniform1f.
gl_FragCoord.xy are not the vertex coordinates. gl_FragCoord.xy are the window coordinate in pixels. You have to divide gl_FragCoord.xy by the size of the viewport:
#version 120
void main(void) {
gl_FragColor = vec4(0.0, 0.0, 0.0, gl_FragCoord.x / 640.0);
}
Or passing coord2d to the fragment shader:
#version 120
attribute vec2 coord2d;
varying vec2 coord;
void main(void) {
coord = coord2d;
gl_Position = vec4(coord2d, 0.0, 1.0);
}
#version 120
varying vec2 coord;
void main(void) {
float alpha = 2.0 / (1.0 - coord.y);
gl_FragColor = vec4(0.0, 0.0, 1.0, alpha);
}
Or use a color attribute:
#version 120
attribute vec2 coord2d;
attribute vec4 attrColor;
varying vec4 color;
void main(void) {
color = attrColor;
gl_Position = vec4(coord2d, 0.0, 1.0);
}
#version 120
varying vec4 color;
void main(void) {
gl_FragColor = color;
}
attribute_color = glGetAttribLocation(program, "attrColor");
GLfloat triangle_colors[] = {
0.0f, 0.0f, 1.0f, 0.5f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f, 1.0f
};
glEnableVertexAttribArray(attribute_color);
glVertexAttribPointer(attribute_color, 4, GL_FLOAT, GL_FALSE, 0, triangle_colors);

How to create QT Window and use pure OpenGL core profile inside?

I don't want to use QOpenGLWidget, because of the old version of OpenGL inside. I don't understand what is the difference between getting QOpengGLFunctions from the context and directly initialization of QOpenGLFunctions_4_5_Core. I see, that I don't get all functions from the context, and don't understand why. So, how to get from the context all functions? For example, glPolygonMode() is inaccessible in QOpenGLFunctions gotten from the context and in QOpenGLExtraFunctions also gotten from the context. Could anybody explain how to use pure modern OpenGL with QT?
This is my code:
openglwidget.cpp
#include "openglwindow.h"
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QOpenGLExtraFunctions>
#include <QOpenGLFunctions_4_5_Core>
#include <QDebug>
#include <QTimer>
#include <sys/time.h>
static const char* vertexShaderSource =
"#version 450 core\n"
"layout (location = 0) in vec3 aPos;\n"
"out vec4 vertexColor;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"vertexColor = vec4(0.5, 0.0, 0.0, 1.0);\n"
"}\0";
/*static const char* fragmentShaderSource =
"#version 450 core\n"
"out vec4 FragColor;\n"
"in vec4 vertexColor;\n"
"void main()\n"
"{\n"
"FragColor = vertexColor;\n"
"}\0";*/
static const char* fragmentShaderSource =
"#version 450 core\n"
"out vec4 FragColor;\n"
"uniform vec4 ourColor;\n"
"void main()\n"
"{\n"
"FragColor = ourColor;\n"
"}\0";
void OpenGLWindow::GenTriangleBuffer()
{
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
this->m_funcs->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
}
void OpenGLWindow::GenRectangleBuffer()
{
float vertices[] = {
0.5f, 0.5f, 0.0f, // top right
0.5f, -0.5f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f // top left
};
unsigned int indices[] = { // note that we start from 0!
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
this->m_funcs->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
this->m_funcs->glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices,
GL_STATIC_DRAW);
}
OpenGLWindow::OpenGLWindow(QScreen* screen)
: QWindow(screen)
{
setSurfaceType(QWindow::OpenGLSurface);
QSurfaceFormat format;
format.setDepthBufferSize( 24 );
format.setMajorVersion(4);
format.setMinorVersion(5);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setSamples(4);
setFormat(format);
create();
// Create an OpenGL context
this->m_context = new QOpenGLContext;
this->m_context->setFormat(format);
this->m_context->create();
// Make the context current on this window
this->m_context->makeCurrent(this);
/*QSet<QByteArray> extensions = m_context->extensions();
//std::sort(extensions);
qDebug() << "Supported extensions (" << extensions.count() <<")";
foreach (const QByteArray &extension, extensions) {
qDebug() << " " << extension;
}*/
// Obtain a functions object and resolve all entry points
// m_funcs is declared as: QOpenGLFunctions_4_5_Core* m_funcs
this->m_funcs = new QOpenGLFunctions_4_5_Core; /*m_context->functions();*/
//this->m_extra_func = m_context->extraFunctions();
this->m_funcs->initializeOpenGLFunctions();
//set window geometry
this->setGeometry(100, 100, 800, 600);
//set OpenGL render size
this->m_funcs->glViewport(this->geometry().x(),
this->geometry().y(),
this->geometry().width(),
this->geometry().height());
qDebug() << "--- Window geometry: {\n" << this->geometry().x() << ", "
<< this->geometry().y() << ", " << this->geometry().width()
<< ", " << this->geometry().height() << "\n\t} ";
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, this->render);
timer->start(500);
//*OPENGL TRINGLE INITIALIZATION*//
unsigned int VBO, vertexShader, fragmentShader, EBO;
this->m_funcs->glGenVertexArrays(1, &VAO);
this->m_funcs->glGenBuffers(1, &VBO);
this->m_funcs->glGenBuffers(1, &EBO);
this->m_funcs->glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
this->m_funcs->glBindVertexArray(VAO);
this->m_funcs->glBindBuffer(GL_ARRAY_BUFFER, VBO);
this->m_funcs->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
GenTriangleBuffer();
vertexShader = this->m_funcs->glCreateShader(GL_VERTEX_SHADER);
this->m_funcs->glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
this->m_funcs->glCompileShader(vertexShader);
int success;
char infoLog[512];
this->m_funcs->glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if(!success)
{
this->m_funcs->glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" <<
infoLog;
}
fragmentShader = this->m_funcs->glCreateShader(GL_FRAGMENT_SHADER);
this->m_funcs->glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
this->m_funcs->glCompileShader(fragmentShader);
this->m_funcs->glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if(!success)
{
this->m_funcs->glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" <<
infoLog;
}
shaderProgram = this->m_funcs->glCreateProgram();
this->m_funcs->glAttachShader(shaderProgram, vertexShader);
this->m_funcs->glAttachShader(shaderProgram, fragmentShader);
this->m_funcs->glLinkProgram(shaderProgram);
this->m_funcs->glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if(!success) {
this->m_funcs->glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" <<
infoLog;
}
this->m_funcs->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float),
(void*)0);
this->m_funcs->glEnableVertexAttribArray(0);
this->m_funcs->glDeleteShader(vertexShader);
this->m_funcs->glDeleteShader(fragmentShader);
}
void OpenGLWindow::resizeEvent(QResizeEvent *)
{
/*qDebug() << "--- Window RESIZED, new geometry: {\n" << this->geometry().x() << ", "
<< this->geometry().y() << ", " << this->geometry().width()
<< ", " << this->geometry().height() << "\n\t} ";*/
if(this->m_funcs)
this->m_funcs->glViewport(0,
0,
this->geometry().width(),
this->geometry().height());
}
void OpenGLWindow::moveEvent(QMoveEvent *)
{
/*qDebug() << "--- Window MOVED, new geometry: {\n" << this->geometry().x() << ", "
<< this->geometry().y() << ", " << this->geometry().width()
<< ", " << this->geometry().height() << "\n\t} ";*/
if(this->m_funcs)
this->m_funcs->glViewport(0,
0,
this->geometry().width(),
this->geometry().height());
}
void OpenGLWindow::render()
{
timeval tim;
gettimeofday(&tim,NULL);
float timeValue = tim.tv_usec;;
float greenValue = (sin(timeValue) / 2.0f) + 0.5f;
int vertexColorLocation = this->m_funcs->glGetUniformLocation(shaderProgram, "ourColor");
this->m_funcs->glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
this->m_funcs->glClear(GL_COLOR_BUFFER_BIT);
this->m_funcs->glUseProgram(shaderProgram);
this->m_funcs->glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);
this->m_funcs->glBindVertexArray(VAO);
this->m_funcs->glDrawArrays(GL_TRIANGLES, 0, 3);
//this->m_funcs->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
this->m_context->swapBuffers(this);
}
void OpenGLWindow::exposeEvent(QExposeEvent *event)
{
if (this->isExposed())
this->render();
}
bool OpenGLWindow::event(QEvent *event)
{
switch (event->type()) {
case QEvent::UpdateRequest:
this->render();
return true;
default:
return QWindow::event(event);
}
}
void OpenGLWindow::keyPressEvent(QKeyEvent *)
{
}
void OpenGLWindow::keyReleaseEvent(QKeyEvent *)
{
}
OpenGLWindow::~OpenGLWindow()
{
}
openglwidget.h
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QWindow>
class QOpenGLFunctions;
class QOpenGLContext;
class QOpenGLExtraFunctions;
class QOpenGLFunctions_4_5_Core;
class OpenGLWindow : public QWindow
{
Q_OBJECT
public:
explicit OpenGLWindow(QScreen *screen = nullptr);
~OpenGLWindow();
public:
virtual void render();
private:
QOpenGLContext* m_context = nullptr;
/*QOpenGLFunctions* m_funcs = nullptr;*/
QOpenGLFunctions_4_5_Core* m_funcs = nullptr;
QOpenGLExtraFunctions* m_extra_func = nullptr;
unsigned int shaderProgram{}, VAO{};
void GenTriangleBuffer();
void GenRectangleBuffer();
protected:
void resizeEvent(QResizeEvent *) override;
void moveEvent(QMoveEvent *) override;
void keyPressEvent(QKeyEvent *) override;
void keyReleaseEvent(QKeyEvent *) override;
void exposeEvent(QExposeEvent *event) override;
bool event(QEvent *event) override;
};
#endif // GLWIDGET_H
main.cpp
#include <QApplication>
#include "openglwindow.h"
#include <QWindow>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
OpenGLWindow w(nullptr);
w.show();
return a.exec();
}
Try to make your OpenGLWindow inherits from
public QOpenGLWidget, protected QOpenGLFunctions
like this:
class OpenGLWindow : public QOpenGLWidget, protected QOpenGLFunctions_4_5_Core { ... };

Syntax error in OpenGl shader that is copied from YouTube

I trying to learn OpenGl and now I wanted to make a simple red triangle on a black background with vertices and shaders. I copied the code from that YouTube video. I've changed a view things. That's my code:
#include "prec.h"
struct Vector2
{
float x, y;
};
struct TrianglePos
{
Vector2 a, b, c;
};
static unsigned int CompileShader(unsigned int type, const std::string& source)
{
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if (!result)
{
int length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
char* message = (char*)alloca(length * sizeof(char));
glGetShaderInfoLog(id, length, &length, message);
std::cout << "Failed to compile shader, message: " << message << std::endl;
glDeleteShader(id);
return 0;
}
return id;
}
static unsigned int createShader(const std::string& vertexShader, const std::string& fragmentShader)
{
unsigned int program = glCreateProgram();
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glValidateProgram(program);
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
int main() {
if (!glfwInit())
return -1;
GLFWwindow *window = glfwCreateWindow(640, 480, "Sand Box GL", NULL, NULL);
if (!window) {
std::cout << "problems with window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (GLEW_OK != glewInit()) {
std::cout << "something with glew went wrong" << std::endl;
return -1;
}
TrianglePos trianglePos = {
-0.5f, -0.5f,
0.0f, 0.5f,
0.5f, -0.5f
};
unsigned int buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(trianglePos), &trianglePos, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), 0);
std::string vertexShader =
"#version 400 core\n"
"\n"
"layout(location = 0) in vec4 position;\n"
"\n"
"void main() \n"
"{\n"
" gl_Position = position;\n"
"}\n";
std::string fragmentShader =
"#version 400 core\n"
"\n"
"layout(location = 0) out vec4 color;\n"
"\n"
"void main()\n"
"{\n"
" color = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n";
const char *versionGL;
versionGL = (char *) (glGetString(GL_VERSION));
std::cout << "openGl version: " << versionGL << std::endl;
if(GL_VERSION_4_0)
std::cout << "opengl 4.0 supported" << std::endl;
unsigned int shader = createShader(vertexShader, fragmentShader);
glUseProgram(shader);
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
and that's the precompiled header (prec.h): #pragma once
#ifndef GLEWINIT_PREC_H
#define GLEWINIT_PREC_H
#endif //GLEWINIT_PREC_H
#include "GL/glew.h"
#include <GLFW/glfw3.h>
#include <iostream>
the program prints that to the console ("OpenGL 4.0 supported" means that GL_VERSION_4_0 == true):
openGl version: 2.1 INTEL-14.5.22
opengl 4.0 supported
When I try to run it I get this error message from the shader Compiler for my vertex and fragment shader:
ERROR: 0:1: '' : version '400' is not supported
ERROR: 0:1: '' : syntax error: #version
ERROR: 0:3: 'layout' : syntax error: syntax error
When I change the #version 400 core to #version 120 I only get the syntax error for the layout. Because of that I think I messed up something with glew. What could I try?
Your system does not support OpenGL 4.0. It just supports OpenGL 2.1. See the output
openGl version: 2.1 INTEL-14.5.22
GLSL 1.20 corresponds to OpenGL 2.1. Downgrade the shader:
Vertex shader
#version 120
attribute vec4 position;
void main()
{
gl_Position = position;
}
Fragment shader
#version 120
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
Respectively using Raw string literals (C++11):
std::string vertexShader =
R"(#version 120
attribute vec4 position;
void main()
{
gl_Position = position;
}
)";
std::string fragmentShader =
R"(#version 120
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
)";

Pass data through TCS and TES

Here is a piece of code that I've been experimenting with:
#include <unistd.h>
#include "GL/gl3w.h"
#include "GLFW/glfw3.h"
#include <math.h>
#include <stdio.h>
#include <string.h>
class application {
private:
static void APIENTRY debug_callback(GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
GLvoid* userParam);
public:
application() {}
virtual ~application() {}
// virtual void run(application* the_app)
void run()
{
bool running = true;
// app = the_app;
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
return;
}
init();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, info.majorVersion);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, info.minorVersion);
if (info.flags.robust)
{
glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS, GLFW_LOSE_CONTEXT_ON_RESET);
}
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_SAMPLES, info.samples);
glfwWindowHint(GLFW_STEREO, info.flags.stereo ? GL_TRUE : GL_FALSE);
{
window = glfwCreateWindow(info.windowWidth, info.windowHeight, info.title, info.flags.fullscreen ? glfwGetPrimaryMonitor() : NULL, NULL);
if (!window)
{
fprintf(stderr, "Failed to open window\n");
return;
}
}
glfwMakeContextCurrent(window);
gl3wInit();
startup();
do
{
render(glfwGetTime());
glfwSwapBuffers(window);
glfwPollEvents();
running &= (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_RELEASE);
running &= (glfwWindowShouldClose(window) != GL_TRUE);
} while (running);
shutdown();
glfwDestroyWindow(window);
glfwTerminate();
}
virtual void init()
{
strcpy(info.title, "OpenGL SuperBible Example");
info.windowWidth = 800;
info.windowHeight = 600;
info.majorVersion = 4;
info.minorVersion = 5;
info.samples = 0;
info.flags.all = 0;
info.flags.cursor = 1;
}
virtual void startup() { }
virtual void render(double currentTime) { }
virtual void shutdown() { }
void setWindowTitle(const char * title) { glfwSetWindowTitle(window, title); }
virtual void onResize(int w, int h)
{
info.windowWidth = w;
info.windowHeight = h;
}
void getMousePosition(int& x, int& y)
{
double dx, dy;
glfwGetCursorPos(window, &dx, &dy);
x = static_cast<int>(floor(dx));
y = static_cast<int>(floor(dy));
}
public:
struct APPINFO
{
char title[128];
int windowWidth;
int windowHeight;
int majorVersion;
int minorVersion;
int samples;
union
{
struct
{
unsigned int fullscreen : 1;
unsigned int vsync : 1;
unsigned int cursor : 1;
unsigned int stereo : 1;
unsigned int debug : 1;
unsigned int robust : 1;
};
unsigned int all;
} flags;
};
protected:
APPINFO info;
static application * app;
GLFWwindow* window;
};
class tessellatedtri_app : public application
{
void init()
{
static const char title[] = "OpenGL SuperBible - Tessellated Triangle";
application::init();
memcpy(info.title, title, sizeof(title));
}
virtual void startup()
{
static const char * vs_source[] =
{
"#version 450 core \n"
"layout (location = 0) in vec4 offset; \n"
"layout (location = 1) in vec4 color; \n"
"out vec4 vs_color; \n"
"void main(void) \n"
"{ \n"
" const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0), \n"
" vec4(-0.25, -0.25, 0.5, 1.0), \n"
" vec4( 0.25, 0.25, 0.5, 1.0)); \n"
" \n"
" gl_Position = vertices[gl_VertexID] + offset; \n"
" vs_color = color; \n"
"} \n"
};
static const char * tcs_source[] =
{
"#version 450 core \n"
"layout (vertices = 3) out; \n"
" in vec4 vs_colors [];\n"
" out vec4 tcs_colors [3];\n"
"patch out vec4 patch_color; \n"
"void main(void) \n"
"{ \n"
// gl_TessLevelInner and gl_TessLevelOuter should only be set once
" if (gl_InvocationID == 0) \n"
" { \n"
" gl_TessLevelInner[0] = 3.0; \n"
" gl_TessLevelOuter[0] = 2.0; \n"
" gl_TessLevelOuter[1] = 2.0; \n"
" gl_TessLevelOuter[2] = 2.0; \n"
" } \n"
// " patch_color = vec4(.2, .3, .8); \n"
// " patch_color = vs_colors [gl_InvocationID]; \n"
// " tcs_colors[gl_InvocationID] = vs_colors[gl_InvocationID]; \n"
" gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; \n"
"} \n"
};
static const char * tes_source[] =
{
"#version 450 core \n"
"layout (triangles, equal_spacing, cw) in; \n"
// "patch in vec4 patch_color; \n"
// " out vec4 tes_color; \n"
"void main(void) \n"
"{ \n"
" gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) + \n"
" (gl_TessCoord.y * gl_in[1].gl_Position) + \n"
" (gl_TessCoord.z * gl_in[2].gl_Position); \n"
// " tes_color = patch_color; \n"
"} \n"
};
static const char * fs_source[] =
{
"#version 450 core \n"
"in vec4 tes_color; \n"
"out vec4 color; \n"
"void main(void) \n"
"{ \n"
" color = vec4(0.2, 0.2, .4, 1.0); \n"
// " color = tes_color;"
"} \n"
};
program = glCreateProgram();
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, vs_source, NULL);
glCompileShader(vs);
GLuint tcs = glCreateShader(GL_TESS_CONTROL_SHADER);
glShaderSource(tcs, 1, tcs_source, NULL);
glCompileShader(tcs);
GLuint tes = glCreateShader(GL_TESS_EVALUATION_SHADER);
glShaderSource(tes, 1, tes_source, NULL);
glCompileShader(tes);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, fs_source, NULL);
glCompileShader(fs);
glAttachShader(program, vs);
glAttachShader(program, tcs);
glAttachShader(program, tes);
glAttachShader(program, fs);
glLinkProgram(program);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
virtual void render(double currentTime)
{
float color_var = ((float)sin(currentTime) + 1.f) / 2.f;
bg_color[0] = color_var;
glClearBufferfv(GL_COLOR, 0, bg_color);
glUseProgram(program);
float offset[] = {
(float) sin(currentTime) * .5f,
(float) cos(currentTime) * .5f,
(float) cos(currentTime) * .5f,
0.0f
};
glVertexAttrib4fv(0, offset);
fg_color[2] = color_var;
glVertexAttrib4fv(1, fg_color);
glDrawArrays(GL_PATCHES, 0, 3);
}
virtual void shutdown()
{
glDeleteVertexArrays(1, &vao);
glDeleteProgram(program);
}
private:
float bg_color[3] = {1.f, .7f, .8f};
float fg_color[3] = {.2f, .7f, .2f};
GLuint program;
GLuint vao;
};
int main(int argc, const char ** argv)
{
tessellatedtri_app *app = new tessellatedtri_app();
app->run();
delete app;
return 0;
}
I'm just trying to vary the color of the wireframe by time, but somehow I couldn't pass the color attribute through the stages after many attempts. Any suggestions? Thanks.
You need an input and an output for the attribute which you want to pass through in ever stage:
Vertex shader:
layout (location = 1) in vec4 color;
out vec4 vs_color;
void main(void)
{
vs_color = color;
// ...
}
In the Tessellation Control Shader the attribute can be passed through:
in vec4 vs_color[];
out vec4 tcs_colors[];
void main(void)
{
tcs_colors[gl_InvocationID] = vs_color[gl_InvocationID];
// ...
}
In the Tessellation Evaluation Shader you have to calculate the "tessellated" attribute from the per vertex input:
in vec4 tcs_colors[];
out vec4 tes_colors;
void main(void)
{
tes_colors = gl_TessCoord.x * tcs_colors[0] +
gl_TessCoord.y * tcs_colors[1] +
gl_TessCoord.z * tcs_colors[2];
// ...
}
Fragment shader:
in vec4 tes_colors;

Red Book fur example not rendering fur (Linux/nvidia gtx675mx)

I trying to get the Red Book (8th edition) chapter 10 Fur example to work on my Ubuntu 14.04 laptop with Nvidia GTX675MX
I've changed the code to use SDL2 and glm but everything else is as it is in the Red Book.
The code compiles and runs but the 3d object is not fur shaded.
Can anyone spot any errors or is my GPU simply not up to the task?
(Full source is here: http://openme.gl/redbook_chapter_10_fur.zip)
#define GLM_FORCE_RADIANS
#include <string>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/gl.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <SDL2/SDL.h>
#include "vermilion.h"
#include "vutils.h"
#include "vbm.h"
#define BUFFER_OFFSET(x) ((const void*) (x))
#define PROGRAM_NAME "Red Book - Chapter 10 - Fur"
void Initialize();
void Display();
void Finalize(void);
void Reshape(int width, int height);
float aspect;
GLuint base_prog;
GLuint fur_prog;
GLuint fur_texture;
VBObject object;
GLint fur_model_matrix_pos;
GLint fur_projection_matrix_pos;
GLint base_model_matrix_pos;
GLint base_projection_matrix_pos;
void Initialize()
{
base_prog = glCreateProgram();
static const char base_vs_source[] =
"#version 410\n"
"\n"
"layout (location = 0) in vec4 position_in;\n"
"layout (location = 1) in vec3 normal_in;\n"
"layout (location = 2) in vec2 texcoord_in;\n"
"\n"
"uniform mat4 model_matrix;\n"
"uniform mat4 projection_matrix;\n"
"\n"
"out VS_FS_VERTEX\n"
"{\n"
" vec3 normal;\n"
"} vertex_out;\n"
"\n"
"void main(void)\n"
"{\n"
" vertex_out.normal = normal_in;\n"
" gl_Position = projection_matrix * (model_matrix * position_in);\n"
"}\n";
static const char base_fs_source[] =
"#version 410\n"
"\n"
"layout (location = 0) out vec4 color;\n"
"\n"
"in VS_FS_VERTEX\n"
"{\n"
" vec3 normal;\n"
"} vertex_in;\n"
"\n"
"void main(void)\n"
"{\n"
" vec3 normal = vertex_in.normal;\n"
" color = vec4(0.2, 0.1, 0.5, 1.0) * (0.2 + pow(abs(normal.z), 4.0)) + vec4(0.8, 0.8, 0.8, 0.0) * pow(abs(normal.z), 137.0);\n"
"}\n";
vglAttachShaderSource(base_prog, GL_VERTEX_SHADER, base_vs_source);
vglAttachShaderSource(base_prog, GL_FRAGMENT_SHADER, base_fs_source);
glLinkProgram(base_prog);
glUseProgram(base_prog);
base_model_matrix_pos = glGetUniformLocation(base_prog, "model_matrix");
base_projection_matrix_pos = glGetUniformLocation(base_prog, "projection_matrix");
fur_prog = glCreateProgram();
static const char fur_vs_source[] =
"#version 410\n"
"\n"
"layout (location = 0) in vec4 position_in;\n"
"layout (location = 1) in vec3 normal_in;\n"
"layout (location = 2) in vec2 texcoord_in;\n"
"\n"
"out VS_GS_VERTEX\n"
"{\n"
" vec3 normal;\n"
" vec2 tex_coord;\n"
"} vertex_out;\n"
"\n"
"void main(void)\n"
"{\n"
" vertex_out.normal = normal_in;\n"
" vertex_out.tex_coord = texcoord_in;\n"
" gl_Position = position_in;\n"
"}\n";
static const char fur_gs_source[] =
"#version 410\n"
"\n"
"layout (triangles) in;\n"
"layout (triangle_strip, max_vertices = 240) out;\n"
"\n"
"uniform mat4 model_matrix;\n"
"uniform mat4 projection_matrix;\n"
"\n"
"uniform int fur_layers = 30;\n"
"uniform float fur_depth = 5.0;\n"
"\n"
"in VS_GS_VERTEX\n"
"{\n"
" vec3 normal;\n"
" vec2 tex_coord;\n"
"} vertex_in[];\n"
"\n"
"out GS_FS_VERTEX\n"
"{\n"
" vec3 normal;\n"
" vec2 tex_coord;\n"
" flat float fur_strength;\n"
"} vertex_out;\n"
"\n"
"void main(void)\n"
"{\n"
" int i, layer;\n"
" float disp_delta = 1.0 / float(fur_layers);\n"
" float d = 0.0;\n"
" vec4 position;\n"
"\n"
" for (layer = 0; layer < fur_layers; layer++)\n"
" {\n"
" for (i = 0; i < gl_in.length(); i++) {\n"
" vec3 n = vertex_in[i].normal;\n"
" vertex_out.normal = n;\n"
" vertex_out.tex_coord = vertex_in[i].tex_coord;\n"
" vertex_out.fur_strength = 1.0 - d;\n"
" position = gl_in[i].gl_Position + vec4(n * d * fur_depth, 0.0);\n"
" gl_Position = projection_matrix * (model_matrix * position);\n"
" EmitVertex();\n"
" }\n"
" d += disp_delta;\n"
" EndPrimitive();\n"
" }\n"
"}\n";
static const char fur_fs_source[] =
"#version 410\n"
"\n"
"layout (location = 0) out vec4 color;\n"
"\n"
"uniform sampler2D fur_texture;\n"
"uniform vec4 fur_color = vec4(0.8, 0.8, 0.9, 1.0);\n"
"\n"
"in GS_FS_VERTEX\n"
"{\n"
" vec3 normal;\n"
" vec2 tex_coord;\n"
" flat float fur_strength;\n"
"} fragment_in;\n"
"\n"
"void main(void)\n"
"{\n"
" vec4 rgba = texture(fur_texture, fragment_in.tex_coord);\n"
" float t = rgba.a;\n"
" t *= fragment_in.fur_strength;\n"
" color = fur_color * vec4(1.0, 1.0, 1.0, t);\n"
"}\n";
vglAttachShaderSource(fur_prog, GL_VERTEX_SHADER, fur_vs_source);
vglAttachShaderSource(fur_prog, GL_GEOMETRY_SHADER, fur_gs_source);
vglAttachShaderSource(fur_prog, GL_FRAGMENT_SHADER, fur_fs_source);
glLinkProgram(fur_prog);
glUseProgram(fur_prog);
fur_model_matrix_pos = glGetUniformLocation(fur_prog, "model_matrix");
fur_projection_matrix_pos = glGetUniformLocation(fur_prog, "projection_matrix");
glGenTextures(1, &fur_texture);
unsigned char * tex = (unsigned char *)malloc(1024 * 1024 * 4);
memset(tex, 0, 1024 * 1024 * 4);
int n, m;
for (n = 0; n < 256; n++)
{
for (m = 0; m < 1270; m++)
{
int x = rand() & 0x3FF;
int y = rand() & 0x3FF;
tex[(y * 1024 + x) * 4 + 0] = (rand() & 0x3F) + 0xC0;
tex[(y * 1024 + x) * 4 + 1] = (rand() & 0x3F) + 0xC0;
tex[(y * 1024 + x) * 4 + 2] = (rand() & 0x3F) + 0xC0;
tex[(y * 1024 + x) * 4 + 3] = n;
}
}
glBindTexture(GL_TEXTURE_2D, fur_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
free(tex);
object.LoadFromVBM("ninja.vbm", 0, 1, 2);
}
void Display()
{
float t = float(SDL_GetTicks() & 0x3FFF) / float(0x3FFF);
static const glm::vec3 X(1.0f, 0.0f, 0.0f);
static const glm::vec3 Y(0.0f, 1.0f, 0.0f);
static const glm::vec3 Z(0.0f, 0.0f, 1.0f);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 p(glm::frustum(-1.0f, 1.0f, aspect, -aspect, 1.0f, 5000.0f));
glm::mat4 m;
m = glm::mat4(glm::translate(glm::mat4(1.0),glm::vec3(0.0f,
0.0f,
/* 100.0f * sinf(6.28318531f * t)*/ - 130.0f)) *
//glm::rotation(360.0f * t, X) *
glm::rotate(glm::mat4(1.0),36.0f * t * 1.0f, Y) *
glm::rotate(glm::mat4(1.0),18.0f, Z) *
glm::translate(glm::mat4(1.0),glm::vec3(0.0f, -80.0f, 0.0f)));
glUseProgram(base_prog);
glUniformMatrix4fv(base_model_matrix_pos, 1, GL_FALSE, glm::value_ptr(m));
glUniformMatrix4fv(base_projection_matrix_pos, 1, GL_FALSE, glm::value_ptr(p));
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
object.Render();
glUseProgram(fur_prog);
glUniformMatrix4fv(fur_model_matrix_pos, 1, GL_FALSE, glm::value_ptr(m));
glUniformMatrix4fv(fur_projection_matrix_pos, 1, GL_FALSE, glm::value_ptr(p));
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(GL_FALSE);
object.Render();
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
}
void Finalize(void)
{
glUseProgram(0);
glDeleteProgram(fur_prog);
}
void Reshape(int width, int height)
{
glViewport(0, 0 , width, height);
aspect = float(height) / float(width);
}
int main(int argc, char *argv[]){
SDL_Window *mainwindow; /* Our window handle */
SDL_GLContext maincontext; /* Our opengl context handle */
if (SDL_Init(SDL_INIT_VIDEO) < 0) { /* Initialize SDL's Video subsystem */
std::cout << "Unable to initialize SDL";
return 1;
}
/* Request opengl 4.4 context. */
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
/* Turn on double buffering with a 24bit Z buffer.
* You may need to change this to 16 or 32 for your system */
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
/* Create our window centered at 512x512 resolution */
mainwindow = SDL_CreateWindow(PROGRAM_NAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
512, 512, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
if (!mainwindow){ /* Die if creation failed */
std::cout << "SDL Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
/* Create our opengl context and attach it to our window */
maincontext = SDL_GL_CreateContext(mainwindow);
GLenum rev;
glewExperimental = GL_TRUE;
rev = glewInit();
if (GLEW_OK != rev){
std::cout << "Error: " << glewGetErrorString(rev) << std::endl;
exit(1);
} else {
std::cout << "GLEW Init: Success!" << std::endl;
}
/* This makes our buffer swap syncronized with the monitor's vertical refresh */
SDL_GL_SetSwapInterval(1);
bool quit=false;
Initialize();
Reshape(512,512);
SDL_Event event;
while(!quit){
Display();
SDL_GL_SwapWindow(mainwindow);
while( SDL_PollEvent( &event ) ){
if( event.type == SDL_QUIT ){
quit = true;
}
if(event.type ==SDL_WINDOWEVENT){
if(event.window.event = SDL_WINDOWEVENT_SIZE_CHANGED){
int w,h;
SDL_GetWindowSize(mainwindow,&w,&h);
Reshape(w,h);
}
}
}
}
Finalize();
/* Delete our opengl context, destroy our window, and shutdown SDL */
SDL_GL_DeleteContext(maincontext);
SDL_DestroyWindow(mainwindow);
SDL_Quit();
return 0;
}
I added
glGetProgramInfoLog(fur_prog, sizeof(buffer), &length, buffer);
std::cout << length << std::endl;
std::cout << buffer << std::endl;
And got
Geometry info
-------------
(0) : error C6033: Hardware limitation reached, can only emit 146 vertices of this size
Changed max_vertices to 146 and now the shader compiles and links.