First time round it went really wrong as I mended a couple of const bugs at the same time breaking most of the code.
So thanks to bzr I managed to revert the code and do one thing at a time correctly. The new version seems to work well and the coding standard has been updated to reflect the changes. Not bad for a day's work
Here is a simple python NGL program to draw a teapot using the new style
#!/usr/bin/python
import math
import pdb
from OpenGL.GL import *
from OpenGL.GLU import *
from PyQt4 import QtGui
from PyQt4.QtOpenGL import *
from PyQt4.Qt import Qt
from PyQt4 import QtCore
from PyNGL import *
import sys
import random
class GLWindow(QGLWidget):
def __init__(self, parent):
QGLWidget.__init__(self, parent)
self.setMinimumSize(1024, 720)
self.m_spinYFace = 0
self.m_spinXFace = 0
self.m_origX = 0
self.m_origY = 0
self.m_transformStack=TransformStack()
def mousePressEvent (self, _event) :
# this method is called when the mouse button is pressed in this case we
# store the value where the maouse was clicked (x,y) and set the Rotate flag to true
if(_event.button() == Qt.LeftButton) :
self.m_origX = _event.x();
self.m_origY = _event.y();
self.m_rotate =True;
def mouseMoveEvent ( self,_event ) :
# note the method buttons() is the button state when event was called
# this is different from button() which is used to check which button was
# pressed when the mousePress/Release event is generated
if(self.m_rotate and _event.buttons() == Qt.LeftButton) :
self.m_spinYFace = ( self.m_spinYFace + (_event.x() - self.m_origX) ) % 360
self.m_spinXFace = ( self.m_spinXFace + (_event.y() - self.m_origY) ) % 360
self.m_origX = _event.x();
self.m_origY = _event.y();
# re-draw GL
self.updateGL();
def mouseReleaseEvent (self, _event) :
# this event is called when the mouse button is released
# we then set Rotate to false
if (_event.button() == Qt.LeftButton) :
self.m_rotate=False
def paintGL(self):
'''
Drawing routine
'''
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
trans=Transformation()
# set the mouse rotation
trans.setRotation(self.m_spinXFace,self.m_spinYFace,0)
# set this in the TX stack
self.m_transformStack.setGlobal(trans);
shader=ShaderManager.instance();
shader.setShaderParamFromMatrix("gl3xTest","ModelMatrix",self.m_transformStack.getCurrAndGlobal().getTransposeMatrix());
vbo=VBOPrimitives.instance()
vbo.draw("teapot")
glFlush()
def resizeGL(self, w, h):
'''
Resize the GL window
'''
glViewport(0, 0, w, h)
self.m_cam.setShape(100,float(w/h),0.5,10,CAMERAPROJECTION.PERSPECTIVE)
def initializeGL(self):
'''
Initialize GL
'''
# set viewing projection
ngl=NGLInit.instance()
ngl.initGlew()
glClearColor(0.4, 0.4, 0.4, 1.0)
glClearDepth(1.0)
From=Vector(0,1,1)
To=Vector(0,0,0)
Up=Vector(0,1,0)
self.m_cam=Camera(From,To,Up,CAMERAPROJECTION.PERSPECTIVE)
self.m_cam.setShape(100,1024.0/720.0,0.5,10,CAMERAPROJECTION.PERSPECTIVE);
glEnable(GL_LIGHTING)
glShadeModel(GL_SMOOTH)
glEnable(GL_DEPTH_TEST)
glEnable(GL_NORMALIZE)
glClearColor(0.5,0.5,0.5,1.0)
self.shader=ShaderManager.instance()
# load a frag and vert shaders
self.shader.loadShader("gl3xTest","Vertex.vs","Fragment.fs","")
# set this as the active shader
self.shader.useShader("gl3xTest");
# now pass the modelView and projection values to the shader
self.shader.setShaderParamFromMatrix("gl3xTest","ViewMatrix",self.m_cam.getModelView())
self.shader.setShaderParamFromMatrix("gl3xTest","projectionMatrix",self.m_cam.getProjection())
m=Material(STDMAT.GOLD)
m.use()
self.Light0 = Light(Vector(5,12,0,1),Colour(1,1,1),Colour(1,1,1),LIGHTMODES.LIGHTLOCAL)
self.Light0.enable()
#
# You don't need anything below this
class NGLOpenGLDemo(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.widget = GLWindow(self)
self.setCentralWidget(self.widget)
def keyPressEvent(self ,_event) :
INC=0.1
if _event.key() == Qt.Key_Q :
sys.exit()
elif _event.key() == Qt.Key_W :
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE)
elif _event.key() == Qt.Key_S :
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL)
elif _event.key() == Qt.Key_Up :
self.widget.m_cam.Move(0.0,-INC,0.0)
elif _event.key() == Qt.Key_Down :
self.widget.m_cam.Move(0.0,INC,0.0)
elif _event.key() == Qt.Key_Left :
self.widget.m_cam.Move(INC,0.0,0.0)
elif _event.key() == Qt.Key_Right :
self.widget.m_cam.Move(-INC,0.0,0.0)
elif _event.key() == Qt.Key_I :
self.widget.m_cam.Move(0.0,0.0,INC)
elif _event.key() == Qt.Key_O :
self.widget.m_cam.Move(0.0,0.0,-INC)
self.widget.updateGL()
if __name__ == '__main__':
app = QtGui.QApplication(['Simple NGL Python Demo'])
window = NGLOpenGLDemo()
window.setWindowTitle("PyNGL Demo")
window.show()
app.exec_()
This program relies on two shaders to do basic transformations and blinn style shading. The Vertex shader is as follows
uniform mat4 projectionMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ModelMatrix;
varying vec3 fragmentNormal;
void main(void)
{
fragmentNormal = (ViewMatrix*ModelMatrix*vec4(gl_Normal, 0.0)).xyz;
gl_Position = projectionMatrix*ViewMatrix*ModelMatrix*gl_Vertex;
}
This shader is passed the values calculated for the projection (from the NGL::Camera class) as well as the Model and View transformations.
It will calculate the position of the vertex as well as the fragment normal (based on the normal passed for shading from the teapot model in this case)
The actual shading is done in the fragment shader below
/// @brief[in] the vertex normal
varying vec3 fragmentNormal;
void main ()
{
// set the output colour to black
vec4 colour= vec4(0.0);
// normalize the vertex normal
vec3 N = normalize(fragmentNormal);
// The Light source vector
vec3 L;
// the Halfway vector (used for speed)
vec3 H;
// pre declare the colour contribution values
vec4 ambient;
vec4 diffuse;
vec4 specular;
// get the Light vector
L = normalize(gl_LightSource[0].position.xyz);
// get the halfway vector
H = normalize(gl_LightSource[0].halfVector.xyz);
// ambient just added
ambient = gl_FrontMaterial.ambient *gl_LightSource[0].ambient;
// calculate diffuse based on Lambert's law (L.N)
diffuse = gl_FrontMaterial.diffuse *gl_LightSource[0].diffuse * max(dot(L, N), 0.0);
// calculate specular based on H.N^Shininess
specular = gl_FrontMaterial.specular *gl_LightSource[0].specular * pow(max(dot(H, N), 0.0), gl_FrontMaterial.shininess);
// combine contribution for the light
colour+=ambient+diffuse+specular;
// finally set the colour clamping between 0 and 1
gl_FragColor = clamp(vec4(colour),0.0,1.0);
}
This shader calculates the shading values based on the 1st GL light in the scene. It calculates ambient diffuse and specular contributions based on the current openGL material passed from the NGL::Material class.
We use a basic diffuse / lambert shading model for the diffuse contribution and the half way vector for the specular shading to mimic Phong / Blinn reflections.
And finally a golden teapot

No comments:
Post a Comment