OpenGL, object blinking when moving - c

I'm new to OpenGL, and I'm trying to move an object using the mouse. I'm using OpenGL 4.4 Core Profile, MinGW32, freeGLUT, GLU, and GLEW, programming in C.
The program draw an hexagon with GL_LINE_LOOP and the color (0.5, 0.5, 0.5, 1.0).
The problem is when I move it using the mouse, the object is softly blinking, the color changes to a darker grey. The blinking also occurs when drawing with the color (1.0, 1.0, 1.0, 1.0), but it is less visible.
I tried to change the swap interval using wglSwapIntervalEXT(), but it accepts only values 0 and 1. I also tried to enable Triple Buffering and "wait for Vsync" parameter of my graphic card. Changing these three parameters doesn't solve the problem.
The code is very simple, the vertex shader takes an Uniform vector t that corresponds to the translation to apply to the object.
Vertex shader program:
#version 440 core
in vec3 vertex_position;
uniform vec3 vertex_color;
uniform vec4 t;
uniform mat4 matrix;
out vec4 color;
vec4 vp;
void main() {
color = vec4(vertex_color,1.0);
vp = matrix * vec4(vertex_position,1.0);
gl_Position = vec4(vp.x+t.x, vp.y+t.y, vp.z+t.z, vp.w+t.w);
}
Fragment shader program:
#version 440 core
in vec4 color;
void main()
{
gl_FragColor = color;
}
The draw function is very simple, and I have a timer function that call glutPostRedisplay() every 16 ms, in order to have arround 60 FPS. I tried without the timer function, it increases the FPS, but the blinking even occurs.
The draw function:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
static int init = 1;
if(init == 1) {
glUseProgram(shader_program_core);
matrixloc = glGetUniformLocation(shader_program_core,"matrix");
// Load the matrix into the vertex shader:
glUniformMatrix4fv(matrixloc, 1, GL_FALSE, PMVmatrix);
colorloc = glGetUniformLocation(shader_program_core,"vertex_color");
// translation localisation:
tloc = glGetUniformLocation(shader_program_core,"t");
init = 0;
}
glUniform3f(colorloc,0.5,0.5,0.5);
// translation:
glUniform4f(tloc,tx,ty,tz,tw);
glBindVertexArray(vao);
glDrawArrays(GL_LINE_LOOP, 0, 6);
glBindVertexArray(0);
glutSwapBuffers();
The complete source code that shows the problem is here:
#define GLEW_STATIC
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
// coordinates of the hexagon:
GLfloat hexagon[18];
GLuint vao;
GLuint vbo;
// translations:
GLfloat tx = 0.0;
GLfloat ty = 0.0;
GLfloat tz = 0.0;
GLfloat tw = 0.0;
// window dimensions:
GLint width;
GLint height;
int window;
// coordinates of clicked point
int clicked_x;
int clicked_y;
// set to 1 if clicked down:
int clicked_down = 0;
/////////////////////////////////////////////////////////
//
// Shader programs for core profile:
//
const char * vsprog_core =
"#version 440 core\n"
"in vec3 vertex_position;\n"
"uniform vec3 vertex_color;\n"
"uniform vec4 t;\n"
"uniform mat4 matrix;\n"
" \n"
"out vec4 color;\n"
" \n"
"vec4 vp;\n"
" \n"
"void main() {\n"
" color = vec4(vertex_color,1.0);\n"
" vp = matrix * vec4(vertex_position,1.0);\n"
" gl_Position = vec4(vp.x+t.x, vp.y+t.y, vp.z+t.z, vp.w+t.w);\n"
"}\n";
const char * fsprog_core =
"#version 440 core\n"
"in vec4 color;\n"
"void main()\n"
"{\n"
" gl_FragColor = color;\n"
"}\n";
// uniforms locations:
GLint tloc;
GLint colorloc;
GLint matrixloc;
GLuint shader_program_core;
GLfloat PMVmatrix[16] = {
0.500000, 0.000000, 0.000000, 0.000000,
0.000000, 0.500000, 0.000000, 0.000000,
0.000000, 0.000000, 0.500000, 0.000000,
0.000000, 0.000000, 0.000000, 1.000000
};
void Draw()
{
int i,j;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
static int init = 1;
if(init == 1) {
glUseProgram(shader_program_core);
matrixloc = glGetUniformLocation(shader_program_core,"matrix");
// Load the matrix into the vertex shader:
glUniformMatrix4fv(matrixloc, 1, GL_FALSE, PMVmatrix);
colorloc = glGetUniformLocation(shader_program_core,"vertex_color");
// translation localisation:
tloc = glGetUniformLocation(shader_program_core,"t");
init = 0;
}
glUniform3f(colorloc,0.5,0.5,0.5);
// translation:
glUniform4f(tloc,tx,ty,tz,tw);
glBindVertexArray(vao);
glDrawArrays(GL_LINE_LOOP, 0, 6);
glBindVertexArray(0);
glutSwapBuffers();
//glutPostRedisplay();
}
void onMouseClick(int button, int state, int x, int y) {
if(state == GLUT_UP && button == GLUT_LEFT_BUTTON) clicked_down = 0;
if(state == GLUT_DOWN && button == GLUT_LEFT_BUTTON) {
clicked_down = 1;
clicked_x = x;
clicked_y = y;
}
}
void onMouseMove(int x, int y) {
int i,j;
if(clicked_down == 1) {
// compute x coordinate of the clicked point from the clicked x pixel:
GLfloat x1 = (clicked_x)*2.0/width - 1.0;
// compute x coordinate of the actual point from the actual x pixel:
GLfloat x2 = (x)*2.0/width - 1.0;
// compute y coordinate of the clicked point from the clicked y pixel:
GLfloat y1 = (clicked_y)*2.0/height - 1.0;
// compute y coordinate of the actual point from the actual y pixel:
GLfloat y2 = (y)*2.0/height - 1.0;
tx += x2 - x1;
ty += y1 - y2;
// save actual coordinates as previous ones, for the next move:
clicked_x = x;
clicked_y = y;
}
}
void timer( int value )
{
glutPostRedisplay();
glutTimerFunc( 16, timer, 0 );
}
int main( int argc, char *argv[ ], char *envp[ ] )
{
int i,j;
glutInitContextVersion(4, 4);
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE/* | GLUT_DEBUG*/);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(640,480);
window = glutCreateWindow("Program");
//glutFullScreen();
width = glutGet(GLUT_WINDOW_WIDTH);
height = glutGet(GLUT_WINDOW_HEIGHT);
// get version info
const GLubyte* renderer;
const GLubyte* version;
///////////////////////////////////////////////////////////////////////
//
// start GLEW extension handler
//
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
{
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
return(-1);
}
fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
// get version info
renderer = glGetString(GL_RENDERER); // get renderer string
version = glGetString(GL_VERSION); // version as a string
printf("\nRenderer: %s", renderer);
printf("\nOpenGL version supported %s", version);
fflush(stdout);
// tell GL to only draw onto a pixel if the shape is closer to the viewer
glEnable(GL_DEPTH_TEST); // enable depth-testing
glDepthFunc(GL_LESS); // depth-testing interprets a smaller value as "closer"
//////////////////////////////////////////////////////////
//
// Shaders:
//
GLint params;
GLint len;
GLuint vscore = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vscore, 1, &vsprog_core, NULL);
glCompileShader(vscore);
glGetShaderiv(vscore,GL_COMPILE_STATUS,&params);
if(params == GL_FALSE) {
GLchar log[100000];
glGetShaderInfoLog(vscore,100000,&len,log);
printf("\n\n%s\n\n",log);
return(-1);
}
GLuint fscore = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fscore, 1, &fsprog_core, NULL);
glCompileShader(fscore);
glGetShaderiv(fscore,GL_COMPILE_STATUS,&params);
if(params == GL_FALSE) {
GLchar log[100000];
glGetShaderInfoLog(fscore,100000,&len,log);
printf("\n\n%s\n\n",log);
return(-1);
}
shader_program_core = glCreateProgram();
glAttachShader(shader_program_core, fscore);
glAttachShader(shader_program_core, vscore);
glLinkProgram(shader_program_core);
glGetProgramiv(shader_program_core,GL_LINK_STATUS,&params);
if(params == GL_FALSE) {
GLchar log[100000];
glGetProgramInfoLog(shader_program_core,100000,&len,log);
printf("\n\n%s\n\n",log);
fflush(stdout);
return(-1);
}
//
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
//
// Compute coordinates of the hexagon:
//
hexagon[0] = cos(0.0*M_PI/3.0 + M_PI/6.0)*500.0/width;
hexagon[1] = sin(0.0*M_PI/3.0 + M_PI/6.0)*500.0/height;
hexagon[2] = 0.0;
hexagon[3] = cos(1.0*M_PI/3.0 + M_PI/6.0)*500.0/width;
hexagon[4] = sin(1.0*M_PI/3.0 + M_PI/6.0)*500.0/height;
hexagon[5] = 0.0;
hexagon[6] = cos(2.0*M_PI/3.0 + M_PI/6.0)*500.0/width;
hexagon[7] = sin(2.0*M_PI/3.0 + M_PI/6.0)*500.0/height;
hexagon[8] = 0.0;
hexagon[9] = cos(3.0*M_PI/3.0 + M_PI/6.0)*500.0/width;
hexagon[10] = sin(3.0*M_PI/3.0 + M_PI/6.0)*500.0/height;
hexagon[11] = 0.0;
hexagon[12] = cos(4.0*M_PI/3.0 + M_PI/6.0)*500.0/width;
hexagon[13] = sin(4.0*M_PI/3.0 + M_PI/6.0)*500.0/height;
hexagon[14] = 0.0;
hexagon[15] = cos(5.0*M_PI/3.0 + M_PI/6.0)*500.0/width;
hexagon[16] = sin(5.0*M_PI/3.0 + M_PI/6.0)*500.0/height;
hexagon[17] = 0.0;
// VAO:
glGenVertexArrays(1, &(vao));
glBindVertexArray(vao);
// VBO:
glGenBuffers(1,&(vbo));
glBindBuffer(GL_ARRAY_BUFFER,vbo);
glBufferData(GL_ARRAY_BUFFER, 18 * sizeof(GLfloat), hexagon, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0*sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER,0);
// End VAO:
glBindVertexArray(0);
glutMouseFunc(onMouseClick);
glutMotionFunc(onMouseMove);
glutDisplayFunc(Draw);
glutTimerFunc(0,timer,0);
glutMainLoop();
return 0;
}
The shaders are defined in two char* constants. Left-clicking and moving the mouse allow to move the object.

From your description, my (wild) guess is you have texturing enabled but you're not providing any texture information.
So, just call glDisable(GL_TEXTURE_2D); before drawing your cube.

Related

Why doesn't the rotation matrix rotate in the center of the text?

I am trying to rotate a text in OpenGL, but however, the problem is that the text rotates like it should but in the wrong point i.e, it does not rotate at the center of the text(and by that I want to know how I could do that!).
The reason I am confused because I am using multiple texture for different letters of the text which makes me confused.
If you are wondering which library I'm using, it is CGLM
But when I compile this code the rotate function rotates the object with the wrong point of rotation.
According to Rabbid76. I did the following to get the size of the whole text:-
for (int i = 0; i < (signed)strlen(text); i++)
{
tw += iterator[(int)text[i]].Character_Array.Size[0];
th += iterator[(int)text[i]].Character_Array.Size[1];
}
Still I am not getting the proper result, the text is still misplaced.
Before any rotation(this is where IT SHOULD rotate):-
After 45 degrees rotation(it gets misplaced from its position):-
Edit: The whole code of the source file:-
// Std. Includes
#include <stdio.h>
#include <stdlib.h>
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
// GLM
#include <cglm/cglm.h>
// FreeType
#include <ft2build.h>
#include FT_FREETYPE_H
// Properties
const GLuint WIDTH = 800, HEIGHT = 600;
const GLchar * vertexShaderSource =
"#version 330 core\n"
"layout(location = 0) in vec4 vertex;\n"
"out vec2 TexCoords;\n"
"uniform mat4 projection;\n"
"uniform mat4 model;\n"
"void main()\n"
"{\n"
"gl_Position = projection * model * vec4(vertex.xy, 0.0, 1.0);\n"
"TexCoords = vertex.zw;\n"
"}\n\0";
const GLchar * fragmentShaderSource =
"#version 330 core\n"
"in vec2 TexCoords;\n"
"out vec4 color;\n"
"uniform sampler2D text;\n"
"uniform vec4 textColor;\n"
"void main()\n"
"{\n"
"vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r);\n"
"color = textColor * sampled;\n"
"}\n\0";
/// Holds all state information relevant to a character as loaded using FreeType
typedef struct {
GLuint TextureID; // ID handle of the glyph texture
int Size[2]; // Size of glyph
int Bearing[2]; // Offset from baseline to left/top of glyph
GLuint Advance; // Horizontal offset to advance to next glyph
} Character;
typedef struct
{
GLchar char_Array;
Character Character_Array;
} Iterator;
Iterator * iterator;
GLuint VAO, VBO;
// RenderText function.. to render our text...
void RenderText(GLuint program, const char * text, GLfloat originx, GLfloat originy, GLfloat x, GLfloat y, GLfloat scalex, GLfloat scaley, float rotation, float r, float g, float b, float a);
// The MAIN function, from here we start our application and run the Game loop
int main()
{
iterator = NULL;
// Init GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", NULL, NULL); // Windowed
glfwMakeContextCurrent(window);
// Initialize GLEW to setup the OpenGL Function pointers
glewExperimental = GL_TRUE;
glewInit();
// Define the viewport dimensions
glViewport(0, 0, WIDTH, HEIGHT);
// Set OpenGL options
glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Compile and setup the shader
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertexShaderSource, NULL);
glCompileShader(vertex_shader);
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragment_shader);
GLuint program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
mat4 projection;
glm_ortho(0.0f, (GLfloat)WIDTH, (GLfloat)HEIGHT, 0.0f, -1, 1, projection);
glUseProgram(program);
glUniformMatrix4fv(glGetUniformLocation(program, "projection"), 1, GL_FALSE, (GLfloat *)projection);
// FreeType
FT_Library ft;
// All functions return a value different than 0 whenever an error occurred
if (FT_Init_FreeType(&ft))
printf("ERROR::FREETYPE: Could not init FreeType Library\n");
// Load font as face
FT_Face face;
if (FT_New_Face(ft, "playfair.ttf", 0, &face))
printf("ERROR::FREETYPE: Failed to load font\n");
// Set size to load glyphs as
FT_Set_Pixel_Sizes(face, 0, 72);
// Disable byte-alignment restriction
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
int i = 0;
// Load first 128 characters of ASCII set
for (GLubyte c = 0; c < 255; c++)
{
// Load character glyph
if (FT_Load_Char(face, c, FT_LOAD_RENDER))
{
printf("ERROR::FREETYTPE: Failed to load Glyph\n");
continue;
}
// Generate texture
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RED,
face->glyph->bitmap.width,
face->glyph->bitmap.rows,
0,
GL_RED,
GL_UNSIGNED_BYTE,
face->glyph->bitmap.buffer
);
// Set texture options
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Now store character for later use
Character character = {
texture,
{(signed)face->glyph->bitmap.width, (signed)face->glyph->bitmap.rows},
{face->glyph->bitmap_left, face->glyph->bitmap_top},
(GLuint)face->glyph->advance.x
};
iterator = (Iterator*)realloc(iterator, sizeof(Iterator) * (i + 1));
iterator[i].Character_Array = character;
iterator[i].char_Array = c;
i++;
}
glBindTexture(GL_TEXTURE_2D, 0);
// Destroy FreeType once we're finished
FT_Done_Face(face);
FT_Done_FreeType(ft);
// Configure VAO/VBO for texture quads
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glfwVulkanSupported();
// Game loop
float k = 0;
while (!glfwWindowShouldClose(window))
{
// Check and call events
glfwPollEvents();
// Clear the colorbuffer
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
if (k > 360)
{
k = 0;
}
k += 0.1f;
RenderText(program, "Rotation", 0, 0, 10.0f, 10.0f, 1.0f, 1.0f, k, 0.5f, 0.8f, 0.2f, 1.0f);
// Swap the buffers
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
void RenderText(GLuint program, const char * text, GLfloat originx, GLfloat originy, GLfloat x, GLfloat y, GLfloat scalex, GLfloat scaley, float rotation, float r, float g, float b, float a)
{
// Activate corresponding render state
glUseProgram(program);
glUniform4f(glGetUniformLocation(program, "textColor"), r, g, b, a);
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(VAO);
GLfloat tw = iterator[(int)text[i]].Character_Array.Bearing[0],
th = 0.0f;
for (int i = 0; i < (signed)strlen(text); i++)
{
Character ch = iterator[(int)text[i]].Character_Array;
tw += (ch.Advance >> 6);
th += ch.Size[1];
}
GLfloat rx = tw / 2.0f;
GLfloat ry = th / 2.0f;
mat4 model;
glm_mat4_identity(model);
glm_translate(model, (vec3) { originx, originy, 0.0f });
glm_translate(model, (vec3) { scalex * rx, scaley * ry, 0.0f });
glm_rotate(model, glm_rad(rotation), (vec3) { 0.0f, 0.0f, 1.0f });
glm_translate(model, (vec3) { -scalex * rx, -scaley * ry, 0.0f });
glm_scale(model, (vec3) { scalex, scaley, 1.0f });
GLfloat xpos = 0.0;
GLfloat ypos = 0.0;
for (int i = 0; i < (signed)strlen(text); i++)
{
Character ch = iterator[(int)text[i]].Character_Array;
mat4 ch_model;
memcpy(ch_model, model, 16 * sizeof(float));
glm_translate(ch_model, (vec3) { x, 0.0f, 0.0f });
// Now advance cursors for next glyph (note that advance is number of 1/64 pixels)
x += (ch.Advance >> 6); // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels))
glUniformMatrix4fv(glGetUniformLocation(program, "model"), 1, GL_FALSE, (GLfloat *)ch_model);
// Render glyph texture over quad
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
GLfloat w = ch.Size[0] * scalex;
GLfloat h = ch.Size[1] * scaley;
GLfloat vertices[6][4] = {
{ 0.0f, h, 0.0, 1.0 },
{ w, 0.0f, 1.0, 0.0 },
{ 0.0f, 0.0f, 0.0, 0.0 },
{ 0.0f, h, 0.0, 1.0 },
{ w, h, 1.0, 01.0 },
{ w, 0.0f, 01.0, 0.0 },
};
// Update content of VBO memory
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // Be sure to use glBufferSubData and not glBufferData
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Render quad
glDrawArrays(GL_TRIANGLES, 0, 6);
}
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
}
glm_rotate applies rotation at origin. So if your geometry's center is not at the origin then rotation will not made around center of object/geometry.
Solution: X = T(p)Rz(φ)T(−p) where X is final transform, p is pivot
Translate pivot (or object center, not object's position, it is not same) to origin
Apply Rotation or scaling
Translate pivot back to it's original position
If you want to rotate around center of object (if object's center is not at the origin) then you must compute center of that object/geometry. Before apply any rotation. You could compute bounding box then get center of that box.
cglm also provides functions for that: glm_vec_center(min, max, pivot); /* pivot = center of object */. Now we have center point. Let's rotate around that point:
/* ... */
glm_vec_center(min, max, pivot); /* center of object */
glm_vec_inv_to(pivot, pivotInv); /* -pivot */
/* ... */
glm_translate(model, pivot);
glm_rotate(model, angle, axis);
glm_translate(model, pivotInv);
The code above do same thing as X = T(p)Rz(φ)T(−p) (translate(-pivot), rotate, translate(pivot)). The order seems reverse in code because glm_translate = Transform * Translate. It would not be reverse order if glm_translate = Translate * Transform. cglm may provide this alternative translation multiplication too in the future
EDIT: By starting v0.4.2 version cglm provides functions for this purpose: check glm_rotate_at() and glm_quat_rotate_at(), glm_rotate_atm and glm_quat_rotate_atm creates NEW rotations for pivot point since glm_rotate_at and glm_quat_rotate_at rotates existing transforms. To use these functions make sure you have latest version.

OpenGL Tessellation Shader Not Drawing

I am attempting to tessellate a a sphere, but when I apply the tessellation shaders nothing shows up on screen. After reading quite a bit of literature on this and going through some questions here, I am still unable to figure out what is wrong. There are no errors when linking or loading the shaders either so I am somewhat at a loss.
The shader and drawing code is below.
Thanks.
Vertex
#version 410
in vec4 vPosition;
out vec3 Position;
void main()
{
Position = vPosition.xyz;
}
Control
#version 410
layout(vertices = 3) out;
in vec3 Position[];
out vec3 tcPosition[];
#define ID gl_InvocationID
void main()
{
tcPosition[ID] = Position[ID];
if(ID == 0) {
gl_TessLevelInner[0] = 3.0;
gl_TessLevelOuter[0] = 2.0;
gl_TessLevelOuter[1] = 2.0;
gl_TessLevelOuter[2] = 2.0;
}
}
Evaluation
#version 410
layout(triangles, equal_spacing, ccw) in;
in vec3 tcPosition[];
out vec3 tePosition;
uniform mat4 projection;
uniform mat4 Modelview;
void main()
{
vec3 p0 = gl_TessCoord.x * tcPosition[0];
vec3 p1 = gl_TessCoord.y * tcPosition[1];
vec3 p2 = gl_TessCoord.z * tcPosition[2];
vec3 tePosition = p0 + p1 + p2;
gl_Position = vec4(tePosition, 1.0);
}
Fragment
#version 410
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0, 1.0, 0.0, 1.0);
}
Draw Code
glPatchParameteri(GL_PATCH_VERTICES, 3);
glDrawArrays( GL_PATCHES, 0, sphere.vertexNumber );

Controlling where to zoom in on the Mandelbrot set

I wrote a simple fragment shader that renders a mandelbrot set. I am doing this in c and with opengl using glsl.
#version 330 core
in vec2 fCoord; //position.x position.y which is -1 to 1 on both axis
uniform int maxIterations;
uniform sampler1D mandiTexture;
out vec4 color;
void main()
{
vec2 c, z;
c.x = fCoord.x;
c.y = fCoord.y;
int i;
z = vec2(0.0f, 0.0f);
for(i=0; i<maxIterations; i++) {
float x = (z.x * z.x - z.y * z.y) + c.x;
float y = (z.y * z.x + z.x * z.y) + c.y;
if((x * x + y * y) > 4.0) break;
z.x = x;
z.y = y;
}
vec4 tcolor;
if (i == maxIterations)
{
tcolor = vec4(0.0f, 0.0f, 0.0f, 1.0f);
}
else
{
tcolor = texture(mandiTexture, float(i) / float(maxIterations));
}
color = tcolor;
}
i've noticed playing around with the initial z value I get some different results but mostly they extend outside of my quad. With z as 0, 0 I get this result.
as you can see the left side of the set is not being rendered on the quad.
The c value is coming from the vertex shader so i assume it goes for -1 to 1 on both x and y axis and being interpolated in between.
My questions are:
1) How can I center the image on the quad? I am not really sure of
that.
2) How can I say zoom in on some in on the mandelbrot set and a
follow up, lets say I want to zoom in on a specific part of the set?
2B) Let's say I click the screen and get the position in NDC?
3) If I set my max iterations higher the set seems to get really
jaggy, is that normal behavior?
I think if I can understand how to zoom in on the set I can figure out how to zoom in on a specific part but I am unsure.
edit, making sure that my code is
main.c
int maxIterations = 70;
int iterAmount = 1;
char* vshad, *fshad;
GLuint verticesBuffer, colorBuffer, vao, texCoordBuffer, indicesBuffer;
GLuint mandiTextureID, sp;
mat4_s vm, pm, opm, tm;
GLint viewMat = -1;
GLint projMat = -1;
GLint modelMat = -1;
GLint mandiTexture = -1;
GLint maxIterLoc = -1;
void initShaders(void)
{
char* vertexShaderSource = getResource("vert.shad");
char* fragmentShaderSource = getResource("frag.shad");
vshad = readFile(vertexShaderSource);
fshad = readFile(fragmentShaderSource);
free(vertexShaderSource);
free(fragmentShaderSource);
}
int run_game()
{
current_utc_time(&start_time);
while(game_running)
{
current_utc_time(&current_time);
double frameTime = (diff(start_time,current_time).tv_sec + diff(start_time,current_time).tv_nsec) * .00000001;
//printf("float time: %0.8f\n",frameTime);
if ( frameTime > 0.25 )
{
frameTime = 0.25;
}
current_utc_time(&start_time);
current_time = start_time;
accumulator += frameTime;
while ( accumulator >= dt )
{
accumulator -= dt;
t += dt;
//printf("fixed update dt: %0.8f\n",dt);
}
//render_state = currentState * alpha + previousState * ( 1.0 - alpha );
const double alpha = accumulator / dt;
render();
if(game_running < 1) { break; }
while (SDL_PollEvent(&event))
{
switch (event.type) {
case SDL_QUIT:
game_running = -1;
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
game_running = -1;
break;
}
break;
}
}
}
return -1;
}
int main(int argc, char const *argv[]) {
initShaders();
mat4_identity(&vm);
vec3_s eye = {0, 0, 0};
vec3_s center = {0, 0, -1};
vec3_s up = {0, 1, 0};
mat4_lookAt(&vm, &eye, &center, &up);
mat4_identity(&opm);
mat4_ortho(&opm, 0, 200, 0, 200, 1, 100);
mat4_identity(&tm);
mat4_scalex(&tm, &tm, 100, 100, 0);
mat4_translatex(&tm, &tm, 100.0f, 100.0f, -20);
SDL_Surface* mandiSurface = loadPNG(getResource("mandi.png"));
if(!mandiSurface) {
printf("IMG_Load: %s\n", IMG_GetError());
// handle error
}
GLenum Mode1 = GL_RGB;
if(4 == mandiSurface->format->BytesPerPixel)
{
Mode1 = GL_RGBA;
printf("mode change");
}
sp = getShaderProgram(vshad, fshad);
r = newRenderable2d();
glGenVertexArrays(1, &vao);
glGenBuffers(1, &verticesBuffer);
glGenBuffers(1, &colorBuffer);
glGenBuffers(1, &indicesBuffer);
glGenBuffers(1, &texCoordBuffer);
glBindVertexArray(vao); //bind vertex array buffer
glBindBuffer(GL_ARRAY_BUFFER, verticesBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(r->vertices), r->vertices, GL_STATIC_DRAW);
//bind n setup indices
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(r->indices), r->indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind indices
//bind n setup colors
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(r->colors), r->colors, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind colors
//bind n setup texture coords
glBindBuffer(GL_ARRAY_BUFFER, texCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(r->texCoords), r->texCoords, GL_STATIC_DRAW);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind texture coords
glBindVertexArray(0); //unbind vertex array buffer
//mandi 1d texture
glGenTextures(1, &mandiTextureID);
glBindTexture(GL_TEXTURE_1D, mandiTextureID);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage1D(GL_TEXTURE_1D, 0, Mode1, mandiSurface->w, 0, Mode1, GL_UNSIGNED_BYTE, mandiSurface->pixels);
glBindTexture(GL_TEXTURE_1D, 0);
free(mandiSurface);
while(run_game() >= 0);
free(r);
IMG_Quit();
SDL_GL_DeleteContext(maincontext);
SDL_DestroyWindow(window);
return 0;
}
void render()
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glUseProgram(sp);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_1D, mandiTextureID);//mandiTexture
mandiTexture = getUniformLocation(sp, "mandiTexture");
glUniform1i(mandiTexture, 0);
glBindVertexArray(verticesBuffer);
viewMat = getUniformLocation(sp, "viewMat");
modelMat = getUniformLocation(sp, "modelMat");
projMat = getUniformLocation(sp, "projMat");
maxIterLoc = getUniformLocation(sp, "maxIterations");
glUniformMatrix4fv(viewMat, 1, GL_FALSE, vm.m);
glUniformMatrix4fv(projMat, 1, GL_FALSE, opm.m);
glUniformMatrix4fv(modelMat, 1, GL_FALSE, tm.m);
glUniform1i(maxIterLoc, maxIterations);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
SDL_GL_SwapWindow(window);
}
int init_sdl(int width, int height, char* title, double fps)
{
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
{
SDL_Log("sdl failed to init");
SDL_Quit();
return -1;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if(window == NULL)
{
SDL_Log("sdl failed to create window");
SDL_Quit();
return -1;
}
maincontext = SDL_GL_CreateContext(window);
if(maincontext == NULL)
{
SDL_Log("sdl failed to create opengl context");
SDL_Quit();
return -1;
}
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
SDL_GL_SetSwapInterval(1);
return 1;
}
vertex shader
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 icolor;
layout (location = 2) in vec2 vTexCoord;
uniform mat4 modelMat;
uniform mat4 viewMat;
uniform mat4 projMat;
out vec4 fcolor;
out vec2 fTexCoord;
out vec2 fCoord;
void main()
{
gl_Position = projMat * viewMat * modelMat * vec4(position, 1.0);
fCoord = vec2(position);
fTexCoord = vTexCoord;
fcolor = vec4(icolor, 1.0f);
}
thanks to #samgak I was able to fixed the issues that I was having and now I am adding some shots of the Mandelbrot set.
The c value is coming from the vertex shader so i assume it goes for -1 to 1 on both x and y axis and being interpolated in between.
That's correct.
1) How can I center the image on the quad? I am not really sure of that.
You just need to zoom out by a factor of 1.5 and center it on -0.5. The interesting parts of the Mandelbrot set extend from roughly -2 to 1 on the real axis and -i to i on the imaginary axis:
2) How can I say zoom in on some in on the mandelbrot set and a follow up, lets say I want to zoom in on a specific part of the set?
2B) Let's say I click the screen and get the position in NDC?
Put back the 2 uniforms that you had in your previous version:
uniform vec2 center;
uniform float scale;
Declare variables to hold these values in your C code and set them with glUniform2f and glUniform1f. To center the set the initial values should be -0.5, 0.0 for the center, and 1.5 for the scale (larger values zoom out). Then in your fragment shader, just apply them like this:
c = (fCoord * scale) + center;
To click the screen and zoom in on a particular location, turn the mouse location into a value between -1,-1 and 1,1 based on its position on the screen then apply the above equation to it to find the location you clicked on. Set that as the new center and multiply scale by a value less than 1 to zoom in a given amount.
3) If I set my max iterations higher the set seems to get really jaggy, is that normal behavior?
The screenshot you posted looks ok. It would probably look better if you implemented some kind of multi-sampling in your fragment shader (e.g. calculate several values in a loop and add them together so that each pixel is actually the average of a 2x2 or 4x4 block of pixels etc).
If you zoom in far enough eventually you will run into the limits of the precision of the floating point numbers used by the GPU.

Fixing glRasterPos() position?

I am working on a OPENGL with C project. In this project, a ball will be there and it will have random motion, colliding with the walls of window and moving in a random direction. the player needs to click on the ball and the score which is displayed on top left corner will be incremented by 1 and the speed of the ball will increase by 1. We also have timer displayed on top right of 1 min. After 1 min the game will be over and the final score will be displayed to the player.
So far I have done the random motion of the ball. Score text displayed. The problem is that score is moving with the ball, it is not static on the top left corner. So how to do it?
Here is my code:
#include<GL/glut.h>
#include<math.h>
#include<stdbool.h>
#define PI 3.14159265f
//Variable defined outside globally
GLfloat ballRadius = 0.2; //Radius of the bouncing ball
GLfloat ballX = 0.0f; //Ball's center(x,y) position
GLfloat ballY = 0.0f;
GLfloat ballXMax,ballXMin,ballYMax,ballYMin; //Ball's center (x,y) bounds
GLfloat xSpeed = 0.02f; //Ball's speed in x and y direction
GLfloat ySpeed = 0.007f;
int refreshMills = 30;
int x1,xa,ya; //refresh period in milliseconds
int score=0;
int last_mx = 0, last_my = 0, cur_mx = 0, cur_my = 0;
int arcball_on = false;
//Projection clipping area
GLdouble clipAreaXLeft,clipAreaXRight,clipAreaYBottom,clipAreaYTop;
// Initialize OpenGL Graphics
void initGL()
{
glClearColor(0.0,0.0,0.0,1.0); //Set background(clear) color to green
}
// Callback handler for window re-paint event
void display()
{
glClear(GL_COLOR_BUFFER_BIT); //Clear the color buffer
glMatrixMode(GL_MODELVIEW); //To operate on the model-view matrix
glLoadIdentity(); //Reset model-view matrix
glTranslatef(ballX,ballY,0.0f); //Translate to (xPos,yPos)
glBegin(GL_TRIANGLE_FAN); //Use triangular segments to form a circle
glColor3ub( rand()%1000, rand()%1000, rand()%1000 ); //Red
glVertex2f(0.0f,0.0f); //Center of circle
int numSegments = 100; //ball shape temp...
GLfloat angle;
int i;
for(i=0;i<=numSegments;i++) //Last vertex same as first vertex
{
angle = i*2.0f*PI/numSegments; //360 degree for all segments
glVertex2f(cos(angle)*ballRadius,sin(angle)*ballRadius);
}
glEnd();
glFlush(); //Swap front and back buffers
//Animation Control - compute the location for next refresh
ballX += xSpeed;
ballY += ySpeed;
//Check if the ball exceeds the edges
if(ballX > ballXMax)
{ xa=ballX;
ballX = ballXMax;
xSpeed = -xSpeed;
}
else if(ballX < ballXMin)
{ xa=ballX;
ballX = ballXMin;
xSpeed = -xSpeed;
}
if(ballY > ballYMax)
{ ya=ballY;
ballY = ballYMax;
ySpeed = -ySpeed;
}
else if(ballY < ballYMin)
{ ya=ballY;
ballY = ballYMin;
ySpeed = -ySpeed;
}
glColor3f(1.0,0.0,0.0);
glRasterPos2f(-1.0,0.0);
glutBitmapCharacter (GLUT_BITMAP_8_BY_13,'S');
glutBitmapCharacter (GLUT_BITMAP_8_BY_13,'C');
glutBitmapCharacter (GLUT_BITMAP_8_BY_13,'O');
glutBitmapCharacter (GLUT_BITMAP_8_BY_13,'R');
glutBitmapCharacter (GLUT_BITMAP_8_BY_13,'E');
glutBitmapCharacter (GLUT_BITMAP_8_BY_13,':');
glFlush();
}
void onMouse(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
arcball_on = true;
last_mx = cur_mx = x;
last_my = cur_my = y;
} else {
arcball_on = false;
if(cur_mx==x && cur_my==y)
{
score=score+1;
}
printf("%d",score);
}
}
void onMotion(int x, int y) {
if (arcball_on) { // if left button is pressed
cur_mx = x;
cur_my = y;
}
}
/*void mouseClicks(int button, int state, int x, int y) {
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
utton == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
}
*/
//Call back when the windows is re-sized
void reshape(GLsizei width,GLsizei height)
{
//Compute aspect ratio of the new window
if(height ==0) height = 1; //To prevent divide by 0
GLfloat aspect = (GLfloat)width / (GLfloat)height;
//Set the viewport to cover the new window
glViewport(0,0,width,height);
//Set the aspect ratio of the clipping area to match the viewport
glMatrixMode(GL_PROJECTION); //To operate on the Projection matrix
glLoadIdentity(); //Reset the Projection Matrix
if(width >=height)
{
clipAreaXLeft = -1.0 * aspect;
clipAreaXRight = 1.0 * aspect;
clipAreaYBottom = -1.0;
clipAreaYTop = 1.0;
}
else
{
clipAreaXLeft = -1.0;
clipAreaXRight = 1.0 ;
clipAreaYBottom = -1.0 / aspect;
clipAreaYTop = 1.0 / aspect;
}
gluOrtho2D(clipAreaXLeft,clipAreaXRight,clipAreaYBottom,clipAreaYTop+0.25);
ballXMin = clipAreaXLeft + ballRadius;
ballXMax = clipAreaXRight - ballRadius;
ballYMin = clipAreaYBottom + ballRadius;
ballYMax = clipAreaYTop - ballRadius;
}
//Call back when the timer expired
void Timer(int value)
{
glutPostRedisplay(); //Post a paint request to activate display()
glutTimerFunc(refreshMills,Timer,5); //subsequent timer call at milliseconds
}
int windowWidth = 500; //Window mode's width
int windowHeight = 500; //Window mode's height
int windowPosX = 100; //Window mode's top-left corner x
int windowPosY = 100;
//Main function: GLUT runs as a console application starting at main()
int main(int argc,char* argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); //Enable double buffered mode
glutInitWindowSize(windowWidth,windowHeight); //Initial window width and height
glutInitWindowPosition(windowPosX,windowPosY); //Initial window top-left corner(x,y)
glutCreateWindow("Bouncing Ball");
glutMouseFunc(onMouse);
glutMotionFunc(onMotion);
glutDisplayFunc(display); //Register callback handler for window re-paint
//glutMouseFunc(mouseClicks);
glutReshapeFunc(reshape);
glutPostRedisplay(); //Register callback handler for window re-shape
glutTimerFunc(0,Timer,0); //First timer call immediately
initGL(); //Our own OpenGL initialization
glutMainLoop(); //Enter event processing loop
}
Omitting the drawing code for the ball, you have this code sequence:
glLoadIdentity(); //Reset model-view matrix
glTranslatef(ballX,ballY,0.0f); //Translate to (xPos,yPos)
...
glRasterPos2f(-1.0,0.0);
glutBitmapCharacter (GLUT_BITMAP_8_BY_13,'S');
The current modelview transformation is applied to the position you specify with glRasterPos2f(), which includes the translation you specified with glTranslatef().
You have a few options to fix this:
Reset the transformation before calling glRasterPos2f():
glLoadIdentity();
glRasterPos2f(-1.0,0.0);
glutBitmapCharacter (GLUT_BITMAP_8_BY_13,'S');
Push/pop the transformation you use for drawing the ball, to restore the previous transformation after you finished drawing the ball:
glLoadIdentity(); //Reset model-view matrix
glPushMatrix();
glTranslatef(ballX,ballY,0.0f); //Translate to (xPos,yPos)
...
glPopMatrix();
glRasterPos2f(-1.0,0.0);
glutBitmapCharacter (GLUT_BITMAP_8_BY_13,'S');
Use glWindowPos() instead of glRasterPos(), which allows you to specify the position in pixels, instead of coordinates that will be transformed.

OpenGL finding `in vec3 vert` but not `in float val` in vertex shader

I have some code that draws squares by passing points through a geometry shader. I construct an array which is sequences of 3 floats, bind that to the in vec3 vert attribute of my vertex shader, and everything is fine.
However, I want to add another float which the fragment shader will use to calculate color. This is in the vertex shader (to pass through) as in float val. Despite being able to find vert, glGetAttribLocation can't find val (get_program_attrib(): Atrrib val not found (-1)).
Code:
void load_model(GLuint* vao, GLuint* vbo) {
glGenVertexArrays(1, vao);
glBindVertexArray(*vao);
glGenBuffers(1, vbo);
glBindBuffer(GL_ARRAY_BUFFER, *vbo);
float data[SQUARES_PER_AXIS_SQ * 4] = {0};
squares_count = 0;
for (int i = 0; i < SQUARES_PER_AXIS_SQ; i++) {
int x_pos = i % SQUARES_PER_AXIS;
int y_pos = i / SQUARES_PER_AXIS;
if (fabs(squares[i]) > 0.0) {
data[squares_count * 4 + 0] = x_pos / ((float)SQUARES_PER_AXIS) * 2 - 1;
data[squares_count * 4 + 1] = (SQUARES_PER_AXIS - y_pos) / ((float)SQUARES_PER_AXIS) * 2 - 1;
data[squares_count * 4 + 2] = 0.5f;
data[squares_count * 4 + 3] = (float)squares[i];
squares_count++;
}
}
DPRINT("Loaded %d squares\n", squares_count);
glBufferData(GL_ARRAY_BUFFER, squares_count * 4 * sizeof(float), data, GL_STATIC_DRAW);
glEnableVertexAttribArray(get_program_attrib(main_shader, "vert"));
glEnableVertexAttribArray(get_program_attrib(main_shader, "val"));
glVertexAttribPointer(get_program_attrib(main_shader, "vert"), 3, GL_FLOAT, GL_FALSE, 4, NULL);
glVertexAttribPointer(get_program_attrib(main_shader, "val"), 1, GL_FLOAT, GL_FALSE, 4, (float*)(3 * sizeof(float)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
GLuint get_program_attrib(program_t* prog, GLchar* name) {
if (!name) {
DPRINT("ERROR: name == NULL\n");
return -1;
}
GLint attrib = glGetAttribLocation(prog->id, name);
if (attrib < 0)
DPRINT("Atrrib %s not found (%d)\n", name, attrib);
return attrib;
}
Vertex shader:
#version 150
in vec3 vert;
in float val;
out float value;
void main() {
gl_Position = vec4(vert, 1);
value = val;
}
Fragment shader:
#version 150
in float value;
out vec4 color;
void main() {
color = vec4(value, 0, 0, 1);
}
Geometry shader:
#version 150
layout (points) in;
layout (triangle_strip, max_vertices=4) out;
uniform float square_size;
void main() {
vec4 position = gl_in[0].gl_Position;
gl_Position = vec4(position.x, position.y, position.zw);
EmitVertex();
gl_Position = vec4(position.x, position.y + square_size, position.zw);
EmitVertex();
gl_Position = vec4(position.x + square_size, position.y, position.zw);
EmitVertex();
gl_Position = vec4(position.x + square_size, position.y + square_size, position.zw);
EmitVertex();
EndPrimitive();
}
Vertex shader outputs are not passed directly to the fragment shader when you have a geometry shader.
It is this that is causing all of your problems. For a vertex attribute to be active, it has to contribute to the final output of your program. Basically that means something calculated in the fragment shader has to be based off of it.
Unfortunately, that is not happening right now. You have a variable called value that is output from your vertex shader and a variable called value that is input by your fragment shader. Because the geometry shader sits inbetween the two of them, the fragment shader only looks for an output named value in the geometry shader -- no such output exists.
Naturally you might think that the solution would be to create a variable called value in the geometry shader that serves as the input and the output. However, that will not work, you would have to declare it inout value and that is invalid.
Here are the necessary corrections:
Vertex shader:
#version 150
in vec3 vert;
in float val;
out float value_vtx; // Output is fed to the Geometry Shader
void main() {
gl_Position = vec4(vert, 1);
value_vtx = val;
}
Fragment shader:
#version 150
in float value_geo; // Takes its input from the Geometry Shader
out vec4 color;
void main() {
color = vec4(value_geo, 0, 0, 1);
}
Geometry shader:
#version 150
layout (points) in;
layout (triangle_strip, max_vertices=4) out;
uniform float square_size;
in float value_vtx []; // This was output by the vertex shader
out float value_geo; // This will be the input to the fragment shader
void main() {
vec4 position = gl_in[0].gl_Position;
gl_Position = vec4(position.x, position.y, position.zw);
value_geo = value_vtx[0];
EmitVertex();
gl_Position = vec4(position.x, position.y + square_size, position.zw);
value_geo = value_vtx[0];
EmitVertex();
gl_Position = vec4(position.x + square_size, position.y, position.zw);
value_geo = value_vtx[0];
EmitVertex();
gl_Position = vec4(position.x + square_size, position.y + square_size, position.zw);
value_geo = value_vtx[0];
EmitVertex();
EndPrimitive();
}
You may be asking why I assigned value_geo 4 times when it is constant. That is because EmitVertex (...) causes all output variables to become undefined when it returns, so you have to set it every time.

Resources