Geometry Shader does not work

I am dealing with geometry shaders following OpenGL - Geometry shaders. My OPENGL version is 2.1, GLSL version is 1.20, OS X. When vertex shader and frag shader are attached to my program, it works and four red points is displayed. When the geometry shader is attached, the program is compiled successfully. However, no point is displayed. The following are my code:
vertex shader:
#version 120
#extension GL_EXT_geometry_shader4 : enable
attribute vec2 position;

void main()
{
gl_Position = vec4(position, 0.0, 1.0);
}
frag shader:
#version 120
#extension GL_EXT_geometry_shader4 : enable
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
geom shader:
#version 120
#extension GL_EXT_geometry_shader4 : enable

void main()
{
for(int i = 0; i < gl_VerticesIn; i++)
{
gl_Position = gl_PositionIn[i] + vec4(-0.1, 0.0, 0.0, 0.0);
EmitVertex();
}
EndPrimitive();
}
main.cpp
#include <GL/glew.h>
#include “textfile.h”
#include <glut/glut.h>
#include <iostream>

using namespace std;

GLuint vShader,fShader, gShader;//顶点着色器对象

//顶点位置数组
float positionData[] = {
// Coordinates Color Sides
-0.45f, 0.45f, 1.0f, 0.0f, 0.0f, 4.0f,
0.45f, 0.45f, 0.0f, 1.0f, 0.0f, 8.0f,
0.45f, -0.45f, 0.0f, 0.0f, 1.0f, 16.0f,
-0.45f, -0.45f, 1.0f, 1.0f, 0.0f, 32.0f};
GLubyte elements[] = {0, 1, 1, 2, 2, 3, 3, 0};
GLuint vaoHandle;//vertex array object
GLuint programHandle;

void initShader(const char *VShaderFile,const char *FShaderFile, const char *GShaerFile) {
//1、查看GLSL和OpenGL的版本
const GLubyte *renderer = glGetString( GL_RENDERER );
const GLubyte *vendor = glGetString( GL_VENDOR );
const GLubyte *version = glGetString( GL_VERSION );
const GLubyte *glslVersion =
glGetString( GL_SHADING_LANGUAGE_VERSION );
GLint major, minor;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
cout << “GL Vendor :” << vendor << endl;
cout << "GL Renderer : " << renderer << endl;
cout << "GL Version (string) : " << version << endl;
cout << "GL Version (integer) : " << major << “.” << minor << endl;
cout << "GLSL Version : " << glslVersion << endl;
//2、编译着色器
//创建着色器对象:顶点着色器
vShader = glCreateShader(GL_VERTEX_SHADER);
//错误检测
if (0 == vShader) {
cerr << “ERROR : Create vertex shader failed” << endl;
exit(1);
}
//把着色器源代码和着色器对象相关联
const GLchar *vShaderCode = textFileRead(VShaderFile);
const GLchar *vCodeArray[1] = {vShaderCode};
glShaderSource(vShader,1,vCodeArray,NULL);
//编译着色器对象
glCompileShader(vShader);
//检查编译是否成功
GLint compileResult;
glGetShaderiv(vShader,GL_COMPILE_STATUS,&compileResult);
if (GL_FALSE == compileResult) {
GLint logLen;
//得到编译日志长度
glGetShaderiv(vShader,GL_INFO_LOG_LENGTH,&logLen);
if (logLen > 0) {
char *log = (char *)malloc(logLen);
GLsizei written;
//得到日志信息并输出
glGetShaderInfoLog(vShader,logLen,&written,log);
cerr << "vertex shader compile log : " << endl;
cerr << log << endl;
free(log);//释放空间
}
}
//创建着色器对象:几何着色器
gShader = glCreateShader(GL_GEOMETRY_SHADER);
//错误检测
if (0 == gShader) {
cerr << “ERROR : Create geometry shader failed” << endl;
exit(1);
}
//把着色器源代码和着色器对象相关联
const GLchar *gShaderCode = textFileRead(GShaerFile);
const GLchar *gCodeArray[1] = {gShaderCode};
glShaderSource(gShader,1,gCodeArray,NULL);
//编译着色器对象
glCompileShader(gShader);
//检查编译是否成功
glGetShaderiv(gShader,GL_COMPILE_STATUS,&compileResult);
if (GL_FALSE == compileResult) {
GLint logLen;
//得到编译日志长度
glGetShaderiv(gShader,GL_INFO_LOG_LENGTH,&logLen);
if (logLen > 0) {
char *log = (char *)malloc(logLen);
GLsizei written;
//得到日志信息并输出
glGetShaderInfoLog(gShader,logLen,&written,log);
cerr << "geometry shader compile log : " << endl;
cerr << log << endl;
free(log);//释放空间
}
}
//创建着色器对象:片断着色器
fShader = glCreateShader(GL_FRAGMENT_SHADER);
//错误检测
if (0 == fShader) {
cerr << “ERROR : Create fragment shader failed” << endl;
exit(1);
}
//把着色器源代码和着色器对象相关联
const GLchar *fShaderCode = textFileRead(FShaderFile);
const GLchar *fCodeArray[1] = {fShaderCode};
glShaderSource(fShader,1,fCodeArray,NULL);
//编译着色器对象
glCompileShader(fShader);
//检查编译是否成功
glGetShaderiv(fShader,GL_COMPILE_STATUS,&compileResult);
if (GL_FALSE == compileResult) {
GLint logLen;
//得到编译日志长度
glGetShaderiv(fShader,GL_INFO_LOG_LENGTH,&logLen);
if (logLen > 0) {
char *log = (char *)malloc(logLen);
GLsizei written;
//得到日志信息并输出
glGetShaderInfoLog(fShader,logLen,&written,log);
cerr << "fragment shader compile log : " << endl;
cerr << log << endl;
free(log);//释放空间
}
}
//3、链接着色器对象
//创建着色器程序
programHandle = glCreateProgram();
if (!programHandle) {
cerr << “ERROR : create program failed” << endl;
exit(1);
}
//glProgramParameteriEXT(programHandle, GL_GEOMETRY_VERTICES_OUT, GL_POINTS);
glProgramParameteriEXT(programHandle, GL_GEOMETRY_INPUT_TYPE, GL_POINTS);
glProgramParameteriEXT(programHandle, GL_GEOMETRY_OUTPUT_TYPE, GL_LINE_STRIP);
glProgramParameteriEXT(programHandle, GL_GEOMETRY_VERTICES_OUT_EXT, 2);
//将着色器程序链接到所创建的程序中
glAttachShader(programHandle,vShader);
glAttachShader(programHandle,gShader);
glAttachShader(programHandle,fShader);
//将这些对象链接成一个可执行程序
glLinkProgram(programHandle);
//查询链接的结果
GLint linkStatus;
glGetProgramiv(programHandle,GL_LINK_STATUS,&linkStatus);
if (GL_FALSE == linkStatus) {
cerr << “ERROR : link shader program failed” << endl;
GLint logLen;
glGetProgramiv(programHandle, GL_INFO_LOG_LENGTH, &logLen);
if (logLen > 0) {
char *log = (char *)malloc(logLen);
GLsizei written;
glGetProgramInfoLog(programHandle, logLen, &written,log);
cerr << "Program log : " << endl;
cerr << log << endl;
}
}
else {//链接成功,在OpenGL管线中使用渲染程序
glUseProgram(programHandle);
}
}

void initVBO() {
// Create and populate the buffer objects
GLuint vboHandles;
glGenBuffers(1, &vboHandles);
//绑定VBO以供使用
glBindBuffer(GL_ARRAY_BUFFER, vboHandles);
//加载数据到VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(positionData), positionData, GL_STATIC_DRAW);
glGenVertexArraysAPPLE(1, &vaoHandle);
glBindVertexArrayAPPLE(vaoHandle);
GLuint locAttrib = glGetAttribLocation(programHandle, “position”);
glEnableVertexAttribArray(locAttrib);//顶点坐标
glVertexAttribPointer(locAttrib, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), 0);
GLuint colAttrib = glGetAttribLocation(programHandle, “color”);
glEnableVertexAttribArray(colAttrib);//顶点颜色
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(float)));
GLuint sidesAttrib = glGetAttribLocation(programHandle, “sides”);
glEnableVertexAttribArray(sidesAttrib);//顶点颜色
glVertexAttribPointer(sidesAttrib, 1, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(5 * sizeof(float)));
}

void init() {
//初始化glew扩展库
GLenum err = glewInit();
if( GLEW_OK != err )
{
cout <<"Error initializing GLEW: " << glewGetErrorString(err) << endl;
}
initShader(“basic.vert”,“basic.frag”, “basic.geom”);
initVBO();
glClearColor(0.0, 0.0, 0.0, 0.0);
//glShadeModel(GL_SMOOTH);
}

void display() {
glClear(GL_COLOR_BUFFER_BIT);
//使用VAO、VBO绘制
//glBindVertexArrayAPPLE(vaoHandle);
//glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawArrays(GL_POINTS, 0, 4);
glBindVertexArrayAPPLE(0);
glutSwapBuffers();
}

void keyboard(unsigned char key,int x,int y) {
switch(key) {
case 27:
glDeleteShader(vShader);
glUseProgram(0);
break;
}
}

int main(int argc,char** argv) {
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(600,600);
glutInitWindowPosition(100,100);
glutCreateWindow(“GLSL Test : Draw a triangle”);
init();
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}

A few different problems:

  1. you’re using constants that are only valid in GL3, in a GL2 context.
    GL_GEOMETRY_INPUT_TYPE != GL_GEOMETRY_INPUT_TYPE_EXT
    GL_GEOMETRY_OUTPUT_TYPE != GL_GEOMETRY_OUTPUT_TYPE_EXT
    (these cause glProgramParameteriEXT to fail, so your program is not linked as you expect, and can’t work)

Also GL_MAJOR_VERSION, GL_MINOR_VERSION are not valid in GL2.
If you compile against <OpenGL/gl.h> instead of using GLEW, you’ll easily catch this. Or use glGetError().

  1. Your geometry shader is nonsensical.
    you draw four points, and want to convert each one to a single line segment. But your shader loops over gl_VerticesIn, which is 1, so it only emits a single point for each line, which draws nothing. Try instead:
for(int i = 0; i < 2; i++)
{
    gl_Position = gl_PositionIn[0] + vec4(i*-0.1, 0.0, 0.0, 0.0);
    EmitVertex();
}

3 you’re setting attribute pointers for missing attributes.
querying the location of a attribute that doesn’t exist in the linked program will return -1, which isn’t an error. But, trying to set the pointer of attribute -1 is an error. That doesn’t break the rendering, but… it’s an error.

I am very appreciate for your reply. I have modified my code, but still nothing is displayed. It is noted that there is no error when my program is compiled and linked.
1)I have modified “GL_GEOMETRY_INPUT_TYPE” and “GL_GEOMETRY_OUTPUT_TYPE” to “GL_GEOMETRY_INPUT_TYPE_EXT” and “GL_GEOMETRY_OUTPUT_TYPE_EXT”. About “GL_MAJOR_VERSION” and “GL_MINOR_VERSION”, I have not removed them, but I think it is a minor problem, meanwhile the program is compiled and linked successfully.
2)I have modified the geometry shader according to your favorite suggestion.
3)I have removed the missing attributes.
The modified code is following, and my modifications have been bolded.
main.cpp
#include <GL/glew.h>
#include “textfile.h”
#include <glut/glut.h>
#include <iostream>
//#include <OpenGL/gl.h>

using namespace std;

GLuint vShader,fShader, gShader;//顶点着色器对象

//顶点位置数组
float positionData[] = {
// Coordinates Color Sides
-0.45f, 0.45f, 1.0f, 0.0f, 0.0f, 4.0f,
0.45f, 0.45f, 0.0f, 1.0f, 0.0f, 8.0f,
0.45f, -0.45f, 0.0f, 0.0f, 1.0f, 16.0f,
-0.45f, -0.45f, 1.0f, 1.0f, 0.0f, 32.0f};
GLubyte elements[] = {0, 1, 1, 2, 2, 3, 3, 0};
GLuint vaoHandle;//vertex array object
GLuint programHandle;

void initShader(const char *VShaderFile,const char *FShaderFile, const char *GShaerFile) {
//1、查看GLSL和OpenGL的版本
const GLubyte *renderer = glGetString( GL_RENDERER );
const GLubyte *vendor = glGetString( GL_VENDOR );
const GLubyte *version = glGetString( GL_VERSION );
const GLubyte *glslVersion =
glGetString( GL_SHADING_LANGUAGE_VERSION );
GLint major, minor;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
cout << “GL Vendor :” << vendor << endl;
cout << "GL Renderer : " << renderer << endl;
cout << "GL Version (string) : " << version << endl;
cout << "GL Version (integer) : " << major << “.” << minor << endl;
cout << "GLSL Version : " << glslVersion << endl;
//2、编译着色器
//创建着色器对象:顶点着色器
vShader = glCreateShader(GL_VERTEX_SHADER);
//错误检测
if (0 == vShader) {
cerr << “ERROR : Create vertex shader failed” << endl;
exit(1);
}
//把着色器源代码和着色器对象相关联
const GLchar *vShaderCode = textFileRead(VShaderFile);
const GLchar *vCodeArray[1] = {vShaderCode};
glShaderSource(vShader,1,vCodeArray,NULL);
//编译着色器对象
glCompileShader(vShader);
//检查编译是否成功
GLint compileResult;
glGetShaderiv(vShader,GL_COMPILE_STATUS,&compileResult);
if (GL_FALSE == compileResult) {
GLint logLen;
//得到编译日志长度
glGetShaderiv(vShader,GL_INFO_LOG_LENGTH,&logLen);
if (logLen > 0) {
char *log = (char *)malloc(logLen);
GLsizei written;
//得到日志信息并输出
glGetShaderInfoLog(vShader,logLen,&written,log);
cerr << "vertex shader compile log : " << endl;
cerr << log << endl;
free(log);//释放空间
}
}
//创建着色器对象:几何着色器
gShader = glCreateShader(GL_GEOMETRY_SHADER);
//错误检测
if (0 == gShader) {
cerr << “ERROR : Create geometry shader failed” << endl;
exit(1);
}
//把着色器源代码和着色器对象相关联
const GLchar *gShaderCode = textFileRead(GShaerFile);
const GLchar *gCodeArray[1] = {gShaderCode};
glShaderSource(gShader,1,gCodeArray,NULL);
//编译着色器对象
glCompileShader(gShader);
//检查编译是否成功
glGetShaderiv(gShader,GL_COMPILE_STATUS,&compileResult);
if (GL_FALSE == compileResult) {
GLint logLen;
//得到编译日志长度
glGetShaderiv(gShader,GL_INFO_LOG_LENGTH,&logLen);
if (logLen > 0) {
char *log = (char *)malloc(logLen);
GLsizei written;
//得到日志信息并输出
glGetShaderInfoLog(gShader,logLen,&written,log);
cerr << "geometry shader compile log : " << endl;
cerr << log << endl;
free(log);//释放空间
}
}
//创建着色器对象:片断着色器
fShader = glCreateShader(GL_FRAGMENT_SHADER);
//错误检测
if (0 == fShader) {
cerr << “ERROR : Create fragment shader failed” << endl;
exit(1);
}
//把着色器源代码和着色器对象相关联
const GLchar *fShaderCode = textFileRead(FShaderFile);
const GLchar *fCodeArray[1] = {fShaderCode};
glShaderSource(fShader,1,fCodeArray,NULL);
//编译着色器对象
glCompileShader(fShader);
//检查编译是否成功
glGetShaderiv(fShader,GL_COMPILE_STATUS,&compileResult);
if (GL_FALSE == compileResult) {
GLint logLen;
//得到编译日志长度
glGetShaderiv(fShader,GL_INFO_LOG_LENGTH,&logLen);
if (logLen > 0) {
char *log = (char *)malloc(logLen);
GLsizei written;
//得到日志信息并输出
glGetShaderInfoLog(fShader,logLen,&written,log);
cerr << "fragment shader compile log : " << endl;
cerr << log << endl;
free(log);//释放空间
}
}
//3、链接着色器对象
//创建着色器程序
programHandle = glCreateProgram();
if (!programHandle) {
cerr << “ERROR : create program failed” << endl;
exit(1);
}
//glProgramParameteriEXT(programHandle, GL_GEOMETRY_VERTICES_OUT, GL_POINTS);
glProgramParameteriEXT(programHandle, GL_GEOMETRY_INPUT_TYPE_EXT, GL_POINTS);
glProgramParameteriEXT(programHandle, GL_GEOMETRY_OUTPUT_TYPE_EXT, GL_LINE_STRIP);
glProgramParameteriEXT(programHandle, GL_GEOMETRY_VERTICES_OUT_EXT, 2);

//将着色器程序链接到所创建的程序中
glAttachShader(programHandle,vShader);
glAttachShader(programHandle,gShader);
glAttachShader(programHandle,fShader);
//将这些对象链接成一个可执行程序
glLinkProgram(programHandle);
//查询链接的结果
GLint linkStatus;
glGetProgramiv(programHandle,GL_LINK_STATUS,&linkStatus);
if (GL_FALSE == linkStatus) {
cerr << “ERROR : link shader program failed” << endl;
GLint logLen;
glGetProgramiv(programHandle, GL_INFO_LOG_LENGTH, &logLen);
if (logLen > 0) {
char *log = (char *)malloc(logLen);
GLsizei written;
glGetProgramInfoLog(programHandle, logLen, &written,log);
cerr << "Program log : " << endl;
cerr << log << endl;
}
}
else {//链接成功,在OpenGL管线中使用渲染程序
glUseProgram(programHandle);
}
}

void initVBO() {
// Create and populate the buffer objects
GLuint vboHandles;
glGenBuffers(1, &vboHandles);
//绑定VBO以供使用
glBindBuffer(GL_ARRAY_BUFFER, vboHandles);
//加载数据到VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(positionData), positionData, GL_STATIC_DRAW);
glGenVertexArraysAPPLE(1, &vaoHandle);
glBindVertexArrayAPPLE(vaoHandle);
GLuint locAttrib = glGetAttribLocation(programHandle, “position”);
glEnableVertexAttribArray(locAttrib);//顶点坐标
glVertexAttribPointer(locAttrib, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), 0);
/GLuint colAttrib = glGetAttribLocation(programHandle, “color”);
glEnableVertexAttribArray(colAttrib);//顶点颜色
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid
)(2 * sizeof(float)));
GLuint sidesAttrib = glGetAttribLocation(programHandle, “sides”);
glEnableVertexAttribArray(sidesAttrib);//顶点颜色
glVertexAttribPointer(sidesAttrib, 1, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(5 * sizeof(float)));*/

}

void init() {
//初始化glew扩展库
GLenum err = glewInit();
if( GLEW_OK != err )
{
cout <<"Error initializing GLEW: " << glewGetErrorString(err) << endl;
}
initShader(“basic.vert”,“basic.frag”, “basic.geom”);
initVBO();
glClearColor(0.0, 0.0, 0.0, 0.0);
//glShadeModel(GL_SMOOTH);
}

void display() {
glClear(GL_COLOR_BUFFER_BIT);
//使用VAO、VBO绘制
//glBindVertexArrayAPPLE(vaoHandle);
//glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawArrays(GL_LINES, 0, 4);
glBindVertexArrayAPPLE(0);
glutSwapBuffers();
}

void keyboard(unsigned char key,int x,int y) {
switch(key) {
case 27:
glDeleteShader(vShader);
glUseProgram(0);
break;
}
}

int main(int argc,char** argv) {
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(600,600);
glutInitWindowPosition(100,100);
glutCreateWindow(“GLSL Test : Draw a triangle”);
init();
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
geometry shader
#version 120
#extension GL_EXT_geometry_shader4 : enable

void main()
{
for(int i = 0; i < 2; i++)
{
gl_Position = gl_PositionIn[0] + vec4(i*-0.1, 0.0, 0.0, 0.0);
EmitVertex();
}
EndPrimitive();
}

Are you sure ? To my opinion they are fully valid for OpenGL 2.x. They were certainly not with OpenGL 1.1, but the user is most certainly not using this version.

But if you use glGetError() you’ll see that your draw call is broken in your new code. Because you changed it to draw GL_LINES, but your geometry shader expects GL_POINTS. Mismatched primitive types throw INVALID_OPERATION.

Also, your display() unbinds the VAO, but the line of code to re-bind it before the draw is commented out, so it will only work for the first time, and draw nothing the second time.

Yes. Those constants were introduced in GL3.0 and are INVALID_ENUM in a GL2 context. On OSX, you must choose to #include either <OpenGL/gl.h> or <OpenGL/gl3.h>, and the compiler will warn if you include both, because it puts you into exactly this situation of using constants (and API) that are invalid for the context profile. But… if you use GLEW or another wrapper, you’re bypassing that mechanism…

It works. Thank you all. According to arekkusu’s suggestion, I modified the “GL_LINES” to “GL_POINTS” in main.cpp.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.