I'm on Linux host and using a Windows guest.
I'm creating the OpenGL context with SDL, and I just draw 1000 objects in different positions, each object is just 6 vertices and 3 lines, just a 3D cross.
I'm using vertex and index buffers and GLSL shaders. It doesn't do anything special: it binds the buffers and sets the vertex attrib pointers, set the matrix and draws the elements.
It renders the scene in 2 seconds, if I hoist the buffer binding and attribute setting outside the loop it renders in 200ms, if I remove glUniformMatrix4fv that sets the matrix due to the updated positions it'll render about 10ms, though I only see 1 object and thousand other is just overdrawn on it.
On Linux and Windows host the same thing renders on stable 60FPS.
OpenGL games like OpenArena run on 60FPS in VirtualBox...
Is buffer binding and uniform setting a slow operation in OpenGL in general?
Does anyone has experience testing 3D programs on VirtualBox?
Update: added some code, error checking removed for clarity:
void drawStuff()
{
GLfloat projectView[16];
int ms;
RenderingContext rc; /*< Nothing special contains the currently bound render object.*/
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
createViewMatrix(
viewMatrix,
&viewedObject->attitude.k,
&viewedObject->attitude.j,
&viewedObject->pos
);
multiplyMatrix(projectView, viewMatrix, projMatrix); /*< Combine projection and view matrices. */
/* Draw 10×10×10 grid of 3D crosses. One cross is 6 vertices and 3 lines. */
bindRenderObject(&rc, &cross); /*< This binds buffers and sets up vertex attrib arrays. It's very slow if I put it into the loop*/
{
int i, j, k;
for (i = -5; i < 5; i++)
{
for (j = -5; j < 5; j++)
{
for (k = -5; k < 5; k++)
{
createTranslationMatrix(modelMatrix, i * 10, j * 10, k * 10);
multiplyMatrix(combinedMatrix, modelMatrix, projectView);
glUniformMatrix4fv(renderingMatrixId, 1, GL_FALSE, combinedMatrix); /*< This is slow for some reason.*/
drawRenderObject(&rc); /*< This is just a call to glDrawElements. No performance bottleneck here at all. */
}
}
}
}
/* Draw some UI. */
glDisable(GL_DEPTH_TEST);
/* ... */
glEnable(GL_DEPTH_TEST);
SDL_GL_SwapBuffers();
}
Related
I want to understand how to create loads of similar 2-D objects and then animate each one separately, using OpenGL.
I have a feeling that it will be done using this and glfwGetTime().
Can anyone here help point me in the right direction?
Ok, so here is what is the general thing that have tried so far:
We have this vector that handles translations created the following code, which I have modified slightly to make a shift in location based on time.
glm::vec2 translations[100];
int index = 0;
float offset = 0.1f;
float time = glfwGetTime(); // newcode
for (int y = -10; y < 10; y += 2)
{
for (int x = -10; x < 10; x += 2)
{
glm::vec2 translation;
translation.x = (float)x / 10.0f + offset + time; // new adjustment
translation.y = (float)y / 10.0f + offset + time*time; // new adjustmet
translations[index++] = translation;
}
}
Later, in the render loop,
while (!glfwWindowShouldClose(window))
{
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.use();
glBindVertexArray(quadVAO);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 100); // 100 triangles of 6 vertices each
glBindVertexArray(0);
time = glfwGetTime(); // new adjustment
glfwSwapBuffers(window);
glfwPollEvents();
}
is what I have tried. I suppose I am misunderstanding the way the graphics pipeline works. As I mentioned earlier, my guess is that I need to use some glm matrices to make this work as I imagined it, but am not sure ...
The general direction would be, during initialization:
Allocate a buffer to hold the positions of your instances (glNamedBufferStorage).
Set up an instanced vertex attribute for your VAO that sources the data from that buffer (glVertexArrayBindingDivisor and others).
Update your vertex shader to apply the position of your instance (coming from the instanced attribute) to the total transformation calculated within the shader.
Then, once per frame (or when the position changes):
Calculate the positions of of all your instances (the code you posted).
Submit those to the previously allocated buffer with glNamedBufferSubData.
So far you showed the code calculating the position. From here try to implement the rest, and ask a specific question if you have difficulties with any particular part of it.
I posted an example of using instancing with multidraw that you can use for reference. Note that in your case you don't need the multidraw, however, just the instancing part.
I want to understand how to create loads of similar 2-D objects and then animate each one separately, using OpenGL.
I have a feeling that it will be done using this and glfwGetTime().
Can anyone here help point me in the right direction?
Ok, so here is what is the general thing that have tried so far:
We have this vector that handles translations created the following code, which I have modified slightly to make a shift in location based on time.
glm::vec2 translations[100];
int index = 0;
float offset = 0.1f;
float time = glfwGetTime(); // newcode
for (int y = -10; y < 10; y += 2)
{
for (int x = -10; x < 10; x += 2)
{
glm::vec2 translation;
translation.x = (float)x / 10.0f + offset + time; // new adjustment
translation.y = (float)y / 10.0f + offset + time*time; // new adjustmet
translations[index++] = translation;
}
}
Later, in the render loop,
while (!glfwWindowShouldClose(window))
{
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.use();
glBindVertexArray(quadVAO);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 100); // 100 triangles of 6 vertices each
glBindVertexArray(0);
time = glfwGetTime(); // new adjustment
glfwSwapBuffers(window);
glfwPollEvents();
}
is what I have tried. I suppose I am misunderstanding the way the graphics pipeline works. As I mentioned earlier, my guess is that I need to use some glm matrices to make this work as I imagined it, but am not sure ...
The general direction would be, during initialization:
Allocate a buffer to hold the positions of your instances (glNamedBufferStorage).
Set up an instanced vertex attribute for your VAO that sources the data from that buffer (glVertexArrayBindingDivisor and others).
Update your vertex shader to apply the position of your instance (coming from the instanced attribute) to the total transformation calculated within the shader.
Then, once per frame (or when the position changes):
Calculate the positions of of all your instances (the code you posted).
Submit those to the previously allocated buffer with glNamedBufferSubData.
So far you showed the code calculating the position. From here try to implement the rest, and ask a specific question if you have difficulties with any particular part of it.
I posted an example of using instancing with multidraw that you can use for reference. Note that in your case you don't need the multidraw, however, just the instancing part.
I am wondering how to render surfaces using depth test correctly. In my case it is not working although it has been enabled. I tried many combinations but can not figure out what is being done wrong, it might been some ordering of OpenGL commands, or it might be something I am missing completely.
I have this code that uses opengl to render a 2d game I am working on. I want to enable z buffering and depth test to simplify things in the code. I read a number of tutorials online and made changes as instructed but can not figure out why it is not working.
the code of the main function is shown below, I am changing the values of z for the two squares to be -10 and -25 and swapping them later on, but I always get the first square rendered over the second one no matter what values I use:
void MainGame::RenderTestUI()
{
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LESS);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLSLProgram *ActiveShader = nullptr;
ActiveShader = &ColorShader;
ActiveShader->Use();
GLint Location1 = ActiveShader->GetUniformLocation("cam");
glm::mat4 tmp = Camera.GetCameraMatrix();
glUniformMatrix4fv(Location1, 1, GL_FALSE, &tmp[0][0]);
glActiveTexture(GL_TEXTURE0);
GLint Location2 = ActiveShader->GetUniformLocation("basic");
glUniform1f(Location2, 0);
glBindTexture(GL_TEXTURE_2D, GameTextures.ID);
CurrentBoundTexture = GameTextures.ID;
RenderingBatch.StartAddingVerticies();
this->GameMap.TileList[1].FillSixVerticies(RenderingBatch.VertexListPtr, 0, 0);
RenderingBatch.VertexCount += 6;
for (int i = 0; i < 6; i++)
RenderingBatch.VertexListPtr[i].z = -10; // first face
this->GameMap.TileList[2].FillSixVerticies(&RenderingBatch.VertexListPtr[RenderingBatch.VertexCount], 8, 8);
RenderingBatch.VertexCount += 6;
for (int i = 0; i < 6; i++)
RenderingBatch.VertexListPtr[i+6].z = -25; // second face
RenderingBatch.EndAddingVerticies();
RenderingBatch.CreateVBO();
RenderingBatch.Render();
ActiveShader->Unuse();
// swap buffers
SDL_GL_SwapWindow(GameWindow);
}
The end result is always the same regardless of the value of z i am assigning to the two faces, the result could be seen here:
any advice is highly appreciated.
When setting up the SDL surface to draw on, did you ask for a depth buffer prior to calling SDL_CreateWindow?
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
I work with an Augmented Reality framework on Android, and it gives me the camera position as a 6 degrees of freedom vector that includes the estimated camera optical and camera orientation.
Since I'm a complete newbie in OpenGL, I don't quite understand what that means and my question is - how to use this 4x4 matrix to position my camera in OpenGL.
Below is a sample from Android SDK which renders a simple textured triangle (I didn't know which details are important so I included the whole two classes - the renderer and the triangle object).
My guess is that it positions the camera with gluLookAt in onDrawFrame(). I want to adjust this,
I receive these matrices from the framework (these are just samples) -
When the camera should look directly at the triangle, I need to use a matrix of this type to somehow position my camera:
0.9930384 0.045179322 0.10878302 0.0
-0.018241059 0.9713616 -0.23690554 0.0
-0.11637083 0.23327199 0.9654233 0.0
21.803288 -14.920643 -150.6514 1.0
When I move the camera a bit far away:
0.9763242 0.041258257 0.21234424 0.0
0.014808476 0.96659267 -0.2558918 0.0
-0.21580763 0.25297752 0.94309634 0.0
17.665 -18.520836 -243.28784 1.0
When I tilt my camera a bit to the right:
0.8340566 0.0874321 0.5447095 0.0
0.054606464 0.96943074 -0.23921578 0.0
-0.5489726 0.22926341 0.8037848 0.0
-8.809776 -7.5869675 -244.01971 1.0
Any thoughts? My guess is that the only thing that matters is actually the last row, everything else is close to zero.
I'd be happy to get any advice on how to adjust this code to use those matrices, including any settings such as setting perspective matrices or whatsoever (again, a newbie).
public class TriangleRenderer implements GLSurfaceView.Renderer{
public TriangleRenderer(Context context) {
mContext = context;
mTriangle = new Triangle();
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
/*
* By default, OpenGL enables features that improve quality
* but reduce performance. One might want to tweak that
* especially on software renderer.
*/
gl.glDisable(GL10.GL_DITHER);
/*
* Some one-time OpenGL initialization can be made here
* probably based on features of this particular context
*/
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
GL10.GL_FASTEST);
gl.glClearColor(0,0,0,0);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glEnable(GL10.GL_TEXTURE_2D);
/*
* Create our texture. This has to be done each time the
* surface is created.
*/
int[] textures = new int[1];
gl.glGenTextures(1, textures, 0);
mTextureID = textures[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_MAG_FILTER,
GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
GL10.GL_REPLACE);
InputStream is = mContext.getResources()
.openRawResource(R.raw.robot);
Bitmap bitmap;
try {
bitmap = BitmapFactory.decodeStream(is);
} finally {
try {
is.close();
} catch(IOException e) {
// Ignore.
}
}
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
public void onDrawFrame(GL10 gl) {
/*
* By default, OpenGL enables features that improve quality
* but reduce performance. One might want to tweak that
* especially on software renderer.
*/
gl.glDisable(GL10.GL_DITHER);
gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
GL10.GL_MODULATE);
/*
* Usually, the first thing one might want to do is to clear
* the screen. The most efficient way of doing this is to use
* glClear().
*/
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
/*
* Now we're ready to draw some 3D objects
*/
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glActiveTexture(GL10.GL_TEXTURE0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
GL10.GL_REPEAT);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
GL10.GL_REPEAT);
long time = SystemClock.uptimeMillis() % 4000L;
float angle = 0.090f * ((int) time);
gl.glRotatef(angle, 0, 0, 1.0f);
mTriangle.draw(gl);
}
public void onSurfaceChanged(GL10 gl, int w, int h) {
gl.glViewport(0, 0, w, h);
/*
* Set our projection matrix. This doesn't have to be done
* each time we draw, but usually a new projection needs to
* be set when the viewport is resized.
*/
float ratio = (float) w / h;
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7);
}
private Context mContext;
private Triangle mTriangle;
private int mTextureID;} class Triangle {
public Triangle() {
// Buffers to be passed to gl*Pointer() functions
// must be direct, i.e., they must be placed on the
// native heap where the garbage collector cannot
// move them.
//
// Buffers with multi-byte datatypes (e.g., short, int, float)
// must have their byte order set to native order
ByteBuffer vbb = ByteBuffer.allocateDirect(VERTS * 3 * 4);
vbb.order(ByteOrder.nativeOrder());
mFVertexBuffer = vbb.asFloatBuffer();
ByteBuffer tbb = ByteBuffer.allocateDirect(VERTS * 2 * 4);
tbb.order(ByteOrder.nativeOrder());
mTexBuffer = tbb.asFloatBuffer();
ByteBuffer ibb = ByteBuffer.allocateDirect(VERTS * 2);
ibb.order(ByteOrder.nativeOrder());
mIndexBuffer = ibb.asShortBuffer();
// A unit-sided equalateral triangle centered on the origin.
float[] coords = {
// X, Y, Z
-0.5f, -0.25f, 0,
0.5f, -0.25f, 0,
0.0f, 0.559016994f, 0
};
for (int i = 0; i < VERTS; i++) {
for(int j = 0; j < 3; j++) {
mFVertexBuffer.put(coords[i*3+j] * 2.0f);
}
}
for (int i = 0; i < VERTS; i++) {
for(int j = 0; j < 2; j++) {
mTexBuffer.put(coords[i*3+j] * 2.0f + 0.5f);
}
}
for(int i = 0; i < VERTS; i++) {
mIndexBuffer.put((short) i);
}
mFVertexBuffer.position(0);
mTexBuffer.position(0);
mIndexBuffer.position(0);
}
public void draw(GL10 gl) {
gl.glFrontFace(GL10.GL_CCW);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mFVertexBuffer);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexBuffer);
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, VERTS,
GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
}
private final static int VERTS = 3;
private FloatBuffer mFVertexBuffer;
private FloatBuffer mTexBuffer;
private ShortBuffer mIndexBuffer;
The "trick" is to understand, that OpenGL does not have a camera. What is does is transforming the whole world by a movement that's the exact opposite of what a camera would have to be moved from position (0,0,0).
Such transformations (=movements) are described in form of so called homogenous transformation matrices. Fixed Function OpenGL uses a combination of two matrices:
Modelview M, which describes placement of the world and view (and objects within the world to some degree).
Projection P, which could be seen as kind of "lens" of the virtual camera (remember, there is no camera in OpenGL).
Any vertex position v is transformed by c = P * M * v (c is the transformed vertex coordinate in clip space, that is screen space not in pixels but with the screen edges at -1, 1 – the viewport then maps from clip space to screen pixel space).
What Android gives you is such a transformation matrix. I'm not sure, but looking at the values it might be, that you're given P * M. As long as there is no lighting involved you can load that directly into the modelview matrix using glLoadMatrix, and projection being set to identity. You pass matrices to OpenGL as a array of 16 floats; the indexing order of OpenGL sometimes confuses people, but the way you dumped the android matrices I think you already got them right (you printed them "wrong", transposed that is, which is the same pitfall people fall into with OpenGL glLoadMatrix, but two times transposing is identity, it's probably right. If it doesn't work at first, flip column and rows, i.e. "mirror" the matrix on its diagonal running from up-left do bottom-right).
I'm really not sure what to do anymore. I'v made my application use VBO's and my cpu usage still goes into the 70's and 80's. My render proceedure works like this:
Set the camera transformation
if the shape has not been tesselated, tesselate it.
create it's VBO
if it has a VBO, use it.
You will notice I have display lists too, I might use these if VBO is not supported. I went and found an OpenGL demo that renders a 32000 poly mesh at 60fps on my PC and uses 4% cpu. I'm rendering about 10,000 polys # 60fps using vbos and its using 70-80%.
Here is my render proc:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
POINT hh = controls.MainGlFrame.GetMousePos();
POINTFLOAT S;
S.x = static_cast<float>(hh.x);
S.y = static_cast<float>(hh.y);
POINTFLOAT t;
t.x = 256;
t.y = 256;
POINT dimensions;
dimensions.x = 512;
dimensions.y = 512;
glDeleteTextures(1,&texName);
texName = functions.CreateGradient(col,t,S,512,512,true);
itt = true;
}
HDC hdc;
PAINTSTRUCT ps;
glEnable(GL_MULTISAMPLE_ARB);
glEnable(GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
hdc = BeginPaint(controls.MainGlContext.mhWnd,&ps);
//start OGL code
glClearColor( 1.0f, 1.0f, 1.0f, 0.0f );
if(!current.isdrawing)
glClear( GL_COLOR_BUFFER_BIT );
glPushMatrix();
glTranslatef(controls.MainGlFrame.GetCameraX(),
controls.MainGlFrame.GetCameraY(),0);
//glTranslatef(current.ScalePoint.x,current.ScalePoint.y,0);
glScalef(current.ScaleFactor,current.ScaleFactor,current.ScaleFactor);
//glTranslatef(-current.ScalePoint.x,-current.ScalePoint.y,0);
if(!current.isdrawing)
{
for(unsigned int currentlayer = 0; currentlayer < layer.size(); ++currentlayer)
{
PolygonTesselator.Init();
for(unsigned int i = 0; i < layer[currentlayer].Shapes.size(); i++)
{
if(layer[currentlayer].Shapes[i].DisplayListInt == -999)
{
gluTessNormal(PolygonTesselator.tobj, 0, 0, 1);
PolygonTesselator.Set_Winding_Rule(layer[currentlayer].Shapes[i].WindingRule);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texName);
layer[currentlayer].Shapes[i].DisplayListInt = glGenLists(1);
glNewList(layer[currentlayer].Shapes[i].DisplayListInt,GL_COMPILE);
PolygonTesselator.SetDimensions(layer[currentlayer].Shapes[i].Dimensions,layer[currentlayer].Shapes[i].minima);
PolygonTesselator.Begin_Polygon();
for(unsigned int c = 0; c < layer[currentlayer].Shapes[i].Contour.size(); ++c)
{
if(layer[currentlayer].Shapes[i].Color.a != 0)
{
PolygonTesselator.Begin_Contour();
for(unsigned int j = 0; j < layer[currentlayer].Shapes[i].Contour[c].DrawingPoints.size(); ++j)
{
gluTessVertex(PolygonTesselator.tobj,&layer[currentlayer].Shapes[i].Contour[c].DrawingPoints[j][0],
&layer[currentlayer].Shapes[i].Contour[c].DrawingPoints[j][0]);
}
PolygonTesselator.End_Contour();
}
}
PolygonTesselator.End_Polygon();
glEndList();
PolygonTesselator.TransferVerticies(layer[currentlayer].Shapes[i].OutPoints);
glGenBuffersARB(1,&layer[currentlayer].Shapes[i].VBOInt);
glBindBufferARB(GL_ARRAY_BUFFER_ARB,layer[currentlayer].Shapes[i].VBOInt);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,sizeof(GLfloat) * layer[currentlayer].Shapes[i].OutPoints.size(),
&layer[currentlayer].Shapes[i].OutPoints[0], GL_STATIC_DRAW_ARB);
InvalidateRect(controls.MainGlFrame.framehWnd,NULL,false);
}
else //run vbo
{
//glEnable(GL_TEXTURE_2D);
//glDisable(GL_TEXTURE_2D);
//glBindTexture(GL_TEXTURE_2D, texName);
glColor4f(layer[currentlayer].Shapes[i].Color.r,
layer[currentlayer].Shapes[i].Color.g,
layer[currentlayer].Shapes[i].Color.b,
layer[currentlayer].Shapes[i].Color.a);
//glColor4f(1,1,1,1);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, layer[currentlayer].Shapes[i].VBOInt);
//glCallList(layer[currentlayer].Shapes[i].DisplayListInt);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, layer[currentlayer].Shapes[i].OutPoints.size() / 2);
glDisableClientState(GL_VERTEX_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
glDisable(GL_TEXTURE_2D);
//Draw outlines
if(layer[currentlayer].Shapes[i].Outline.OutlinePoints.size() > 4)
{
glColor4f(layer[currentlayer].Shapes[i].Outline.OutlineColor.r
,layer[currentlayer].Shapes[i].Outline.OutlineColor.g
,layer[currentlayer].Shapes[i].Outline.OutlineColor.b
,layer[currentlayer].Shapes[i].Outline.OutlineColor.a);
}
}
PolygonTesselator.End();
}
}
glPopMatrix();
//end OGL code
glFlush();
SwapBuffers(hdc);
glDisable(GL_MULTISAMPLE_ARB);
EndPaint(controls.MainGlContext.mhWnd,&ps);
}
Why could I be getting such high cpu usage?
Under what conditions is that first bit of code run? There's a couple of suspicious-looking lines in there:
glDeleteTextures(1,&texName);
texName = functions.CreateGradient(col,t,S,512,512,true);
If you're deleting and recreating a texture every time you paint, that could get expensive. I couldn't say how expensive the OpenGL parts would be -- I'd expect uploading texture data to be reasonably efficient, even if deleting and creating texture names might be less so -- but perhaps CreateGradient is inherently slow. Or maybe you're accidentally hitting some kind of slow path for your graphics card. Or the function is creating all the mipmap levels. And so on.
Aside from that, some random ideas:
What is the present interval? If the buffer swap is set to sync with the monitor, you may incur a delay because of that. (You can use the WGL_EXT_swap_control extension to tweak this value.)
If all of this is being run in response to a WM_PAINT, check that you aren't getting unexpected extra WM_PAINTs for some reason.
Check that the polygon tesselator Init and End functions aren't doing anything, since they're being called every time, even if there's no tesselating to be done.
Based on the code snippet you have provided, you have (at one point) loops nested four layers deep. You may be seeing high CPU load due to running each of these loops an extremely large number of times. Can you give us any idea how many iterations these loops are having to run through?
Try grabbing a timestamp inside each loop iteration and compare it against the previous to see how long it is taking to run one iteration of each particular loop. This should help you determine what part of the function is taking up the bulk of your CPU time.