问题
I'm trying to use geometry shaders to turn points into line segments (GL_POINTS to GL_LINE_STRIP), but no line segments appear. If I change the input to GL_LINES, and just repeat the vertex, then I get the behavior I'm expecting. What's going on?
Here's a complete program that demonstrates the behavior. As-is, I get nothing but a black window. Setting USE_POINTS to False gets me the rotating psychedelic flashing lines I'm expecting.
#!/usr/bin/python
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from OpenGL.GL.ARB.geometry_shader4 import *
from OpenGL.GL.EXT.geometry_shader4 import *
import Image
import numpy
import numpy.linalg as linalg
import random
from math import sin, cos
shader = None
USE_POINTS = True
def update(*args):
glutTimerFunc(33, update, 0)
glutPostRedisplay()
def display():
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
t = glutGet(GLUT_ELAPSED_TIME)
rot = t % (10 * 1000)
theta = 2 * 3.141592 * (rot / 10000.0)
glLoadIdentity()
gluLookAt(-10*sin(theta), -10*cos(theta), 0,
0, 0, 0,
0, 0, 1)
glUseProgram(shader)
glUniform1f(glGetUniformLocation(shader, "distance"), rot/10000.0)
# difference #1
glBegin(GL_POINTS if USE_POINTS else GL_LINES)
for x in [-2.5, 0, 2.5]:
for y in [-2.5, 0, 2.5]:
glVertexAttrib1f(7, random.uniform(0.0, 1.0))
glVertexAttrib3f(0, x, y, 0)
# difference #2
if not USE_POINTS:
glVertexAttrib1f(7, random.uniform(0.0, 1.0))
glVertexAttrib3f(0, x, y, 0)
glEnd()
glUseProgram(0)
glutSwapBuffers()
def key(*args):
if args[0] == '\x1b':
sys.exit(0);
def reshape(width, height):
aspect = float(width)/float(height) if (height>0) else 1.0
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45.0,
aspect,
1.0, 100.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glutPostRedisplay()
glutInit([])
glutInitDisplayString("rgba>=8 depth>16 double")
glutInitWindowSize(1280, 720)
glutCreateWindow("Geometry Shader")
glutDisplayFunc(display)
glutReshapeFunc(reshape)
glutKeyboardFunc(key)
glutTimerFunc(33, update, 0)
glEnable(GL_DEPTH_TEST)
glEnable(GL_POINT_SMOOTH)
glEnable(GL_LINE_SMOOTH)
shader = glCreateProgram()
vertex_shader = glCreateShader(GL_VERTEX_SHADER)
geometry_shader = glCreateShader(GL_GEOMETRY_SHADER)
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER)
# difference #3
glProgramParameteriEXT(shader, GL_GEOMETRY_INPUT_TYPE_ARB, GL_POINTS if USE_POINTS else GL_LINES)
glProgramParameteriEXT(shader, GL_GEOMETRY_OUTPUT_TYPE_ARB, GL_LINE_STRIP)
glProgramParameteriEXT(shader, GL_GEOMETRY_VERTICES_OUT_ARB, 200)
glAttachShader(shader, vertex_shader)
glAttachShader(shader, geometry_shader)
glAttachShader(shader, fragment_shader)
glShaderSource(vertex_shader, """
attribute float color;
varying float geom_color;
void main(void) {
gl_Position = gl_Vertex;
geom_color = color;
}
""")
glCompileShader(vertex_shader)
print glGetShaderInfoLog(vertex_shader)
glShaderSource(geometry_shader, """
#version 120
#extension GL_EXT_geometry_shader4 : enable
varying in float geom_color[1];
varying out float frag_color;
uniform float distance;
void main(void)
{
int x, y;
for(x=-1; x<=1; x+=1) {
for(y=-1; y<=1; y+=1) {
gl_Position = gl_PositionIn[0];
gl_Position.x += x * distance;
gl_Position.y += y * distance;
gl_Position.z -= 2.0;
gl_Position = gl_ModelViewProjectionMatrix * gl_Position;
frag_color = geom_color[0];
EmitVertex();
gl_Position = gl_PositionIn[0];
gl_Position.x += x * distance;
gl_Position.y += y * distance;
gl_Position.z += 2.0;
gl_Position = gl_ModelViewProjectionMatrix * gl_Position;
frag_color = geom_color[0];
EmitVertex();
EndPrimitive();
}
}
}
""")
glCompileShader(geometry_shader)
print glGetShaderInfoLog(geometry_shader)
glShaderSource(fragment_shader, """
varying float frag_color;
void main(void) {
gl_FragColor = vec4(frag_color,1.0-frag_color,frag_color,1);
}
""")
glCompileShader(fragment_shader)
print glGetShaderInfoLog(fragment_shader)
glLinkProgram(shader)
print glGetProgramInfoLog(shader)
glBindAttribLocation(shader, 7, "color")
glLinkProgram(shader)
print glGetProgramInfoLog(shader)
glutMainLoop()
回答1:
I cross-checked the code with the GL_EXT_geometry_shader4 specification, and I don't see any obvious errors at least. According to the specification, all input primitives work with all types of output primitives. If OpenGL returns no errors via glGetError, and no shader linker/compilation errors, I'd say this is an ATI or pyOpenGL-related issue.
I'm fairly sure I've tested most combinations of input and output primitives for geometry shaders, and they all work on my Nvidia card. I use the native C OpenGL libraries though, not a binding.
回答2:
I got the same problem just now with HD4850. It seems weird but the problem really has a cause and can be resolved. It looks like this is not the same situation as the original post. Just FYI when someone else happens to reach this post blocked by similar situations.
Here goes the cause. When GL_GEOMETRY_INPUT_TYPE_ARB is set to GL_POINTS, in the geometry shader code, there is code accessing the input array beyond 0.
Vertex Shader
in ivec4 vertex;
flat out ivec4 v;
Geometry Shader
flat in ivec4 v[gl_VerticesIn];
// somewhere in the code
v[1].x ...
Everything goes fine with compile/link, but glGetAttribLocationARB fails for the "vertex" attribute.
来源:https://stackoverflow.com/questions/3936368/geometry-shader-doesnt-do-anything-when-fed-gl-points