New features, my suggestions and findings thus far.
New features, my suggestions and findings thus far.
Hello again all. A couple of days ago I started a forum post in the Help section that started out as a help question, but turned into a things to do list. So I wanted to start a post in a more appropriate spot. Like I stated in my previous posting, this will take some time, BUT, this is what I have come up with thus far.
1. Implementing CVAs in OpenGL render path. Used to speed up rendering of multitextured meshs under OpenGL.
To do this I would first have to *adjust* the
void CVideoOpenGL::loadExtensions(). I currently load my extensions a little differently than irrlicht. In my programs I load them like this.
//Extensions
PFNGLLOCKARRAYSEXTPROC glLockArraysEXT = NULL;
PFNGLUNLOCKARRAYSEXTPROC glUnlockArraysEXT = NULL;
PFNGLACTIVETEXTUREPROC glActiveTextureARB = NULL;
PFNGLCLIENTACTIVETEXTUREPROC glClientActiveTextureARB = NULL;
PFNGLMULTITEXCOORD1FPROC glMultiTexCoord1fARB = NULL;
PFNGLMULTITEXCOORD2FPROC glMultiTexCoord2fARB = NULL;
PFNGLMULTITEXCOORD3FPROC glMultiTexCoord3fARB = NULL;
PFNGLMULTITEXCOORD4FPROC glMultiTexCoord4fARB = NULL;
void CheckExtensions(void)
{
glGetString(GL_EXTENSIONS);
#ifdef _WIN32
if(strstr((const char *)glGetString(GL_EXTENSIONS), "ARB_multitexture") != NULL)
{
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &MaxTextures);
glActiveTextureARB = (PFNGLACTIVETEXTUREPROC) wglGetProcAddress("glActiveTextureARB");
glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREPROC) wglGetProcAddress("glClientActiveTextureARB");
glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FPROC) wglGetProcAddress("glMultiTexCoord1fARB");
glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FPROC) wglGetProcAddress("glMultiTexCoord2fARB");
glMultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FPROC) wglGetProcAddress("glMultiTexCoord3fARB");
glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FPROC) wglGetProcAddress("glMultiTexCoord4fARB");
MultiTextureSupport = true;
}
else
{
MultiTextureSupport = false;
}
if(strstr((const char *)glGetString(GL_EXTENSIONS), "EXT_compiled_vertex_array") != NULL)
{
glLockArraysEXT = (PFNGLLOCKARRAYSEXTPROC) wglGetProcAddress("glLockArraysEXT");
glUnlockArraysEXT = (PFNGLUNLOCKARRAYSEXTPROC) wglGetProcAddress("glUnlockArraysEXT");
CompiledVertexArraySupport = true;
}
else
{
CompiledVertexArraySupport = false;
}
#endif
#ifdef __linux
if(strstr((const char *)glGetString(GL_EXTENSIONS), "ARB_multitexture") != NULL)
{
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &MaxTextures);
glActiveTextureARB = (PFNGLACTIVETEXTUREPROC) glXGetProcAddressARB("glActiveTextureARB");
glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREPROC) glXGetProcAddressARB("glClientActiveTextureARB");
glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FPROC) glXGetProcAddressARB("glMultiTexCoord1fARB");
glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FPROC) glXGetProcAddressARB("glMultiTexCoord2fARB");
glMultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FPROC) glXGetProcAddressARB("glMultiTexCoord3fARB");
glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FPROC) glXGetProcAddressARB("glMultiTexCoord4fARB");
MultiTextureSupport = true;
}
else
{
MultiTextureSupport = false;
}
if(strstr((const char *)glGetString(GL_EXTENSIONS), "EXT_compiled_vertex_array") != NULL)
{
glLockArraysEXT = (PFNGLLOCKARRAYSEXTPROC) glXGetProcAddressEXT("glLockArraysEXT");
glUnlockArraysEXT = (PFNGLUNLOCKARRAYSEXTPROC) glXGetProcAddressEXT("glUnlockArraysEXT");
CompiledVertexArraySupport = true;
}
else
{
CompiledVertexArraySupport = false;
}
#endif
#ifdef __APPLE__
if(strstr((const char *)glGetString(GL_EXTENSIONS), "ARB_multitexture") != NULL)
{
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &MaxTextures);
glActiveTextureARB = (PFNGLACTIVETEXTUREPROC) aglGetProcAddress("glActiveTextureARB");
glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREPROC) aglGetProcAddress("glClientActiveTextureARB");
glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FPROC) aglGetProcAddress("glMultiTexCoord1fARB");
glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FPROC) aglGetProcAddress("glMultiTexCoord2fARB");
glMultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FPROC) aglGetProcAddress("glMultiTexCoord3fARB");
glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FPROC) aglGetProcAddress("glMultiTexCoord4fARB");
MultiTextureSupport = true;
}
else
{
MultiTextureSupport = false;
}
if(strstr((const char *)glGetString(GL_EXTENSIONS), "EXT_compiled_vertex_array") != NULL)
{
glLockArraysEXT = (PFNGLLOCKARRAYSEXTPROC) aglGetProcAddress("glLockArraysEXT");
glUnlockArraysEXT = (PFNGLUNLOCKARRAYSEXTPROC) aglGetProcAddress("glUnlockArraysEXT");
CompiledVertexArraySupport = true;
}
else
{
CompiledVertexArraySupport = false;
}
#endif
}
So do to the differences, in code I will have to adjust the current irrlicht routine to pull out CompiledVertexArraySupport as well. Then its just a matter of checking a bool value each time a multitextured mesh is rendered, and locking/unlocking the arrays.
2. I would also like to implement triangle stripping. To do this in my programs I use the library http://users.pandora.be/tfautre/softdev ... r_main.htm
This is a little more tricky than CVAs. Because it means adding a *new* piece to the meshs. The current meshs contain an index (for indexed triangle arrays), I will also have to add a stripper object. Currently this is how tri stripper is implemented in my code.
The first step is to link a Tri Stripper object, we can reuse the same object over and over, because we only use the primatives_vector (mentioned below) created for each mesh. So the original object can be added/deleted over and over again for each new mesh.
using triangle_stripper::tri_stripper; //Namespace
tri_stripper MyStripper; //Object
After that you can optionally set the settings of MyStripper as you want (the cache size and the minimum strip size):
MyStripper.SetCacheSize(10); //Optimize for hardware cache
MyStripper.SetMinStripSize(2); //2 triangles minimum per strip
Then you just have to create primatives_vector where the results will be put, and launch the strippification, we simply use the current indecies of the mesh and pass it to try stripper after the mesh has been loaded into memory. Then try stripper takes those indecies and creates a stripper object containing a list of indecies strippified. NOTE: Tri stipper does NOT moddify the original indecies, so rendering w/out strippifing will still be possible.
tri_stripper::primitives_vector MyResult; //This will be the NEW mesh indecies object that I need to create for this to work.
MyStripper.Strip(& MyResult); //Save the results in the object.
The type primitives_vector is defined as follow in "tri_stripper.":
"primitives_vector" is a "std::vector<primitives>"
"primitives" is a struct containing a "primitive_type" and "indices" ("indices" is a "std::vector<unsigned int>")
"primitive_type" is an enum of either "PT_Triangles" or "PT_Triangle_Strip"
With all that said (I like to show what Im doing, or else I get lost, lol). Triangle stripping will be able to be implemented in all render paths, since the indecies are never actualy modiffied. This should allow for quite a speedup expecialy w/ large meshs. Only draw back will be slightly longer mesh load times.
3. I would realy like to implement a *basic* version of shaders, to do cel shading. The BEST method would be to load 1D textures, but I am not aware of a DirectX method for doing so. (Sorry if im way wrong, I am an opengl guy, pretty much exclusivly). If anyone knows of one, please inform me, that would make life much easier. But I am going to have to create a new material anyhow, since no matter how the cel-shading is done, it will require rerendering the mesh twice.
IMPLEMENTATION: This is a look at the current OpenGL rendering path in irrlicht, and a semi seudo code new rendering path im working on. The new path implements CVAs and tri stripping.
OLD:
//! draws an indexed triangle list
void CVideoOpenGL::drawIndexedTriangleList(const S3DVertex2TCoords* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount)
{
CVideoNull::drawIndexedTriangleList(vertices, vertexCount, indexList, triangleCount);
setRenderStates3DMode();
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY );
glEnableClientState(GL_NORMAL_ARRAY );
// convert colors to gl color format.
const S3DVertex2TCoords* p = vertices;
ColorBuffer.set_used(vertexCount);
for (s32 i=0; i<vertexCount; ++i)
{
ColorBuffer = p->Color.toOpenGLColor();
++p;
}
// draw everything
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(video::SColor), &ColorBuffer[0]);
glNormalPointer(GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].Normal);
glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].Pos);
// texture coordiantes
if (MultiTextureExtension)
{
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].TCoords);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].TCoords2);
}
else
glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].TCoords);
glDrawElements(GL_TRIANGLES, triangleCount * 3, GL_UNSIGNED_SHORT, indexList);
glFlush();
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
if (MultiTextureExtension)
{
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
}
else
glDisableClientState(GL_TEXTURE_COORD_ARRAY );
glDisableClientState(GL_NORMAL_ARRAY );
}
NEW:
void CVideoOpenGL::drawStrippedTriangleList(const S3DVertex2TCoords* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount, tri_stripper::primitives_vector* strips)
{
CVideoNull::drawIndexedTriangleList(vertices, vertexCount, indexList, triangleCount);
setRenderStates3DMode();
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY );
glEnableClientState(GL_NORMAL_ARRAY );
// convert colors to gl color format.
const S3DVertex2TCoords* p = vertices;
ColorBuffer.set_used(vertexCount);
for (s32 i=0; i<vertexCount; ++i)
{
ColorBuffer = p->Color.toOpenGLColor();
++p;
}
// draw everything
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(video::SColor), &ColorBuffer[0]);
glNormalPointer(GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].Normal);
glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].Pos);
// texture coordiantes
if (MultiTextureExtension)
{
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].TCoords);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].TCoords2);
}
else
{
glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].TCoords);
}
for(int b=0; b<strips.size(); b++)
{
switch(strips.primitives.primitive_type)
{
case PT_Triangles:
if(CompiledVertexArraySupport)
{
glLockArraysEXT(0, &strips.primitives.indices.size());
glDrawElements(GL_TRIANGLES, &strips.primitives.indices.size(), GL_UNSIGNED_INT, &strips.primitives.indices);
glUnlockArraysEXT();
}
else
{
glDrawElements(GL_TRIANGLES, &strips.primitives.indices.size(), GL_UNSIGNED_INT, &strips.primitives.indices);
}
break;
case PT_Triangle_Strip:
if(CompiledVertexArraySupport)
{
glLockArraysEXT(0, &strips.primitives.indices.size());
glDrawElements(GL_TRIANGLE_STRIP, &strips.primitives.indices.size(), GL_UNSIGNED_INT, &strips.primitives.indices);
glUnlockArraysEXT();
}
else
{
glDrawElements(GL_TRIANGLE_STRIP, &strips.primitives.indices.size(), GL_UNSIGNED_INT, &strips[b].primitives.indices);
}
break;
}
}
glFlush();
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
if (MultiTextureExtension)
{
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
}
else
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY );
}
glDisableClientState(GL_NORMAL_ARRAY );
}
NOTE: The above was kind of slapped togeather, dont take for absolute face value. Also, I am not sure when I will get to any of this. But if anyone wants to jump the gun and take off on any area of what I am working on, please go ahead, Lets make irrlicht the best engine it can be shall we? I personaly think irrlicht is one of the coolest things I have seen in a while, and maybe some of our design changes might be absorbed into irrlicht, how cool would that be?
PS: On a side note, I am REALY sorry for spelling mistakes etc. One of the reasons I became a programmer is that I get to make words up for a living. lol. I am REALY bad with spelling them REAL words. Thankx, and sorry.
1. Implementing CVAs in OpenGL render path. Used to speed up rendering of multitextured meshs under OpenGL.
To do this I would first have to *adjust* the
void CVideoOpenGL::loadExtensions(). I currently load my extensions a little differently than irrlicht. In my programs I load them like this.
//Extensions
PFNGLLOCKARRAYSEXTPROC glLockArraysEXT = NULL;
PFNGLUNLOCKARRAYSEXTPROC glUnlockArraysEXT = NULL;
PFNGLACTIVETEXTUREPROC glActiveTextureARB = NULL;
PFNGLCLIENTACTIVETEXTUREPROC glClientActiveTextureARB = NULL;
PFNGLMULTITEXCOORD1FPROC glMultiTexCoord1fARB = NULL;
PFNGLMULTITEXCOORD2FPROC glMultiTexCoord2fARB = NULL;
PFNGLMULTITEXCOORD3FPROC glMultiTexCoord3fARB = NULL;
PFNGLMULTITEXCOORD4FPROC glMultiTexCoord4fARB = NULL;
void CheckExtensions(void)
{
glGetString(GL_EXTENSIONS);
#ifdef _WIN32
if(strstr((const char *)glGetString(GL_EXTENSIONS), "ARB_multitexture") != NULL)
{
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &MaxTextures);
glActiveTextureARB = (PFNGLACTIVETEXTUREPROC) wglGetProcAddress("glActiveTextureARB");
glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREPROC) wglGetProcAddress("glClientActiveTextureARB");
glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FPROC) wglGetProcAddress("glMultiTexCoord1fARB");
glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FPROC) wglGetProcAddress("glMultiTexCoord2fARB");
glMultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FPROC) wglGetProcAddress("glMultiTexCoord3fARB");
glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FPROC) wglGetProcAddress("glMultiTexCoord4fARB");
MultiTextureSupport = true;
}
else
{
MultiTextureSupport = false;
}
if(strstr((const char *)glGetString(GL_EXTENSIONS), "EXT_compiled_vertex_array") != NULL)
{
glLockArraysEXT = (PFNGLLOCKARRAYSEXTPROC) wglGetProcAddress("glLockArraysEXT");
glUnlockArraysEXT = (PFNGLUNLOCKARRAYSEXTPROC) wglGetProcAddress("glUnlockArraysEXT");
CompiledVertexArraySupport = true;
}
else
{
CompiledVertexArraySupport = false;
}
#endif
#ifdef __linux
if(strstr((const char *)glGetString(GL_EXTENSIONS), "ARB_multitexture") != NULL)
{
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &MaxTextures);
glActiveTextureARB = (PFNGLACTIVETEXTUREPROC) glXGetProcAddressARB("glActiveTextureARB");
glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREPROC) glXGetProcAddressARB("glClientActiveTextureARB");
glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FPROC) glXGetProcAddressARB("glMultiTexCoord1fARB");
glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FPROC) glXGetProcAddressARB("glMultiTexCoord2fARB");
glMultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FPROC) glXGetProcAddressARB("glMultiTexCoord3fARB");
glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FPROC) glXGetProcAddressARB("glMultiTexCoord4fARB");
MultiTextureSupport = true;
}
else
{
MultiTextureSupport = false;
}
if(strstr((const char *)glGetString(GL_EXTENSIONS), "EXT_compiled_vertex_array") != NULL)
{
glLockArraysEXT = (PFNGLLOCKARRAYSEXTPROC) glXGetProcAddressEXT("glLockArraysEXT");
glUnlockArraysEXT = (PFNGLUNLOCKARRAYSEXTPROC) glXGetProcAddressEXT("glUnlockArraysEXT");
CompiledVertexArraySupport = true;
}
else
{
CompiledVertexArraySupport = false;
}
#endif
#ifdef __APPLE__
if(strstr((const char *)glGetString(GL_EXTENSIONS), "ARB_multitexture") != NULL)
{
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &MaxTextures);
glActiveTextureARB = (PFNGLACTIVETEXTUREPROC) aglGetProcAddress("glActiveTextureARB");
glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREPROC) aglGetProcAddress("glClientActiveTextureARB");
glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FPROC) aglGetProcAddress("glMultiTexCoord1fARB");
glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FPROC) aglGetProcAddress("glMultiTexCoord2fARB");
glMultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FPROC) aglGetProcAddress("glMultiTexCoord3fARB");
glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FPROC) aglGetProcAddress("glMultiTexCoord4fARB");
MultiTextureSupport = true;
}
else
{
MultiTextureSupport = false;
}
if(strstr((const char *)glGetString(GL_EXTENSIONS), "EXT_compiled_vertex_array") != NULL)
{
glLockArraysEXT = (PFNGLLOCKARRAYSEXTPROC) aglGetProcAddress("glLockArraysEXT");
glUnlockArraysEXT = (PFNGLUNLOCKARRAYSEXTPROC) aglGetProcAddress("glUnlockArraysEXT");
CompiledVertexArraySupport = true;
}
else
{
CompiledVertexArraySupport = false;
}
#endif
}
So do to the differences, in code I will have to adjust the current irrlicht routine to pull out CompiledVertexArraySupport as well. Then its just a matter of checking a bool value each time a multitextured mesh is rendered, and locking/unlocking the arrays.
2. I would also like to implement triangle stripping. To do this in my programs I use the library http://users.pandora.be/tfautre/softdev ... r_main.htm
This is a little more tricky than CVAs. Because it means adding a *new* piece to the meshs. The current meshs contain an index (for indexed triangle arrays), I will also have to add a stripper object. Currently this is how tri stripper is implemented in my code.
The first step is to link a Tri Stripper object, we can reuse the same object over and over, because we only use the primatives_vector (mentioned below) created for each mesh. So the original object can be added/deleted over and over again for each new mesh.
using triangle_stripper::tri_stripper; //Namespace
tri_stripper MyStripper; //Object
After that you can optionally set the settings of MyStripper as you want (the cache size and the minimum strip size):
MyStripper.SetCacheSize(10); //Optimize for hardware cache
MyStripper.SetMinStripSize(2); //2 triangles minimum per strip
Then you just have to create primatives_vector where the results will be put, and launch the strippification, we simply use the current indecies of the mesh and pass it to try stripper after the mesh has been loaded into memory. Then try stripper takes those indecies and creates a stripper object containing a list of indecies strippified. NOTE: Tri stipper does NOT moddify the original indecies, so rendering w/out strippifing will still be possible.
tri_stripper::primitives_vector MyResult; //This will be the NEW mesh indecies object that I need to create for this to work.
MyStripper.Strip(& MyResult); //Save the results in the object.
The type primitives_vector is defined as follow in "tri_stripper.":
"primitives_vector" is a "std::vector<primitives>"
"primitives" is a struct containing a "primitive_type" and "indices" ("indices" is a "std::vector<unsigned int>")
"primitive_type" is an enum of either "PT_Triangles" or "PT_Triangle_Strip"
With all that said (I like to show what Im doing, or else I get lost, lol). Triangle stripping will be able to be implemented in all render paths, since the indecies are never actualy modiffied. This should allow for quite a speedup expecialy w/ large meshs. Only draw back will be slightly longer mesh load times.
3. I would realy like to implement a *basic* version of shaders, to do cel shading. The BEST method would be to load 1D textures, but I am not aware of a DirectX method for doing so. (Sorry if im way wrong, I am an opengl guy, pretty much exclusivly). If anyone knows of one, please inform me, that would make life much easier. But I am going to have to create a new material anyhow, since no matter how the cel-shading is done, it will require rerendering the mesh twice.
IMPLEMENTATION: This is a look at the current OpenGL rendering path in irrlicht, and a semi seudo code new rendering path im working on. The new path implements CVAs and tri stripping.
OLD:
//! draws an indexed triangle list
void CVideoOpenGL::drawIndexedTriangleList(const S3DVertex2TCoords* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount)
{
CVideoNull::drawIndexedTriangleList(vertices, vertexCount, indexList, triangleCount);
setRenderStates3DMode();
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY );
glEnableClientState(GL_NORMAL_ARRAY );
// convert colors to gl color format.
const S3DVertex2TCoords* p = vertices;
ColorBuffer.set_used(vertexCount);
for (s32 i=0; i<vertexCount; ++i)
{
ColorBuffer = p->Color.toOpenGLColor();
++p;
}
// draw everything
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(video::SColor), &ColorBuffer[0]);
glNormalPointer(GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].Normal);
glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].Pos);
// texture coordiantes
if (MultiTextureExtension)
{
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].TCoords);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].TCoords2);
}
else
glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].TCoords);
glDrawElements(GL_TRIANGLES, triangleCount * 3, GL_UNSIGNED_SHORT, indexList);
glFlush();
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
if (MultiTextureExtension)
{
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
}
else
glDisableClientState(GL_TEXTURE_COORD_ARRAY );
glDisableClientState(GL_NORMAL_ARRAY );
}
NEW:
void CVideoOpenGL::drawStrippedTriangleList(const S3DVertex2TCoords* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount, tri_stripper::primitives_vector* strips)
{
CVideoNull::drawIndexedTriangleList(vertices, vertexCount, indexList, triangleCount);
setRenderStates3DMode();
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY );
glEnableClientState(GL_NORMAL_ARRAY );
// convert colors to gl color format.
const S3DVertex2TCoords* p = vertices;
ColorBuffer.set_used(vertexCount);
for (s32 i=0; i<vertexCount; ++i)
{
ColorBuffer = p->Color.toOpenGLColor();
++p;
}
// draw everything
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(video::SColor), &ColorBuffer[0]);
glNormalPointer(GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].Normal);
glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].Pos);
// texture coordiantes
if (MultiTextureExtension)
{
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].TCoords);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].TCoords2);
}
else
{
glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].TCoords);
}
for(int b=0; b<strips.size(); b++)
{
switch(strips.primitives.primitive_type)
{
case PT_Triangles:
if(CompiledVertexArraySupport)
{
glLockArraysEXT(0, &strips.primitives.indices.size());
glDrawElements(GL_TRIANGLES, &strips.primitives.indices.size(), GL_UNSIGNED_INT, &strips.primitives.indices);
glUnlockArraysEXT();
}
else
{
glDrawElements(GL_TRIANGLES, &strips.primitives.indices.size(), GL_UNSIGNED_INT, &strips.primitives.indices);
}
break;
case PT_Triangle_Strip:
if(CompiledVertexArraySupport)
{
glLockArraysEXT(0, &strips.primitives.indices.size());
glDrawElements(GL_TRIANGLE_STRIP, &strips.primitives.indices.size(), GL_UNSIGNED_INT, &strips.primitives.indices);
glUnlockArraysEXT();
}
else
{
glDrawElements(GL_TRIANGLE_STRIP, &strips.primitives.indices.size(), GL_UNSIGNED_INT, &strips[b].primitives.indices);
}
break;
}
}
glFlush();
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
if (MultiTextureExtension)
{
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
}
else
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY );
}
glDisableClientState(GL_NORMAL_ARRAY );
}
NOTE: The above was kind of slapped togeather, dont take for absolute face value. Also, I am not sure when I will get to any of this. But if anyone wants to jump the gun and take off on any area of what I am working on, please go ahead, Lets make irrlicht the best engine it can be shall we? I personaly think irrlicht is one of the coolest things I have seen in a while, and maybe some of our design changes might be absorbed into irrlicht, how cool would that be?
PS: On a side note, I am REALY sorry for spelling mistakes etc. One of the reasons I became a programmer is that I get to make words up for a living. lol. I am REALY bad with spelling them REAL words. Thankx, and sorry.
Sounds like you're doing some pretty cool shiz. Keep it up.
One question I have-- the TriStripper. Is this something thats going to re-create a tri-stripped list based on the current tri list every time a thing is drawn using TriStripping? If so, perhaps after it has been accepted, we can move it to replace regular tri-lists when objects are loaded with TriStripping = true. (so, there is a trilist and tristrip pointer, but only one of them is used based on bool useTriStrip) ?
One question I have-- the TriStripper. Is this something thats going to re-create a tri-stripped list based on the current tri list every time a thing is drawn using TriStripping? If so, perhaps after it has been accepted, we can move it to replace regular tri-lists when objects are loaded with TriStripping = true. (so, there is a trilist and tristrip pointer, but only one of them is used based on bool useTriStrip) ?
a screen cap is worth 0x100000 DWORDS
Ok, your question confussed me a bit, but that might be lack of sleep lol, but... TriStripper takes a list of indecies and returns a *new* list of stripped indecies (well a list of strips, made out of indicies), but dosnt modify the old ones. So you could forseably use either list to draw your polys from. So yes you could have a bool value to pass to the draw routine telling it which method to use.
But the only reason 2 reasons I can see where normal triangles would be better than strips would be for
A. Particles (no real strips can be formed, its just a BUNCH of triangles, not conected in any particular way).
B. A mesh that is going to be destructed/reconstructed often. For instance, if you have to add/remove polys from a mesh on a reqular basis, the strippifier being called to restrip the mesh over and over would introduce a performance hit.
Other than that, I see no reason to not replace the current triangle routine with strips. But yes I agree, a bool value set when loading a model might be best. This way, it would be all internal. Basicaly, when loading a model the first time, you would set a bool value, this value would inturn decide if a strip was created or not. Then using the power of STL (I LOVE STL) we can simply check the size of the strippifier object before we go to render. So if the strips.size() = 0; then we know that the object was NEVER even strippified for this mesh, and to render it with the original methods.
But the only reason 2 reasons I can see where normal triangles would be better than strips would be for
A. Particles (no real strips can be formed, its just a BUNCH of triangles, not conected in any particular way).
B. A mesh that is going to be destructed/reconstructed often. For instance, if you have to add/remove polys from a mesh on a reqular basis, the strippifier being called to restrip the mesh over and over would introduce a performance hit.
Other than that, I see no reason to not replace the current triangle routine with strips. But yes I agree, a bool value set when loading a model might be best. This way, it would be all internal. Basicaly, when loading a model the first time, you would set a bool value, this value would inturn decide if a strip was created or not. Then using the power of STL (I LOVE STL) we can simply check the size of the strippifier object before we go to render. So if the strips.size() = 0; then we know that the object was NEVER even strippified for this mesh, and to render it with the original methods.
what sort of gains?
now i know tri strips or fans are faster than indexed tris, but what sort of performance increase have you noticed with this? it sounds like a bit of a tradeoff to me, since you must build this tristrip list at load, maybe a load time vs FPS analysis would be in order lol maybe if i can figure out just what all that code there does i can find out
-Ted
-Ted
My irrlicht-based projects have gone underground for now, but if you want, check out my webcomic instead! http://brokenboomerang.net
Quite right. Expecialy since that extra ~50fps performace increase leaves alot of extra time for other parts of the code to work. So with that, you can possibly add a couple of WOW features that would have previously been to cpu consuming to add. And being that the indecies created during load time are just unsigned ints, there isnt very much more memory used either. So its kind of a win win. But when I actualy get it functioning, I will do some tests and let ya know. But I am expecting a faily substantial fps increase. But the most important part of that code, is where you set the cache for the video card. The more dead on that cache is for a particular card, the better the performance from tristrips, and that is where this method will realy shine.
Updates thus far:
Well I started playing with the engine. I have figured out what I believe is to be all the files that will have to be modified for the triangle strippifier to work.
So far:
Added: the strippifier #include <tri_stripper>, and #include <vector> to the Meshbuffer headers.
Added: a tri_stipper object to the SMeshBuffer.h, and SMeshBufferLightMap.h as well as a couple of functions to those and the IMeshBuffer.h classes for returning the number of mesh strips, etc.
Working on: Adding a bool value to the mesh creation code, to allow meshs to be strippified onload.
Working on: CMeshManipulator, checking to see if the object was strippified onload, if so we need to update the strips when certain MeshManipulators are done.
Working on: Rendering paths. Each path will test the size of the stripper object, and if it is 0 (meaning it was never built) the rendering paths will default back to indexed triangles, but if not, it will render with tri_stripper.
Working on: Reimplementing the check extensions code in OpenGL to use CVAs.
Not Even Close to Yet: New matrial type, Toon shading.
I know its not much yet, but figuring out which files need to be changed, took me a while. Hopefully I will have the triangle strips up and running by next week. When it works (a heck, IF it works lol). I will submit the edited files, with notation of what I changed.
So far:
Added: the strippifier #include <tri_stripper>, and #include <vector> to the Meshbuffer headers.
Added: a tri_stipper object to the SMeshBuffer.h, and SMeshBufferLightMap.h as well as a couple of functions to those and the IMeshBuffer.h classes for returning the number of mesh strips, etc.
Working on: Adding a bool value to the mesh creation code, to allow meshs to be strippified onload.
Working on: CMeshManipulator, checking to see if the object was strippified onload, if so we need to update the strips when certain MeshManipulators are done.
Working on: Rendering paths. Each path will test the size of the stripper object, and if it is 0 (meaning it was never built) the rendering paths will default back to indexed triangles, but if not, it will render with tri_stripper.
Working on: Reimplementing the check extensions code in OpenGL to use CVAs.
Not Even Close to Yet: New matrial type, Toon shading.
I know its not much yet, but figuring out which files need to be changed, took me a while. Hopefully I will have the triangle strips up and running by next week. When it works (a heck, IF it works lol). I will submit the edited files, with notation of what I changed.
Status report:
Ok, I have taken Keless's statement to heart, and have decided to simply rewrite the parts of the tri_stripper library, to use core::array<> instead of stl::vector<>. Turns out its a VERY easy switch, since core::array<> is virtualy identical.
But, I have had some problems adding the neccessary tid bits to irrlicht, not because of any coding problems, but just attempting to find all of the calls to the drawtriangles functions, etc. Problem arrises from the fact that I have no compiler or IDE at work (dont do software at work, but have alot of free time some days), but I do have a text editor. So I have to search manualy through all of the files and change the needed calls. But back to the grind.
But, I have had some problems adding the neccessary tid bits to irrlicht, not because of any coding problems, but just attempting to find all of the calls to the drawtriangles functions, etc. Problem arrises from the fact that I have no compiler or IDE at work (dont do software at work, but have alot of free time some days), but I do have a text editor. So I have to search manualy through all of the files and change the needed calls. But back to the grind.
welp you could try dev-c++ maybe
its free, can you install stuff on your work PC?
if so here is the link:
http://www.bloodshed.net/devcpp.html
-Ted
if so here is the link:
http://www.bloodshed.net/devcpp.html
-Ted
My irrlicht-based projects have gone underground for now, but if you want, check out my webcomic instead! http://brokenboomerang.net
Thanx
First off, Thanx niko.
Second: I have a couple more updates. Well I started to actualy look @ the stl implementation inside of the tri_stripper library, turns out, NOT so easy to change. There is alot of stl in there, not just std::vector<>, but also deques and maps etc etc. So it looks like that may have to stay using stl. Which all and all isnt bad.
But I have been a busy little bee inside of the irlicht engine itself, here is a list of the files currently modified to use tri_stripping. If anyone can think of any others (before I go home and compile tonight) that might need to be changed, let me know. (I have no idea how you would know, what files need to be changed, but any help is help right, lol).
ImeshBuffer.h //Added: "return pointers to" and "size of" stripper object
SmeshBuffer.h //Added: same as above, w/ declration of stripper object
SmeshBufferLightMap.h //Ditto
ISceneManager.h //Added: bool "stripit" to getMesh();
CSceneManager.h //ditto
CSceneManager.cpp //Not sure if the pointer notations are correct yet. But
//added a routine to strippify the mesh (if bool passed).
IVideoDriver.h //Extended drawIndexedTriangleList
CMeshSceneNode.cpp //Extended drawIndexedTriangleList
CAnimatedMeshSceneNode.cpp //Extended drawIndexedTriangleList
CVideoSoftware.h //Extended drawIndexedTriangleList
CVideoSoftware.cpp //Extended drawIndexedTriangleList
CVideoOpenGL.h //Extended drawIndexedTriangleList
CVideoOpenGL.cpp //Extended drawIndexedTriangleList
CVideoNull.h //Extended drawIndexedTriangleList
CVideoNull.cpp //Extended drawIndexedTriangleList
CVideoDirectX8.h //Extended drawIndexedTriangleList
CVideoDirectX8.cpp //Extended drawIndexedTriangleList
CMeshManipulator.cpp //Currently making it so it changes the strips too
CGeometryCreator.cpp //Thought it would be cool to stripify them too
I have pretty much finished the opengl rendering path expansion. Exept for the compiled vertex arrays. But I have a question on the DX stuff. (I am deffinatly NOT a DX coder, sorry).
Here is the current implementation
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0,
vertexCount,
triangleCount,
indexList,
D3DFMT_INDEX16,
vertices,
sizeof(S3DVertex));
Could someone please tell me what it would look like, if I wanted to change that to use triangle strips. For instance with opengl, its simply a change of
glDrawElements(GL_TRIANGLES, yada yada) to
glDrawElements(GL_TRIANGLE_STRIP, yad yada).
Second: I have a couple more updates. Well I started to actualy look @ the stl implementation inside of the tri_stripper library, turns out, NOT so easy to change. There is alot of stl in there, not just std::vector<>, but also deques and maps etc etc. So it looks like that may have to stay using stl. Which all and all isnt bad.
But I have been a busy little bee inside of the irlicht engine itself, here is a list of the files currently modified to use tri_stripping. If anyone can think of any others (before I go home and compile tonight) that might need to be changed, let me know. (I have no idea how you would know, what files need to be changed, but any help is help right, lol).
ImeshBuffer.h //Added: "return pointers to" and "size of" stripper object
SmeshBuffer.h //Added: same as above, w/ declration of stripper object
SmeshBufferLightMap.h //Ditto
ISceneManager.h //Added: bool "stripit" to getMesh();
CSceneManager.h //ditto
CSceneManager.cpp //Not sure if the pointer notations are correct yet. But
//added a routine to strippify the mesh (if bool passed).
IVideoDriver.h //Extended drawIndexedTriangleList
CMeshSceneNode.cpp //Extended drawIndexedTriangleList
CAnimatedMeshSceneNode.cpp //Extended drawIndexedTriangleList
CVideoSoftware.h //Extended drawIndexedTriangleList
CVideoSoftware.cpp //Extended drawIndexedTriangleList
CVideoOpenGL.h //Extended drawIndexedTriangleList
CVideoOpenGL.cpp //Extended drawIndexedTriangleList
CVideoNull.h //Extended drawIndexedTriangleList
CVideoNull.cpp //Extended drawIndexedTriangleList
CVideoDirectX8.h //Extended drawIndexedTriangleList
CVideoDirectX8.cpp //Extended drawIndexedTriangleList
CMeshManipulator.cpp //Currently making it so it changes the strips too
CGeometryCreator.cpp //Thought it would be cool to stripify them too
I have pretty much finished the opengl rendering path expansion. Exept for the compiled vertex arrays. But I have a question on the DX stuff. (I am deffinatly NOT a DX coder, sorry).
Here is the current implementation
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0,
vertexCount,
triangleCount,
indexList,
D3DFMT_INDEX16,
vertices,
sizeof(S3DVertex));
Could someone please tell me what it would look like, if I wanted to change that to use triangle strips. For instance with opengl, its simply a change of
glDrawElements(GL_TRIANGLES, yada yada) to
glDrawElements(GL_TRIANGLE_STRIP, yad yada).