GLuint ShaderProgramBuilder::loadShaderProgram(GLenum shaderType, const char * pSource)
{
    GLuint shader = glCreateShader(shaderType);
    GL_ERROR_CHECK("ShaderProgramBuilder:Create Shader");
    if (shader)
        {
            glShaderSource(shader, 1, &pSource, NULL);
            glCompileShader(shader);
            GLint compiled = 0;
            glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
            if (!compiled)
                {
                    GLint infoLen = 0;
                    glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
                    if (infoLen)
                        {
                            GL_ERROR_CHECK("ShaderProgramBuilder:Failed on Compile Shader");
                            char* buf = new char[infoLen];
                            if (buf)
                                {
                                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
                                    LOG_ERROR("Could not compile shader %d:\n%s\n", shaderType, buf);
                                    delete buf;
                                }
                            glDeleteShader(shader);
                            shader = 0;
                        }
                }
        }
    else
        {
            LOG_ERROR("Create shader error!\n");
        }
    return shader;
}
Beispiel #2
0
static PyObject* opengl_startdraw( PyObject* self, PyObject* args )
{
    PyObject* clear_color;

    query_object = NULL;

    GL_ERROR_CHECK( "top of opengl_startdraw" );
    
    if ( !PyArg_ParseTuple( args, "O|O", &clear_color, &query_object ) )
	return NULL;

    if ( query_object )
    {
	if ( !PyTuple_Check( query_object ) || PyTuple_GET_SIZE(query_object) % 2 != 0 )
	{
	    PyErr_SetString( PyExc_ValueError, "bad query object" );
	    return NULL;
	}
    }

    if ( PyTuple_Check( clear_color ) && PyTuple_Size( clear_color ) == 4 )
    {
	glClearColor( (float)PyFloat_AsDouble( PyTuple_GetItem( clear_color, 0 ) ),
		      (float)PyFloat_AsDouble( PyTuple_GetItem( clear_color, 1 ) ),
		      (float)PyFloat_AsDouble( PyTuple_GetItem( clear_color, 2 ) ),
		      0.0 );
    }
    else
	glClearColor( 1.0, 1.0, 1.0, 0.0 );
    
    glClearStencil( 0 );
    glDisable( GL_STENCIL_TEST );
    glClearDepth( 0.0 );
    glDepthMask( GL_TRUE );
    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );

    glColor4d( 0.0, 0.0, 0.0, 1.0 );
    glLineWidth( 1.0 );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    /* left, right, bottom, top, zNear, zFar (in distance from eye) */
    glOrtho( -window_aspect, window_aspect, -1.0, 1.0, 0.0, 1.0 ); 
    glPushMatrix();

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    glReadBuffer( GL_BACK );
    
    GL_ERROR_CHECK( "after opengl_redraw setup" );

    Py_INCREF( Py_None );
    return Py_None;
}
Beispiel #3
0
static void free_old_textures( void )
{
    GL_ERROR_CHECK( "top of free_old" );
    
    if ( old_textures_used > 0 )
    {
	glDeleteTextures( old_textures_used, old_textures );
	old_textures_used = 0;
    }

    GL_ERROR_CHECK( "bottom of free_old" );
}
Beispiel #4
0
static int make_texture( ImageObject* obj )
{
    int bound = 0;
    
    free_old_textures();
    
    if ( obj->has_texture == 0 )
    {
	GLuint t;

	glGenTextures( 1, &t );

	glBindTexture( GL_TEXTURE_2D, t );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
	glTexImage2D( GL_TEXTURE_2D, 0, obj->has_alpha ? GL_RGBA : GL_RGB,
		      obj->tw, obj->th, 0, obj->has_alpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE,
		      obj->data );

	GL_ERROR_CHECK( "draw_image - created texture" );
	
	obj->texture = t;
	obj->has_texture = 1;
	bound = 1;

	free( obj->data );
	obj->data = NULL;
    }

    return bound;
}
void UBOShaderInterface::Create(const std::string &uniformBlockName, Shader* shader, const char** uniformNames, GLsizei numUniformNames)
{
	m_pShader = shader;

	m_blockIndex = glGetUniformBlockIndex(m_pShader->GetProgID(), uniformBlockName.c_str());

	assert(m_blockIndex != GL_INVALID_INDEX);

	glGetActiveUniformBlockiv(m_pShader->GetProgID(), m_blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &m_blockSize);

	GLuint* indices = new GLuint[numUniformNames];

	glGetUniformIndices(m_pShader->GetProgID(), numUniformNames, uniformNames, indices);

	// Query offsets and associate names to the offsets
	int* offsets = new int[numUniformNames];

	glGetActiveUniformsiv(m_pShader->GetProgID(), numUniformNames, indices, GL_UNIFORM_OFFSET, offsets);

	delete[] indices;

	for(size_t i = 0; i < numUniformNames; i++)
		m_uniformNameToOffset[uniformNames[i]] = offsets[i];

	delete[] offsets;

	GL_ERROR_CHECK();
}
void NormalWrapper::setup()
{
    shaderProgram = loadShaderProgram("assets/shaders/normal.vert", "assets/shaders/normal.frag", { "in_pos", "in_color" });

    float posColorVertices[]{
        -0.25f, -0.25f, 0.f, 0.f, 0.f, 1.f, 1.f,
        0.25f, -0.25f, 0.f, 0.f, 0.f, 1.f, 1.f,
        -0.25f, 0.25f, 0.f, 0.f, 0.f, 1.f, 1.f,
        0.25f, 0.25f, 0.f, 0.f, 0.f, 1.f, 1.f
    };

    constexpr size_t vertexSize = sizeof(float) * 7;
    constexpr uint8_t vertexCount = 4;
    mesh.renderMode = GL_TRIANGLE_STRIP;

    glGenVertexArrays(1, &mesh.vao);
    glBindVertexArray(mesh.vao);

    glGenBuffers(1, &mesh.vbo);
    glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo);
    glBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, &posColorVertices, GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertexSize, 0);

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, vertexSize, reinterpret_cast<const void*>(12));

    mesh.vertexCount = vertexCount;

    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    GL_ERROR_CHECK();
}
Beispiel #7
0
void CreateRenderTarget(int width, int height)
{
    printf("Render Target size %d x %d\n", width, height);

    // create a fbo
    glGenFramebuffers(1, &s_fbo);

    GL_ERROR_CHECK("RenderTargetInit1");

    // create a depth buffer
    glGenRenderbuffers(1, &s_fboDepth);

    GL_ERROR_CHECK("RenderTargetInit2");

    // bind fbo
    glBindFramebuffer(GL_FRAMEBUFFER, s_fbo);

    GL_ERROR_CHECK("RenderTargetInit3");

    glGenTextures(1, &s_fboTex);
    glBindTexture(GL_TEXTURE_2D, s_fboTex);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);

    // attach texture to fbo
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                           GL_TEXTURE_2D, s_fboTex, 0);

    // init depth buffer
    glBindRenderbuffer(GL_RENDERBUFFER, s_fboDepth);

    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, s_fboDepth);

    // check status
    assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);

    GL_ERROR_CHECK("RenderTargetInit");
}
GLuint ShaderProgramBuilder::buildShaderProgram(const char * pVertexSource, const char * pFragmentSource)
{
    GLuint vertexShader = loadShaderProgram(VERTEX_SHADER, pVertexSource);
    if (!vertexShader)
        return false;
    LOG_INFO("Render=> Pass Build Vertex Shader\n");

    GLuint pixelShader = loadShaderProgram(FRAGMENT_SHADER, pFragmentSource);
    if (!pixelShader)
        return false;
    LOG_INFO("Render=> Pass Build Fragment Shader\n");

    GLuint program = glCreateProgram();
    GL_ERROR_CHECK("ShaderProgramBuilder:Create Program");
    if (program)
        {
            glAttachShader(program, vertexShader);
            glAttachShader(program, pixelShader);
            GL_ERROR_CHECK("ShaderProgramBuilder:Attach Program");

            glLinkProgram(program);
            GL_ERROR_CHECK("ShaderProgramBuilder:Link Program");

            GLint linkStatus = GL_FALSE;
            glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
            if (linkStatus != GL_TRUE)
                {
                    GLint bufLength = 0;
                    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
                    if (bufLength)
                        {
                            char* buf = new char[bufLength];
                            if (buf)
                                {
                                    glGetProgramInfoLog(program, bufLength, NULL, buf);
                                    LOG_ERROR("Could not link program:\n%s\n", buf);
                                    delete buf;
                                }
                        }

                    glDeleteProgram(program);
                    program = 0;
                }
        }
    return program;
}
Beispiel #9
0
 void VertexArrayObject::disableVertexAttribArray(GLuint index)
 {
     glDisableVertexAttribArray(index);
     std::vector<GLuint>::iterator ind = std::find(
         mImpl->vertexArrays.begin(), mImpl->vertexArrays.end(), index);
     mImpl->vertexArrays.erase(ind);
     GL_ERROR_CHECK();
 }
Beispiel #10
0
        void VertexArrayObject::enableVertexAttribArray(GLuint index)
        {
            std::vector<GLuint>::iterator ind = std::find(
                mImpl->vertexArrays.begin(), mImpl->vertexArrays.end(), index);
            if (ind != mImpl->vertexArrays.end())
            {
                WARN_LOG("The vertex attribute array at index " +
                    std::to_string(index) + " has already been bound");
                return;
            }

            glEnableVertexAttribArray(index);
            mImpl->vertexArrays.push_back(index);
            GL_ERROR_CHECK();
        }
Beispiel #11
0
static PyObject* opengl_reshape( PyObject* self, PyObject* args )
{
    if ( !PyArg_ParseTuple( args, "ii", &window_width, &window_height ) )
	return NULL;

    window_aspect = window_width / (double)window_height;
    
    glViewport( 0, 0, window_width, window_height );
    GL_ERROR_CHECK( "glViewport" );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    
    Py_INCREF( Py_None );
    return Py_None;
}
void InstanceWrapper::setup()
{
    shaderProgram = loadShaderProgram("assets/shaders/instanced.vert", "assets/shaders/instanced.frag", { "in_sPos", "in_pos" });

    float posVertices[]{
        -0.25f, -0.25f, 0.f,
        0.25f, -0.25f, 0.f,
        -0.25f, 0.25f, 0.f,
        0.25f, 0.25f, 0.f
    };

    constexpr size_t vertexSize = sizeof(float) * 3;
    constexpr uint8_t vertexCount = 4;
    mesh.renderMode = GL_TRIANGLE_STRIP;

    glGenVertexArrays(1, &mesh.vao);
    glBindVertexArray(mesh.vao);

    // Instanced
    constexpr size_t instanceSize = sizeof(float) * 3;
    glGenBuffers(1, &mesh.instanceVBO);
    glBindBuffer(GL_ARRAY_BUFFER, mesh.instanceVBO);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, instanceSize, 0);
    glVertexAttribDivisor(0, 1);

    // Normal
    glGenBuffers(1, &mesh.vbo);
    glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo);
    glBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, &posVertices, GL_STATIC_DRAW);

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertexSize, 0);

    mesh.vertexCount = vertexCount;

    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    GL_ERROR_CHECK();
}
GLuint loadShaderProgram(const std::string& vsPath, const std::string& fsPath, const std::vector<std::string>& attributes)
{
    GLuint vsID = glCreateShader(GL_VERTEX_SHADER);
    GLuint fsID = glCreateShader(GL_FRAGMENT_SHADER);

    // Compile Vertex Shader
    std::string source = readAsString(vsPath);
    char const* vsSource = source.c_str();
    glShaderSource(vsID, 1, &vsSource, nullptr);
    glCompileShader(vsID);

    Logger::shaderErrorCheck(vsID, vsPath);

    // Compile Fragment Shader
    source = readAsString(fsPath);
    char const* fsSource = source.c_str();
    glShaderSource(fsID, 1, &fsSource, nullptr);
    glCompileShader(fsID);

    Logger::shaderErrorCheck(fsID, fsPath);

    GLuint programID = glCreateProgram();

    glAttachShader(programID, vsID);
    glAttachShader(programID, fsID);

    GLuint index = 0;
    for (auto& attribute : attributes)
        glBindAttribLocation(programID, index++, attribute.c_str());

    glLinkProgram(programID);

    Logger::programErrorCheck(programID, vsPath, fsPath);

    glDeleteShader(vsID);
    glDeleteShader(fsID);

    GL_ERROR_CHECK();

    return programID;
}
Beispiel #14
0
static void draw_image( ImageObject* obj, double x, double y, double w, double h, double ax, double ay )
{
    GL_ERROR_CHECK( "top of draw_image" );

    // would like to save GL_TEXTURE_BIT as well, but it tweaks a bug in
    // ATI's radeon 7500 drivers.
    
    glPushAttrib( GL_ENABLE_BIT | GL_TRANSFORM_BIT );
    glEnable( GL_TEXTURE_2D );

    if ( ! make_texture( obj ) )
	glBindTexture( GL_TEXTURE_2D, obj->texture );

    glMatrixMode( GL_MODELVIEW );
    glPushMatrix();
    glTranslated( x - w * ax, y - h * ay, 0 );

    glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

    glBegin( GL_QUADS );

    glTexCoord2d( 0.0, obj->tbottom );
    glVertex2d( 0, 0 );

    glTexCoord2d( obj->tright, obj->tbottom );
    glVertex2d( w, 0 );

    glTexCoord2d( obj->tright, 0.0 );
    glVertex2d( w, h );

    glTexCoord2d( 0.0, 0.0 );
    glVertex2d( 0, h );

    glEnd();

    glPopMatrix();
    glPopAttrib();
}
Beispiel #15
0
void 
draw(Widget w)
{
    GLfloat         red, green, blue;
    int             i;

    glClear(GL_DEPTH_BUFFER_BIT);

    /* paint black to blue smooth shaded polygon for background */
    glDisable(GL_DEPTH_TEST);
    glShadeModel(GL_SMOOTH);
    glBegin(GL_POLYGON);
    glColor3f(1.0, 1.0, 1.0);
    glVertex3f(-20, 20, -19);
    glVertex3f(20, 20, -19);
    glColor3f(0.0, 0.0, 1.0);
    glVertex3f(20, -20, -19);
    glVertex3f(-20, -20, -19);
    glEnd();

    glEnable(GL_DEPTH_TEST);
    glShadeModel(GL_FLAT);

    glPushMatrix();
    glTranslatef(0, 0, -distance);
    glRotatef(angle, 0, 0, 1);
    glRotatef(wobble_angle, 0, 1, 0);
    glCallList(base);
    glPopMatrix();

    if (doubleBuffer)
	glXSwapBuffers(dpy, XtWindow(w));
    if (!glXIsDirect(dpy, cx))
	glFinish();		/* avoid indirect rendering latency from
				 * queuing */
    GL_ERROR_CHECK();
}
Beispiel #16
0
 void VertexArrayObject::bindVertexArray()
 {
     glBindVertexArray(mImpl->handle);
     GL_ERROR_CHECK();
 }
Beispiel #17
0
static PyObject* opengl_init( PyObject* self, PyObject* args )
{
    GL_ERROR_CHECK("top of opengl_init");
    printf( "     vendor : %s\n", glGetString( GL_VENDOR ) );
    printf( "   renderer : %s\n", glGetString( GL_RENDERER ) );
    printf( "    version : %s\n", glGetString( GL_VERSION ) );
    printf( "glu version : %s\n", gluGetString( GLU_VERSION ) );
    /*printf( "extensions : %s\n", glGetString( GL_EXTENSIONS ) );*/
    
    glewExperimental=GL_TRUE;
    GLenum err = glewInit();
    if (GLEW_OK != err)
      {
	/* Problem: glewInit failed, something is seriously wrong. */
	printf("Error: %s\n", glewGetErrorString(err));

      }
    printf("Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));

    if (glewIsSupported("GLX_SGI_swap_control"))
      {
	/* It is safe to use the ARB_vertex_program extension here. */
	printf("GLX_SGI_swap_control supported!\n");
	//glXSwapIntervalSGI(1);
      }
    else
      {
	printf("No GLX_SGI_swap_control support.\n");
      }


    if (glewIsSupported("GLX_SGI_video_sync"))
      {
	/* It is safe to use the ARB_vertex_program extension here. */
	printf("GLX_SGI_video_sync supported!\n");
	//glXSwapIntervalSGI(1);

	int retraceCount;
        glXGetVideoSyncSGI(&retraceCount);
	glXWaitVideoSyncSGI(2, (retraceCount+1)%2, &retraceCount);


      }
    else
      {
	printf("GLX_SGI_video_sync support.\n");
	int c;
	//__glewXWaitVideoSyncSGI(5,0,&c);
      }



    glEnable( GL_VERTEX_ARRAY );
    /* on mac, we expect that to fail; must be enabled as 
       client state instead, */
    if(glGetError() != GL_NO_ERROR) {
      glEnableClientState( GL_VERTEX_ARRAY );
      GL_ERROR_CHECK( "enable client gl_vertex_array" );
    }
    glEnable( GL_BLEND );
    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

    glEnable( GL_DEPTH_TEST );
    glDepthFunc( GL_ALWAYS );

    glClearDepth( 0.0 );
    GL_ERROR_CHECK( "end of opengl_init" );
    

    //glEnable( GL_POLYGON_SMOOTH );
    
    Py_INCREF( Py_None );
    return Py_None;
}
World::World()
	: m_created(false),
	m_lightVec(0.4f, -0.5f, -0.7f),
	m_ambient(0.1f),
	m_pPhysicsWorld(NULL), m_pathFindingThreadPool(8), m_AOSampleDistance(6.0f),
	m_AOSampleAngle(pif / s_numAOSamples)
{
	m_lightVec = m_lightVec.Normalize();

	// Generate normals
	m_normals[0] = Vec3f(1.0f, 0.0f, 0.0f);
	m_normals[1] = Vec3f(-1.0f, 0.0f, 0.0f);
	m_normals[2] = Vec3f(0.0f, 1.0f, 0.0f);
	m_normals[3] = Vec3f(0.0f, -1.0f, 0.0f);
	m_normals[4] = Vec3f(0.0f, 0.0f, 1.0f);
	m_normals[5] = Vec3f(0.0f, 0.0f, -1.0f);

	// Generate test offsets
	m_positionOffsets[0] = Point3i(1, 0, 0);
	m_positionOffsets[1] = Point3i(-1, 0, 0);
	m_positionOffsets[2] = Point3i(0, 1, 0);
	m_positionOffsets[3] = Point3i(0, -1, 0);
	m_positionOffsets[4] = Point3i(0, 0, 1);
	m_positionOffsets[5] = Point3i(0, 0, -1);

	// Generate corners
	float cornerDist = 0.5f;

	m_corners[0][0] = Vec3f(cornerDist, -cornerDist, cornerDist);
	m_corners[0][1] = Vec3f(cornerDist, -cornerDist, -cornerDist);
	m_corners[0][2] = Vec3f(cornerDist, cornerDist, -cornerDist);
	m_corners[0][3] = Vec3f(cornerDist, cornerDist, cornerDist);

	m_corners[1][0] = Vec3f(-cornerDist, -cornerDist, -cornerDist);
	m_corners[1][1] = Vec3f(-cornerDist, -cornerDist, cornerDist);
	m_corners[1][2] = Vec3f(-cornerDist, cornerDist, cornerDist);
	m_corners[1][3] = Vec3f(-cornerDist, cornerDist, -cornerDist);

	m_corners[2][0] = Vec3f(-cornerDist, cornerDist, -cornerDist);
	m_corners[2][1] = Vec3f(-cornerDist, cornerDist, cornerDist);
	m_corners[2][2] = Vec3f(cornerDist, cornerDist, cornerDist);
	m_corners[2][3] = Vec3f(cornerDist, cornerDist, -cornerDist);

	m_corners[3][0] = Vec3f(-cornerDist, -cornerDist, cornerDist);
	m_corners[3][1] = Vec3f(-cornerDist, -cornerDist, -cornerDist);
	m_corners[3][2] = Vec3f(cornerDist, -cornerDist, -cornerDist);
	m_corners[3][3] = Vec3f(cornerDist, -cornerDist, cornerDist);

	m_corners[4][0] = Vec3f(-cornerDist, -cornerDist, cornerDist);
	m_corners[4][1] = Vec3f(cornerDist, -cornerDist, cornerDist);
	m_corners[4][2] = Vec3f(cornerDist, cornerDist, cornerDist);
	m_corners[4][3] = Vec3f(-cornerDist, cornerDist, cornerDist);

	m_corners[5][0] = Vec3f(cornerDist, -cornerDist, -cornerDist);
	m_corners[5][1] = Vec3f(-cornerDist, -cornerDist, -cornerDist);
	m_corners[5][2] = Vec3f(-cornerDist, cornerDist, -cornerDist);
	m_corners[5][3] = Vec3f(cornerDist, cornerDist, -cornerDist);

	// Generate chunk occlusion query
	glGenQueriesARB(1, &m_chunkOcclusionQueryID);

	GL_ERROR_CHECK();

	m_unmanagedName = "world";

	GetSphereDistribution(m_sphereDistribution);
}
Beispiel #19
0
static PyObject* opengl_enddraw( PyObject* self, PyObject* args )
{
    char* filename = NULL;

    if ( !PyArg_ParseTuple( args, "|s", &filename ) )
	return NULL;

    GL_ERROR_CHECK( "top of opengl_enddraw" );

#if 0
    {
	GLfloat d;
	glReadPixels( 400, 300, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &d );
	printf( "-- enddraw %.16f\n", d );
    }
#endif

    
    glMatrixMode( GL_PROJECTION );
    glPopMatrix();
    
    if ( query_object )
    {
	PyObject* result;
	int n = PyTuple_GET_SIZE( query_object );
	int i, x, y;
	GLfloat d;
	GLint depth_bits;
	unsigned int id;
	
	glGetIntegerv( GL_DEPTH_BITS, &depth_bits );
	
	result = PyTuple_New( n / 2 );
	for( i = 0; i < n/2; ++i )
	{
	    x = PyInt_AsLong( PyTuple_GET_ITEM( query_object, i*2 ) );
	    y = PyInt_AsLong( PyTuple_GET_ITEM( query_object, i*2+1 ) );
	    
	    glReadPixels( x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &d );
	    id = (unsigned int)(d * (1<<(depth_bits-2)));

	    PyTuple_SET_ITEM( result, i, PyInt_FromLong(id) );
	}

        GL_ERROR_CHECK( "another end to opengl_enddraw" );
	return result;
    }
    
    SoggySwap();

    if ( filename )
    {
	static PyObject* module;
	PyObject* im;
	PyObject* ret;
	PyObject* data;
	
	fprintf( stderr, "saving to [%s]\n", filename );

	if ( module == NULL )
	{
	    PyObject* name = PyString_FromString( "Image" );
	    module = PyImport_Import( name );
	    Py_DECREF( name );
	    if ( module == NULL )
	    {
		PyErr_SetString( PyExc_ImportError, "failed to find PIL module" );
		return NULL;
	    }
	}

	data = PyString_FromStringAndSize( NULL, window_width * window_height * 3 );
	glPixelStorei( GL_PACK_ALIGNMENT, 1 );
	glReadBuffer( GL_FRONT );
	glReadPixels( 0, 0, window_width, window_height, GL_RGB, GL_UNSIGNED_BYTE,
		      PyString_AsString( data ) );
        GL_ERROR_CHECK( "after glReadPixels" );
	
	im = PyObject_CallMethod( module, "fromstring", "s(ii)Ossii", "RGB", window_width, window_height,
				  data, "raw", "RGB", 0, -1 );

	ret = PyObject_CallMethod( im, "save", "s", filename );

	Py_XDECREF( ret );
	Py_XDECREF( im );
	Py_XDECREF( data );
    }

    GL_ERROR_CHECK( "an end to opengl_enddraw" );
    Py_INCREF( Py_None );
    return Py_None;
}
void ShaderProgramBuilder::useShaderProgram(GLuint program)
{
    LOG_INFO("Render=> Use GL program %d\n", program);
    glUseProgram( program);
    GL_ERROR_CHECK("ShaderProgramBuilder:use GL program");
}