After a fairly long Google Session I have enough from it!
I had a python/opengl application with some simple Quad's where I used gluLookAt to move around on the scene. Then I needed just 1 Texture on one of those Quad's, so I obviously use a shader progam for this single Quad now.
Now when I use gluLookAt, the Quad with the Texture doesn't move, what I also can understand.
Now is there any way to somehow get the gluLookAt function to working with the shader program, get the Current Matrix Stack so I can feed the shader programm with it or do I have to rewrite the hole application and reinvent the glulookup function like he did(either in the shader or on the CPU)?
EDIT1: I use:
python 3.5
PyOpenGL 3.1.0
GLSL 1.4 (According to this list)
EDIT2 (My Solution):
Since I opened this thread, some things have changed but with the guideance of you I managed to get a modern & stable solution.
There are 3 Main components which I have to draw. A static Field, some Lines (for better visualisation) and some Movable Quads.
The Field is now written once to a VBO in an Array. (major improvement compared to single drawing commands)
The moveable squares and lines work on the same principle, but they are dynamic and must be reuploaded with each frame.
Foreach type of object I have a vertex + fragment shader program. I'am aware that I could use just one big one but that's not like it's supposed to be.
Each Matrix (Model,View,Projection) Is assigned to a uniform which then are multiplied with the Vertices from the VBO in the vertex shader.
Field Vertex Shader (Example):
#version 330
uniform mat4 uniform_Model;
uniform mat4 uniform_View;
uniform mat4 uniform_Projection;
in vec3 Quad_Color_Attrib;
in vec3 Quad_Size_Attrib;
out vec3 frag_ColorId;
void main()
{
// Pass the tex coord straight through to the fragment shader
frag_ColorId = Quad_Color_Attrib;
// Remember : inverted !
gl_Position = uniform_Projection * uniform_View * uniform_Model * vec4(Quad_Size_Attrib,1);
}
What I asked for wasn't the right way to do it. (Combining old and new OpenGL) Unfortunatly I can't share the hole code as it is but I here you can find all opengl key codes:
Vertex/Fragment Shader Program Loader:
Initialize Vertex/Fragment Shader (in this case for the field)
def init_field(self, p_VertexShaderPath, p_FragmentShaderPath, p_FieldList, p_FieldCount):
# ############### Field Shader ###############
# Shader Program
self.m_FieldShader = LoadShaders(p_VertexShaderPath, p_FragmentShaderPath)
glUseProgram(self.m_FieldShader)
# VAO
self.m_FieldVAO = glGenVertexArrays(1)
glBindVertexArray(self.m_FieldVAO)
# Field Definition
self.m_FieldCount = p_FieldCount
t_Vertices = []
for t_FieldNr in p_FieldList:
x = p_FieldList[t_FieldNr].m_XPos
y = p_FieldList[t_FieldNr].m_YPos
cr = p_FieldList[t_FieldNr].m_Color[0]/255
cg = p_FieldList[t_FieldNr].m_Color[1]/255
cb = p_FieldList[t_FieldNr].m_Color[2]/255
t_Vertices.extend([
x - 0.5, y + 0.5, 0.0, cr, cg, cb, # 0----1
x + 0.5, y + 0.5, 0.0, cr, cg, cb, # | |
x + 0.5, y - 0.5, 0.0, cr, cg, cb, # | |
x - 0.5, y - 0.5, 0.0, 0, 0, 0 # 3----2
])
t_FieldVerticesBuffer = numpy.array(t_Vertices, dtype = numpy.float32)
# VBO
self.m_FieldVBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, self.m_FieldVBO)
glBufferData(GL_ARRAY_BUFFER, t_FieldVerticesBuffer.nbytes, t_FieldVerticesBuffer, GL_STATIC_DRAW)
# VBO Size Attrib
self.m_FieldVerticesAttrib = glGetAttribLocation(self.m_FieldShader, "Quad_Size_Attrib")
glEnableVertexAttribArray(self.m_FieldVerticesAttrib)
glVertexAttribPointer(self.m_FieldVerticesAttrib,
3,
GL_FLOAT,
GL_FALSE,
ctypes.sizeof(6*GLfloat),
ctypes.c_void_p(0))
# VBO Color Attrib
self.m_FieldColorAttrib = glGetAttribLocation(self.m_FieldShader, "Quad_Color_Attrib")
glEnableVertexAttribArray(self.m_FieldColorAttrib)
glVertexAttribPointer(self.m_FieldColorAttrib,
3,
GL_FLOAT,
GL_FALSE,
ctypes.sizeof(6*GLfloat),
ctypes.c_void_p(12))
# Uniform Locations
self.m_Field_ModelMat_Uniform = glGetUniformLocation(self.m_FieldShader, 'uniform_Model')
self.m_Field_ViewMat_Uniform = glGetUniformLocation(self.m_FieldShader, 'uniform_View')
self.m_Field_ProjectionMat_Uniform = glGetUniformLocation(self.m_FieldShader, 'uniform_Projection')
# Detach Shader & VAO
glBindVertexArray(0) # unbind the VAO
glUseProgram(0) # Disable shader
Screen Draw Cycle
This now is just psydo code:
OpenGLEnv.Clear()
OpenGLEnv.SetCamera()
OpenGLEnv.DrawField()
OpenGLEnv.FlipBuffer()
So SetCamera set's the ViewMat and ProjectionMat.
def SetCamera(self, camera, zoom_distance):
self.m_ViewMat = lookAt(glm.vec3(-camera[0], -camera[1], zoom_distance), # Camera is at (x,x,x), in World Space
glm.vec3(-camera[0], -camera[1], -100), # and looks at the origin
glm.vec3(0, 1, 0)) # Head is up (set to 0,-1,0 to look upside-down)
self.m_ProjectionMat = perspective(45, self.m_AspectRatio, 1, 1000.0)
Draw Field Routine
With this Function I will draw the Vertices from the VBO.
def DrawField(self):
glUseProgram(self.m_FieldShader) # Use shader
self.m_ModelMat = glm.mat4(1) # Reset ModelMat
# ############################
# 1. Scale self.ModelMat = scale(self.ModelMat,glm.vec3(10,10,10))
# 2. Rotation self.ModelMat = rotate(self.ModelMat, self.test, glm.vec3(0,1,0))
# 3. Translate self.ModelMat = translate(self.ModelMat,glm.vec3(0,0,0))
####################################
glUniformMatrix4fv(self.m_Field_ModelMat_Uniform, 1, GL_FALSE, numpy.squeeze(numpy.asarray(self.m_ModelMat.value)))
glUniformMatrix4fv(self.m_Field_ViewMat_Uniform, 1, GL_FALSE, numpy.squeeze(numpy.asarray(self.m_ViewMat.value)))
glUniformMatrix4fv(self.m_Field_ProjectionMat_Uniform, 1, GL_FALSE, numpy.squeeze(numpy.asarray(self.m_ProjectionMat.value)))
glBindVertexArray(self.m_FieldVAO)
glBindBuffer(GL_ARRAY_BUFFER, self.m_FieldVBO)
# Draw Field
glDrawArrays(GL_QUADS, 0, 4*self.m_FieldCount)
# Disable shader and unbind VAO
glBindVertexArray(0)
glUseProgram(0)
Used Librarys:
- GLM (I think it was this one https://github.com/Zuzu-Typ/PyGLM)
- OpenGL (PyOpenGL 3.1.0)
- Numpy
- Math
You may decide :
You may use OpenGL 2, what makes things much easier and means no shader programming but less efficiency.
If you have to draw at least 1000 triangles or want to add bumpmapping or other special effects, you should maybe consider a shader. That means :
uniform mat4 modelviewMatrix;, which has to be multiplied with your vertex position. http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/#the-model-matrixDo not use Python & Pyopengl if you are aiming at high efficiency(own experience)
I will maybe also port my camera class to Python, but it depends on the jogl Matrix4 class and so on, but is easy if pyopengl also offers this math helper classes(Matrix4, Quaternion, ...)
EDIT :
Vertex Shader :
Fragment Shader :
About the matrices :
uniform_Transformationis the Transformation matrix. It is used to rotate, scale, flip, mirror and move your models, in your case quads.uniform_Modelviewis the View matrix. It's basically the camera. It defines how the camera is rotated and where it is located.uniform_Projectionis the Projection matrix. It's about the perspective projection. Read more about it here : http://www.songho.ca/opengl/gl_projectionmatrix.htmlHope it helps !