#include "ASW_Graphics_OGL.h" #ifdef WIN32 PFNGLMULTIDRAWARRAYSEXTPROC glMultiDrawArrays; PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements; PFNGLMULTIDRAWELEMENTSPROC glMultiDrawElements; PFNGLACTIVETEXTUREPROC glActiveTexture; PFNGLACTIVESTENCILFACEEXTPROC glActiveStencilFaceEXT; PFNGLBUFFERDATAARBPROC glBufferDataARB; PFNGLBINDBUFFERARBPROC glBindBufferARB; PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB; PFNGLGENBUFFERSARBPROC glGenBuffersARB; PFNGLMAPBUFFERARBPROC glMapBufferARB; PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB; PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB; PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubDataARB; #endif OpenGLS::Exception:: Exception(const char * p_ptrFile, const unsigned int p_uintLine, const char * p_ptrFunction, const char * p_ptrDetail, const GLenum p_enmError) : ASW::Exception(p_ptrFile, p_uintLine, p_ptrFunction, p_ptrDetail), m_enmError(p_enmError) {} void OpenGLS::Exception:: Print(UTIL::Output & p_clsOutput) { p_clsOutput.Printf("OpenGL has generated an error.\n\nFile: [%s]\nLine: [%u]\nFunction: [%s]\nDetail: [%s]\nError: [%s]", ( m_ptrFile != NULL ) ? m_ptrFile : "unknown", m_uintLine, ( m_ptrFunction != NULL ) ? m_ptrFunction : "unknown", ( m_ptrDetail != NULL ) ? m_ptrDetail : "none", OpenGLS::ResultString(m_enmError)); } const char * OpenGLS::Exception:: Type() { return "OpenGL"; } /////////////////////////////////////////////////////////////////// // OpenGLS /////////////////////////////////////////////////////////////////// unsigned char g_uchrExtensionMask[(OpenGLS::EXT_AMOUNT / 8) + 1]; #define OGL_EXTENSION_SUPPORTED(ext_enum) ((g_uchrExtensionMask[ext_enum / 8] & (1 << ext_enum)) != 0 ) void InitExtensionMask() { static bool blnInitialized = false; if ( blnInitialized == false ) { memset(g_uchrExtensionMask, 0, (OpenGLS::EXT_AMOUNT / 8) + 1); const char * ptrExtensionList[OpenGLS::EXT_AMOUNT] = { "GL_EXT_stencil_two_side", }; const char * ptrExtensionsGL = (const char *)(glGetString(GL_EXTENSIONS)); for (unsigned int i=0; im_clsApi) == this, "Buffer is not loaded to this API object"); m_ptrActiveBufferIndex = p_ptrBuffer; } void OpenGLS:: Bind(const ASW::BufferVertex * p_ptrBuffer) { ASW_ASSERT(p_ptrBuffer == NULL || &(p_ptrBuffer->m_clsApi) == this, "Buffer is not loaded to this API object"); m_ptrActiveBufferVertex = p_ptrBuffer; if ( m_ptrActiveBufferVertex == NULL ) { OGL_RUN(glDisableClientState(GL_VERTEX_ARRAY)); OGL_RUN(glDisableClientState(GL_NORMAL_ARRAY)); OGL_RUN(glDisableClientState(GL_TEXTURE_COORD_ARRAY)); return; } if ( m_ptrActiveShaderVertex == NULL ) { // // Position // if ( p_ptrBuffer->m_ulngActiveMask & (1 << p_ptrBuffer->m_uchrElementPosition) ) { ASW::BufferVertex::Element stuElement = p_ptrBuffer->m_clsElements[p_ptrBuffer->m_uchrElementPosition]; ASW_ASSERT(stuElement.m_enmTypeElement == ASW::Type::ELEMENT_POSITION, "Incorrect element type"); OGL_RUN(glEnableClientState(GL_VERTEX_ARRAY)); OGL_RUN(glVertexPointer(stuElement.m_uchrElements, OpenGLS::m_enmDataTypes[stuElement.m_enmTypeData], p_ptrBuffer->m_uchrElementSize, ((const char *)(p_ptrBuffer->m_ptrData)) + stuElement.m_uchrOffset)); } else OGL_RUN(glDisableClientState(GL_VERTEX_ARRAY)); // // Normal // if ( p_ptrBuffer->m_ulngActiveMask & (1 << p_ptrBuffer->m_uchrElementNormal) ) { ASW::BufferVertex::Element stuElement = p_ptrBuffer->m_clsElements[p_ptrBuffer->m_uchrElementNormal]; ASW_ASSERT(stuElement.m_enmTypeElement == ASW::Type::ELEMENT_NORMAL, "Incorrect element type"); ASW_ASSERT(stuElement.m_uchrElements == 3, "NORMAL element must have 3 values"); OGL_RUN(glEnableClientState(GL_NORMAL_ARRAY)); OGL_RUN(glNormalPointer(OpenGLS::m_enmDataTypes[stuElement.m_enmTypeData], p_ptrBuffer->m_uchrElementSize, ((const char *)(p_ptrBuffer->m_ptrData)) + stuElement.m_uchrOffset)); } else OGL_RUN(glDisableClientState(GL_NORMAL_ARRAY)); // // Texture // if ( p_ptrBuffer->m_ulngActiveMask & (1 << p_ptrBuffer->m_uchrElementTexture) ) { ASW::BufferVertex::Element stuElement = p_ptrBuffer->m_clsElements[p_ptrBuffer->m_uchrElementTexture]; ASW_ASSERT(stuElement.m_enmTypeElement == ASW::Type::ELEMENT_TEXTURE, "Incorrect element type"); OGL_RUN(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); OGL_RUN(glTexCoordPointer(stuElement.m_uchrElements, OpenGLS::m_enmDataTypes[stuElement.m_enmTypeData], p_ptrBuffer->m_uchrElementSize, ((char *)(p_ptrBuffer->m_ptrData)) + stuElement.m_uchrOffset)); } else OGL_RUN(glDisableClientState(GL_TEXTURE_COORD_ARRAY)); } else { for (unsigned int i=0; im_ptrParametersVarying[i] == 0 ) continue; unsigned int j; for (j=0; jm_clsElements.size(); j++) { if ( (p_ptrBuffer->m_ulngActiveMask & (1 << j)) != 0 && (i + 1) == (int)(p_ptrBuffer->m_clsElements[j].m_enmTypeElement) ) { CG_RUN(cgGLEnableClientState(m_ptrActiveShaderVertex->m_ptrParametersVarying[i])); CG_RUN(cgGLSetParameterPointer(m_ptrActiveShaderVertex->m_ptrParametersVarying[i], p_ptrBuffer->m_clsElements[j].m_uchrElements, OpenGLS::m_enmDataTypes[p_ptrBuffer->m_clsElements[j].m_enmTypeData], p_ptrBuffer->m_uchrElementSize, ((const char *)(p_ptrBuffer->m_ptrData)) + p_ptrBuffer->m_clsElements[j].m_uchrOffset)); break; } } if ( j >= p_ptrBuffer->m_clsElements.size() ) CG_RUN(cgGLDisableClientState(m_ptrActiveShaderVertex->m_ptrParametersVarying[i])); } } } void OpenGLS:: Bind(const ASW::Shader * p_ptrShader, const ASW::Type::Shader p_enmType) { ASW_ASSERT(p_ptrShader == NULL || p_ptrShader->m_blnLoaded, "Cannot bind an unloaded shader"); ASW_ASSERT(p_ptrShader != NULL || p_enmType == ASW::Type::SHADER_VERTEX || p_enmType == ASW::Type::SHADER_PIXEL, "Invalid parameter"); if ( p_ptrShader != NULL ) { CG_RUN(cgGLEnableProfile(( p_ptrShader->m_enmType == ASW::Type::SHADER_VERTEX ) ? m_enmCgProfileVertex : m_enmCgProfilePixel)); if ( cgGLIsProgramLoaded(p_ptrShader->m_clsProgram) != CG_TRUE ) CG_RUN(cgGLLoadProgram(p_ptrShader->m_clsProgram)); CG_RUN(cgGLBindProgram(p_ptrShader->m_clsProgram)); m_ptrActiveShaderVertex = p_ptrShader; } else if ( p_enmType == ASW::Type::SHADER_VERTEX ) { CG_RUN(cgGLDisableProfile(m_enmCgProfileVertex)); m_ptrActiveShaderVertex = NULL; } else if ( p_enmType == ASW::Type::SHADER_PIXEL ) { CG_RUN(cgGLDisableProfile(m_enmCgProfilePixel)); m_ptrActiveShaderPixel = NULL; } } void OpenGLS:: Bind(const ASW::Texture * p_ptrTexture, const unsigned int p_uintStage) { ASW_ASSERT(p_ptrTexture == NULL || p_ptrTexture->m_blnLoaded, "Cannot bind an unloaded texture"); ASW_ASSERT(p_uintStage < m_uintMaxTextures, "Stage exceeds maximum number of textures"); OGL_RUN(glActiveTexture((GLenum)(GL_TEXTURE0 + p_uintStage))); if ( p_ptrTexture != NULL ) { GLenum enmAddressMode[] = {GL_REPEAT, GL_CLAMP}; GLenum enmFilterMode[] = {GL_NEAREST, GL_LINEAR}; GLenum enmTargets[] = {GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D}; OGL_RUN(glMatrixMode(GL_TEXTURE)); OGL_RUN(glLoadMatrixf(p_ptrTexture->m_stuMatrix)); OGL_RUN(glBindTexture(enmTargets[p_ptrTexture->m_uchrDimensions - 1], (unsigned int)(p_ptrTexture->m_ptrObject))); OGL_RUN(glTexParameteri(enmTargets[p_ptrTexture->m_uchrDimensions - 1], GL_TEXTURE_MIN_FILTER, enmFilterMode[p_ptrTexture->m_enmFilterMode[0]])); OGL_RUN(glTexParameteri(enmTargets[p_ptrTexture->m_uchrDimensions - 1], GL_TEXTURE_MAG_FILTER, enmFilterMode[p_ptrTexture->m_enmFilterMode[1]])); OGL_RUN(glTexParameteri(enmTargets[p_ptrTexture->m_uchrDimensions - 1], GL_TEXTURE_WRAP_S, enmAddressMode[p_ptrTexture->m_enmAddressMode[0]])); OGL_RUN(glTexParameteri(enmTargets[p_ptrTexture->m_uchrDimensions - 1], GL_TEXTURE_WRAP_T, enmAddressMode[p_ptrTexture->m_enmAddressMode[1]])); } else OGL_RUN(glBindTexture(GL_TEXTURE_2D, 0)); } void OpenGLS:: Blend(const ASW::GraphicsApi::BlendType p_enmSourceType, const ASW::GraphicsApi::BlendType p_enmDestinationType) { ASW_ASSERT((int)(p_enmSourceType) > (int)(ASW::GraphicsApi::BLEND_UNKNOWN) && (int)(p_enmSourceType) <= (int)(ASW::GraphicsApi::BLEND_COUNT), "Invalid parameter"); ASW_ASSERT((int)(p_enmDestinationType) > (int)(ASW::GraphicsApi::BLEND_UNKNOWN) && (int)(p_enmDestinationType) <= (int)(ASW::GraphicsApi::BLEND_COUNT), "Invalid parameter"); GLenum enmTypes[ASW::GraphicsApi::BLEND_COUNT] = { GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA_SATURATE, }; OGL_RUN(glBlendFunc(enmTypes[p_enmSourceType - 1], enmTypes[p_enmDestinationType - 1])); } void OpenGLS:: BufferClear(const unsigned int p_uintMask) { unsigned int uintMask = 0; if ( p_uintMask & ASW::GraphicsApi::BUFFER_COLOR ) uintMask |= GL_COLOR_BUFFER_BIT; if ( p_uintMask & ASW::GraphicsApi::BUFFER_DEPTH ) uintMask |= GL_DEPTH_BUFFER_BIT; if ( p_uintMask & ASW::GraphicsApi::BUFFER_STENCIL ) uintMask |= GL_STENCIL_BUFFER_BIT; OGL_RUN(glClear(uintMask)); } void OpenGLS:: BufferEnable(const unsigned int p_uintMask, const bool p_blnEnable) { if ( (p_uintMask & ASW::GraphicsApi::BUFFER_COLOR) != 0 ) { GLboolean enmBool = ( p_blnEnable ) ? GL_TRUE : GL_FALSE; OGL_RUN(glColorMask(enmBool, enmBool, enmBool, enmBool)); } if ( (p_uintMask & ASW::GraphicsApi::BUFFER_DEPTH) != 0 ) OGL_RUN(glDepthMask(( p_blnEnable ) ? GL_TRUE : GL_FALSE)); if ( (p_uintMask & ASW::GraphicsApi::BUFFER_STENCIL) != 0 ) OGL_RUN(glStencilMask(( p_blnEnable ) ? (GLuint)(-1) : 0)); } bool OpenGLS:: CheckEnable(const ASW::GraphicsApi::PropertyType p_enmProperty) { switch ( p_enmProperty ) { case ASW::GraphicsApi::PROPERTY_TWO_SIDED_STENCIL: return OGL_EXTENSION_SUPPORTED(OpenGLS::EXT_STENCIL_TEST_TWO_SIDE); default: return true; } } void OpenGLS:: ClearColor(const unsigned char p_uchrRed, const unsigned char p_uchrGreen, const unsigned char p_uchrBlue, const unsigned char p_uchrAlpha) { OGL_RUN(glClearColor((float)(p_uchrRed * (1.0f / 255.0f)), (float)(p_uchrGreen * (1.0f / 255.0f)), (float)(p_uchrBlue * (1.0f / 255.0f)), (float)(p_uchrAlpha * (1.0f / 255.0f)))); } void OpenGLS:: ClearDepth(const float p_fltDepth) { OGL_RUN(glClearDepth(p_fltDepth)); } void OpenGLS:: CullMode(const ASW::GraphicsApi::CullType p_enmType) { ASW_ASSERT((int)(p_enmType) > (int)(ASW::GraphicsApi::CULL_UNKNOWN) && (int)(p_enmType) <= (int)(ASW::GraphicsApi::CULL_COUNT), "Invalid parameter"); if ( p_enmType != ASW::GraphicsApi::CULL_NONE ) { GLenum enmTypes[] = { GL_BACK, GL_FRONT, GL_FRONT_AND_BACK }; OGL_RUN(glEnable(GL_CULL_FACE)); OGL_RUN(glCullFace(enmTypes[p_enmType - 2])); } else OGL_RUN(glDisable(GL_CULL_FACE)); } void OpenGLS:: Draw(const ASW::Type::Primitive p_enmType, const ASW::BufferVertex::Index & p_clsIndex) { ASW_ASSERT(m_ptrActiveBufferVertex != NULL, "No vertex buffer bound"); ASW_ASSERT((int)(p_enmType) > (int)(ASW::Type::PRIMITIVE_UNKNOWN) && (int)(p_enmType) <= (int)(ASW::Type::PRIMITIVE_COUNT), "Invalid primitive type"); ASW_ASSERT(p_enmType != ASW::Type::PRIMITIVE_LINES || ((p_clsIndex.m_stuIndices[1] - p_clsIndex.m_stuIndices[0]) % 2) == 0, "Incorrect number of vertices for PRIMITIVE_LINES"); ASW_ASSERT(p_enmType != ASW::Type::PRIMITIVE_TRIANGLES || ((p_clsIndex.m_stuIndices[1] - p_clsIndex.m_stuIndices[0]) % 3) == 0, "Incorrect number of vertices for PRIMITIVE_TRIANGLES"); OGL_RUN(glDrawArrays(m_enmPrimitiveTypes[p_enmType - 1], (GLint)(p_clsIndex.m_stuIndices[0]), (GLsizei)(p_clsIndex.m_stuIndices[1] - p_clsIndex.m_stuIndices[0]))); } void OpenGLS:: Draw(const ASW::Type::Primitive p_enmType, const ASW::BufferIndex::Index & p_clsIndex) { ASW_ASSERT(m_ptrActiveBufferVertex != NULL && m_ptrActiveBufferIndex != NULL, "No vertex and/or index buffers bound"); ASW_ASSERT((int)(p_enmType) > (int)(ASW::Type::PRIMITIVE_UNKNOWN) && (int)(p_enmType) <= (int)(ASW::Type::PRIMITIVE_COUNT), "Invalid primitive type"); ASW_ASSERT(p_enmType != ASW::Type::PRIMITIVE_LINES || ((p_clsIndex.m_stuIndices[1] - p_clsIndex.m_stuIndices[0]) % 2) == 0, "Incorrect number of vertices for PRIMITIVE_LINES"); ASW_ASSERT(p_enmType != ASW::Type::PRIMITIVE_TRIANGLES || ((p_clsIndex.m_stuIndices[1] - p_clsIndex.m_stuIndices[0]) % 3) == 0, "Incorrect number of vertices for PRIMITIVE_TRIANGLES"); OGL_RUN(glDrawRangeElements(OpenGLS::m_enmPrimitiveTypes[p_enmType - 1], (GLuint)(p_clsIndex.m_stuIndicesRange[0]), (GLuint)(p_clsIndex.m_stuIndicesRange[1]), (GLsizei)(p_clsIndex.m_stuIndices[1] - p_clsIndex.m_stuIndices[0]), OpenGLS::m_enmDataTypes[m_ptrActiveBufferIndex->m_enmDataType], ((char *)(m_ptrActiveBufferIndex->m_ptrData)) + (p_clsIndex.m_stuIndices[0] * m_ptrActiveBufferIndex->m_uchrElementSize))); } void OpenGLS:: DrawIndices(const ASW::Type::Primitive p_enmType, const ASW::CompositeIndex ** p_ptrIndices, const unsigned int p_uintAmount) { ASW_ASSERT(m_ptrActiveBufferVertex != NULL && m_ptrActiveBufferIndex != NULL, "OpenGLS::Draw"); ASW_ASSERT((int)(p_enmType) > (int)(ASW::Type::PRIMITIVE_UNKNOWN) && (int)(p_enmType) <= (int)(ASW::Type::PRIMITIVE_COUNT), "Invalid primitive type"); GLsizei * ptrAmounts = (GLsizei *)(alloca(p_uintAmount * (sizeof(GLsizei) + sizeof(GLvoid *)))); const GLvoid ** ptrTemp = (const GLvoid **)(ptrAmounts + p_uintAmount); ASW_ASSERT(ptrAmounts != NULL, "Unable to allocate stack memory"); for (unsigned int i=0; im_stuIndices[1] - ptrIndex->m_stuIndices[0]); ptrTemp[i] = ((char *)(m_ptrActiveBufferIndex->m_ptrData)) + (ptrIndex->m_stuIndices[0] * m_ptrActiveBufferIndex->m_uchrElementSize); ASW_ASSERT(p_enmType != ASW::Type::PRIMITIVE_LINES || (ptrAmounts[i] % 2) == 0, "Incorrect number of vertices for PRIMITIVE_LINES"); ASW_ASSERT(p_enmType != ASW::Type::PRIMITIVE_TRIANGLES || (ptrAmounts[i] % 3) == 0, "Incorrect number of vertices for PRIMITIVE_TRIANGLES"); } OGL_RUN(glMultiDrawElements(m_enmPrimitiveTypes[p_enmType - 1], ptrAmounts, OpenGLS::m_enmDataTypes[m_ptrActiveBufferIndex->m_enmDataType], ptrTemp, (GLsizei)(p_uintAmount))); } void OpenGLS:: DrawVertices(const ASW::Type::Primitive p_enmType, const ASW::CompositeIndex ** p_ptrIndices, const unsigned int p_uintAmount) { ASW_ASSERT(m_ptrActiveBufferVertex != NULL, "No vertex buffer bound"); ASW_ASSERT((int)(p_enmType) > (int)(ASW::Type::PRIMITIVE_UNKNOWN) && (int)(p_enmType) <= (int)(ASW::Type::PRIMITIVE_COUNT), "Invalid primitive type"); GLint * ptrStarts = (GLint *)(alloca(p_uintAmount * (sizeof(GLint) + sizeof(GLsizei)))); GLsizei * ptrAmounts = (GLsizei *)(ptrStarts + p_uintAmount); ASW_ASSERT(ptrStarts != NULL, "Unable to allocate stack memory"); for (unsigned int i=0; im_stuIndices[0]); ptrAmounts[i] = (GLsizei)(ptrIndex->m_stuIndices[1] - ptrIndex->m_stuIndices[0]); ASW_ASSERT(p_enmType != ASW::Type::PRIMITIVE_LINES || (ptrAmounts[i] % 2) == 0, "Incorrect number of vertices for PRIMITIVE_LINES"); ASW_ASSERT(p_enmType != ASW::Type::PRIMITIVE_TRIANGLES || (ptrAmounts[i] % 3) == 0, "Incorrect number of vertices for PRIMITIVE_TRIANGLES"); } OGL_RUN(glMultiDrawArrays(OpenGLS::m_enmPrimitiveTypes[p_enmType - 1], ptrStarts, ptrAmounts, (GLsizei)(p_uintAmount))); } void OpenGLS:: Enable(const ASW::GraphicsApi::PropertyType p_enmProperty, const bool p_blnEnable) { ASW_ASSERT((int)(p_enmProperty) > (int)(ASW::GraphicsApi::PROPERTY_UNKNOWN) && (int)(p_enmProperty) <= (int)(ASW::GraphicsApi::PROPERTY_COUNT), "Invalid parameter"); m_blnProperties[p_enmProperty - 1] = p_blnEnable; switch ( p_enmProperty ) { case ASW::GraphicsApi::PROPERTY_TEXTURING: if ( p_blnEnable == false ) { OGL_RUN(glDisable(GL_TEXTURE_1D)); OGL_RUN(glDisable(GL_TEXTURE_2D)); } else { if ( m_blnProperties[ASW::GraphicsApi::PROPERTY_TEXTURE_1D - 1] ) OGL_RUN(glEnable(GL_TEXTURE_1D)); if ( m_blnProperties[ASW::GraphicsApi::PROPERTY_TEXTURE_2D - 1] ) OGL_RUN(glEnable(GL_TEXTURE_2D)); } break; case ASW::GraphicsApi::PROPERTY_TEXTURE_1D: if ( p_blnEnable == false ) OGL_RUN(glDisable(GL_TEXTURE_1D)); else if ( m_blnProperties[ASW::GraphicsApi::PROPERTY_TEXTURING - 1] ) OGL_RUN(glEnable(GL_TEXTURE_1D)); break; case ASW::GraphicsApi::PROPERTY_TEXTURE_2D: if ( p_blnEnable == false ) OGL_RUN(glDisable(GL_TEXTURE_2D)); else if ( m_blnProperties[ASW::GraphicsApi::PROPERTY_TEXTURING - 1] ) OGL_RUN(glEnable(GL_TEXTURE_2D)); break; default: void (STDCALL * ptrEnableFunc)(GLenum) = ( p_blnEnable ) ? glEnable : glDisable; OGL_RUN(ptrEnableFunc(m_enmFlags[p_enmProperty - 1])); break; } } void OpenGLS:: EnableLight(const unsigned int p_uintIndex, const bool p_blnEnable) { ASW_ASSERT(p_uintIndex < m_uintMaxLights, "Index exceeds maximum number of lights"); void (STDCALL * ptrEnableFunc)(GLenum) = ( p_blnEnable ) ? glEnable : glDisable; OGL_RUN(ptrEnableFunc((GLenum)(GL_LIGHT0 + p_uintIndex))); } void OpenGLS:: FillMode(const ASW::GraphicsApi::FillType p_enmType) { ASW_ASSERT((int)(p_enmType) > (int)(ASW::GraphicsApi::FILL_UNKNOWN) && (int)(p_enmType) <= (int)(ASW::GraphicsApi::FILL_COUNT), "Invalid parameter"); GLenum enmTypes[] = { GL_POINT, GL_LINE, GL_FILL }; OGL_RUN(glPolygonMode(GL_FRONT_AND_BACK, enmTypes[p_enmType - 1])); } ASW::Colorf OpenGLS:: GetAmbience() { ASW::Colorf stuReturn; OGL_RUN(glGetFloatv(GL_LIGHT_MODEL_AMBIENT, (GLfloat *)(&stuReturn))); return stuReturn; } void OpenGLS:: GetDeviceInfo(std::string & p_clsDevice, std::string & p_clsApi) { p_clsDevice = (const char *)(glGetString(GL_VENDOR)); p_clsDevice += " - "; p_clsDevice += (const char *)(glGetString(GL_RENDERER)); p_clsApi = "OpenGL "; p_clsApi += (const char *)(glGetString(GL_VERSION)); } ASW::Point4i OpenGLS:: GetViewport(ASW::Point2f * p_ptrDepthRange) { ASW::Point4i stuReturn; glGetIntegerv(GL_VIEWPORT, stuReturn); if ( p_ptrDepthRange ) glGetFloatv(GL_DEPTH_RANGE, (GLfloat *)(p_ptrDepthRange)); return stuReturn; } bool OpenGLS:: Load(ASW::Shader & p_clsShader, const char * p_ptrFileName, const char * p_ptrEntryPoint) { if ( ASW::GraphicsApi::Load(p_clsShader, p_ptrFileName, p_ptrEntryPoint) == false ) { return false; } CG_RUN(cgGLLoadProgram(p_clsShader.m_clsProgram)); return true; } bool OpenGLS:: Load(ASW::Texture & p_clsTexture) { ASW_ASSERT(p_clsTexture.m_blnLoaded == false, "Texture has already been loaded"); /* Texture coords in OpenGL: (0.0,1.0) (1.0,1.0) _______________ | | | | | | | | | | | | |_______________| (0.0,0.0) (1.0,0.0) */ // // Read the texture file // unsigned int uintWidth; unsigned int uintHeight; unsigned short ushtChannels; unsigned char * ptrTextureData; if ( UTIL::Image::Read(p_clsTexture.m_ptrFileName, UTIL::Image::UNKNOWN, &uintWidth, &uintHeight, &ushtChannels, (void **)(&ptrTextureData)) == false ) { return false; } else if ( ushtChannels > 4 ) { delete [] ptrTextureData; return false; } // // Create the texture object // glGenTextures(1, (unsigned int *)(&(p_clsTexture.m_ptrObject))); if ( uintHeight > 1 ) { p_clsTexture.m_uchrDimensions = 2; glBindTexture(GL_TEXTURE_2D, (unsigned int)(p_clsTexture.m_ptrObject)); if ( glIsTexture((unsigned int)(p_clsTexture.m_ptrObject)) != GL_TRUE ) { glDeleteTextures(1, (unsigned int *)(&(p_clsTexture.m_ptrObject))); delete [] ptrTextureData; return false; } // WARNING: ERROR CHECKING NOT PERFORMED FOR THE FOLLOWING 3 OpenGL FUNCTION CALLS GLenum enmFormats[] = {0, GL_ALPHA, 0, GL_BGR_EXT, GL_BGRA_EXT}; glTexImage2D(GL_TEXTURE_2D, 0, (int)(ushtChannels), uintWidth, uintHeight, 0, enmFormats[ushtChannels], GL_UNSIGNED_BYTE, ptrTextureData); } else { p_clsTexture.m_uchrDimensions = 1; glBindTexture(GL_TEXTURE_1D, (unsigned int)(p_clsTexture.m_ptrObject)); if ( glIsTexture((unsigned int)(p_clsTexture.m_ptrObject)) != GL_TRUE ) { glDeleteTextures(1, (unsigned int *)(&(p_clsTexture.m_ptrObject))); delete [] ptrTextureData; return false; } // WARNING: ERROR CHECKING NOT PERFORMED FOR THE FOLLOWING 3 OpenGL FUNCTION CALLS GLenum enmFormats[] = {0, GL_ALPHA, 0, GL_BGR_EXT, GL_BGRA_EXT}; glTexImage1D(GL_TEXTURE_1D, 0, (int)(ushtChannels), uintWidth, 0, enmFormats[ushtChannels], GL_UNSIGNED_BYTE, ptrTextureData); } delete [] ptrTextureData; p_clsTexture.SetMatrix(ASW::Type::DIRECTION_RIGHT, ASW::Type::DIRECTION_UP); p_clsTexture.m_blnLoaded = true; return true; } void * OpenGLS:: Lock(ASW::Buffer & p_clsBuffer, const unsigned int p_uintOffset, const unsigned int p_uintSize, const ASW::Type::HintAccess) { ASW_ASSERT(&(p_clsBuffer.m_clsApi) == this, "Buffer is not loaded to this API object"); if ( p_clsBuffer.m_blnIsIndexBuffer && m_ptrActiveBufferIndex != (ASW::BufferIndex *)(&p_clsBuffer) ) m_ptrActiveBufferIndex = NULL; else if ( p_clsBuffer.m_blnIsIndexBuffer == false && m_ptrActiveBufferVertex != (ASW::BufferVertex *)(&p_clsBuffer) ) m_ptrActiveBufferVertex = NULL; return ((char *)(p_clsBuffer.m_ptrData)) + p_uintOffset; } UTIL::D3::Matrix OpenGLS:: MatrixBuild(const unsigned int p_uintWidth, const unsigned int p_uintHeight, const float p_fltPlaneNear, const float p_fltPlaneFar, const float p_fltFov) { ASW_ASSERT(p_fltPlaneNear != p_fltPlaneFar, "Near/far are the same value"); ASW_ASSERT(p_uintWidth > 0 && p_uintHeight > 0, "Width/height must both be non-zero"); UTIL::D3::Matrix stuResult; float fltWidth = (float)(( p_uintWidth > 0 ) ? p_uintWidth : 1); float fltHeight = (float)(( p_uintHeight > 0 ) ? p_uintHeight : 1); if ( p_fltFov > 0.0f ) { float fltRadians = p_fltFov * (float)(UTIL_PI / 180.0f) * 0.5f; float fltCot = cosf(fltRadians) / sinf(fltRadians); float fltDelta = 1.0f / (p_fltPlaneNear - p_fltPlaneFar); stuResult.m_flt11 = fltCot * (fltHeight / fltWidth); stuResult.m_flt22 = fltCot; stuResult.m_flt33 = 2.0f * p_fltPlaneFar * p_fltPlaneNear * fltDelta; stuResult.m_stuTranslation = ASW::Point3f(0.0f, 0.0f, 2.0f * p_fltPlaneFar * p_fltPlaneNear * fltDelta); stuResult.m_fltExtraZ = -1.0f; stuResult.m_fltExtra = 0.0f; //stuResult.m_stuBasisX = ASW::Point3f(fltCot / fltAspect, 0.0f, 0.0f); //stuResult.m_stuBasisY = ASW::Point3f(0.0f, fltCot, 0.0f); //stuResult.m_stuBasisZ = ASW::Point3f(0.0f, 0.0f, (p_fltPlaneFar + p_fltPlaneNear) * fltDelta); //stuResult.m_fltExtraX = 0.0f; //stuResult.m_fltExtraY = 0.0f; //stuResult.m_fltExtraZ = -1.0f; //stuResult.m_fltExtra = 0.0f; } else { float fltWidth = (float)(( p_uintWidth > 0 ) ? p_uintWidth : 1); ASW::Point3f stuDelta(1.0f / fltWidth, 1.0f / -fltHeight, 1.0f / (p_fltPlaneFar - p_fltPlaneNear)); stuResult.m_flt11 = +2.0f * stuDelta[0]; stuResult.m_flt22 = +2.0f * stuDelta[1]; stuResult.m_flt33 = -2.0f * stuDelta[2]; stuResult.m_stuTranslation = ASW::Point3f(fltWidth, fltHeight, p_fltPlaneFar + p_fltPlaneNear) * stuDelta * -1.0f; stuResult.m_fltExtraZ = 0.0f; stuResult.m_fltExtra = 1.0f; } stuResult.m_flt12 = stuResult.m_flt13 = stuResult.m_flt14 = stuResult.m_flt21 = stuResult.m_flt23 = stuResult.m_flt24 = stuResult.m_flt31 = stuResult.m_flt32 = 0.0f; return stuResult; } UTIL::D3::Matrix OpenGLS:: MatrixGet(const ASW::Type::Matrix p_enmType) { ASW_ASSERT((int)(p_enmType) > (int)(ASW::Type::MATRIX_UNKNOWN) && (int)(p_enmType) <= (int)(ASW::Type::MATRIX_COUNT), "Invalid parameter"); GLenum enmTypes[] = { GL_PROJECTION_MATRIX, GL_TEXTURE_MATRIX, GL_MODELVIEW_MATRIX, }; UTIL::D3::Matrix stuMatrix; OGL_RUN(glGetFloatv(enmTypes[p_enmType - 1], (float *)(&stuMatrix))); return stuMatrix; } void OpenGLS:: MatrixSet(const ASW::Type::Matrix p_enmType, const UTIL::D3::Matrix & p_stuMatrix) { ASW_ASSERT((int)(p_enmType) > (int)(ASW::Type::MATRIX_UNKNOWN) && (int)(p_enmType) <= (int)(ASW::Type::MATRIX_COUNT), "Invalid parameter"); OGL_RUN(glMatrixMode(OpenGLS::m_enmMatrixTypes[p_enmType - 1])); OGL_RUN(glLoadMatrixf((GLfloat *)(&p_stuMatrix))); } //void //OpenGLS:: //MatrixSet(const unsigned int p_uintWidth, // const unsigned int p_uintHeight) //{ // OGL_RUN(glMatrixMode(GL_PROJECTION)); // OGL_RUN(glLoadIdentity()); // OGL_RUN(gluOrtho2D(0, // p_uintWidth, // p_uintHeight, // 0)); //} // //void //OpenGLS:: //MatrixSet(const unsigned int p_uintWidth, // const unsigned int p_uintHeight, // const float p_fltPlaneNear, // const float p_fltPlaneFar) //{ // float fltAspect = ((float)(p_uintWidth)) / ((float)(( p_uintHeight > 0 ) ? p_uintHeight : 1)); // float fltRadians = 45.0f * (float)(UTIL_PI / 180.0f) * 0.5f; // float fltSine = sinf(fltRadians); // float fltDelta = p_fltPlaneNear - p_fltPlaneFar; // if ( fltSine == 0.0f || fltDelta == 0.0f ) // return; // float fltCot = cosf(fltRadians) / fltSine; // fltDelta = 1.0f / fltDelta; // // UTIL::D3::Matrix stuPerspective; // stuPerspective.m_stuBasisX = ASW::Point3f(fltCot / fltAspect, 0.0f, 0.0f); // stuPerspective.m_stuBasisY = ASW::Point3f(0.0f, fltCot, 0.0f); // stuPerspective.m_stuBasisZ = ASW::Point3f(0.0f, 0.0f, (p_fltPlaneFar + p_fltPlaneNear) * fltDelta); // stuPerspective.m_stuTranslation = ASW::Point3f(0.0f, 0.0f, 2.0f * p_fltPlaneFar * p_fltPlaneNear * fltDelta); // stuPerspective.m_fltExtraX = 0.0f; // stuPerspective.m_fltExtraY = 0.0f; // stuPerspective.m_fltExtraZ = -1.0f; // stuPerspective.m_fltExtra = 0.0f; // // OGL_RUN(glMatrixMode(GL_PROJECTION)); // OGL_RUN(glLoadMatrixf(stuPerspective)); //} void OpenGLS:: Print(const ASW::GraphicsApi::DrawTextInfo & p_stuInfo) { ASW_ASSERT(p_stuInfo.m_enmHorizontal == ASW::Type::ALIGN_LEFT || p_stuInfo.m_enmHorizontal == ASW::Type::ALIGN_MIDDLE || p_stuInfo.m_enmHorizontal == ASW::Type::ALIGN_RIGHT, "Invalid horizontal alignment"); ASW_ASSERT(p_stuInfo.m_enmVertical == ASW::Type::ALIGN_TOP || p_stuInfo.m_enmVertical == ASW::Type::ALIGN_MIDDLE || p_stuInfo.m_enmVertical == ASW::Type::ALIGN_BOTTOM, "Invalid vertical alignment"); // // Horizontal alignment // int intRasterX; if ( p_stuInfo.m_enmHorizontal == ASW::Type::ALIGN_LEFT ) intRasterX = p_stuInfo.m_stuBox[0]; else if ( p_stuInfo.m_enmHorizontal == ASW::Type::ALIGN_RIGHT ) intRasterX = p_stuInfo.m_stuBox[1]; else intRasterX = p_stuInfo.m_stuBox[0] + ((p_stuInfo.m_stuBox[1] - p_stuInfo.m_stuBox[0]) - UTIL::Round(p_stuInfo.m_stuSize[0] * 0.5f)); // // Vertical alignment // int intRasterY; if ( p_stuInfo.m_enmVertical == ASW::Type::ALIGN_TOP ) intRasterY = p_stuInfo.m_stuBox[2] + UTIL::Round(p_stuInfo.m_stuSize[1]); else if ( p_stuInfo.m_enmVertical == ASW::Type::ALIGN_BOTTOM ) intRasterY = p_stuInfo.m_stuBox[2]; else intRasterY = p_stuInfo.m_stuBox[2] + UTIL::Round((((float)(p_stuInfo.m_stuBox[3] - p_stuInfo.m_stuBox[2])) + p_stuInfo.m_stuSize[2]) * 0.5f); OGL_RUN(glColor4f(p_stuInfo.m_stuColor[0], p_stuInfo.m_stuColor[1], p_stuInfo.m_stuColor[2], p_stuInfo.m_stuColor[3])); OGL_RUN(glRasterPos2i(intRasterX, intRasterY)); OGL_RUN(glPushAttrib(GL_LIST_BIT)); OGL_RUN(glListBase(((unsigned int)(p_stuInfo.m_ptrFont->m_ptrData[0])) - ASW_FONT_FIRST_CHARACTER)); OGL_RUN(glCallLists((GLsizei)(strlen(p_stuInfo.m_ptrText)), GL_UNSIGNED_BYTE, p_stuInfo.m_ptrText)); OGL_RUN(glPopAttrib()); } void OpenGLS:: Resize(const unsigned int p_uintWidth, const unsigned int p_uintHeight) { OGL_RUN(glViewport(0, 0, p_uintWidth, (( p_uintHeight > 0 ) ? p_uintHeight : 1))); } const char * OpenGLS:: ResultString(const GLenum p_enmResult) { switch ( p_enmResult ) { case GL_NO_ERROR: return "GL_NO_ERROR"; case GL_INVALID_ENUM: return "GL_INVALID_ENUM"; case GL_INVALID_VALUE: return "GL_INVALID_VALUE"; case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION"; case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW"; case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW"; case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY"; default: return "(unknown)"; } } void OpenGLS:: Set(ASW::Buffer & p_clsBuffer, const void * p_ptrData, const unsigned int p_uintOffset, const unsigned int p_uintSize) { ASW_ASSERT(&(p_clsBuffer.m_clsApi) == this, "Buffer is not loaded to this API object"); ASW_ASSERT((p_uintOffset + p_uintSize) <= (p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize), "Size/offset exceeds buffer size"); memcpy((char *)(p_clsBuffer.m_ptrData) + p_uintOffset, p_ptrData, p_uintSize); } void OpenGLS:: SetLight(const unsigned int p_uintIndex, const ASW::Instance::Light & p_clsLight) { ASW_ASSERT(p_uintIndex < m_uintMaxLights, "Index exceeds maximum number of lights"); ASW::Point3f stuRotation; ASW::Point3f stuTranslation; p_clsLight.GetTransform(stuRotation, stuTranslation, true); ASW::Parameters::Light stuParams = p_clsLight.GetParams(); GLenum enmLight = (GLenum)(GL_LIGHT0 + p_uintIndex); OGL_RUN(glLightfv(enmLight, GL_AMBIENT, (const GLfloat *)(&(stuParams.m_stuAmbient)))); OGL_RUN(glLightfv(enmLight, GL_DIFFUSE, (const GLfloat *)(&(stuParams.m_stuDiffuse)))); OGL_RUN(glLightfv(enmLight, GL_SPECULAR, (const GLfloat *)(&(stuParams.m_stuSpecular)))); if ( stuParams.m_enmType == ASW::Type::LIGHT_DIRECTIONAL ) { GLfloat fltValues[4] = { stuRotation[0] * -1.0f, stuRotation[1] * -1.0f, stuRotation[2] * -1.0f, 0.0f, }; OGL_RUN(glLightfv(enmLight, GL_POSITION, fltValues)); // modified by modelview matrix return; } GLfloat fltValues[4] = { stuTranslation[0], stuTranslation[1], stuTranslation[2], 1.0f, }; OGL_RUN(glLightfv(enmLight, GL_POSITION, fltValues)); // modified by modelview matrix OGL_RUN(glLightfv(enmLight, GL_CONSTANT_ATTENUATION, (const GLfloat *)(&(stuParams.m_stuAttenuation[0])))); OGL_RUN(glLightfv(enmLight, GL_LINEAR_ATTENUATION, (const GLfloat *)(&(stuParams.m_stuAttenuation[1])))); OGL_RUN(glLightfv(enmLight, GL_QUADRATIC_ATTENUATION, (const GLfloat *)(&(stuParams.m_stuAttenuation[2])))); if ( stuParams.m_enmType == ASW::Type::LIGHT_SPOT ) { GLfloat fltValues[3] = { stuRotation[0], stuRotation[1], stuRotation[2], }; OGL_RUN(glLightfv(enmLight, GL_SPOT_DIRECTION, fltValues)); // modified by inverse of modelview matrix OGL_RUN(glLightfv(enmLight, GL_SPOT_EXPONENT, (const GLfloat *)(&(stuParams.m_fltFocus)))); // exponent: 0-128 OGL_RUN(glLightfv(enmLight, GL_SPOT_CUTOFF, (const GLfloat *)(&(stuParams.m_fltAngle)))); // angle: 0-90 } } void OpenGLS:: SetAmbience(const ASW::Colorf & p_stuAmbience) { OGL_RUN(glLightModelfv(GL_LIGHT_MODEL_AMBIENT, p_stuAmbience)); } void OpenGLS:: SetDepthTest(const ASW::GraphicsApi::Test p_enmTest) { ASW_ASSERT((int)(p_enmTest) > (int)(ASW::GraphicsApi::TEST_UNKNOWN) && (int)(p_enmTest) <= (int)(ASW::GraphicsApi::TEST_COUNT), "Invalid parameter"); OGL_RUN(glDepthFunc(OpenGLS::m_enmTests[p_enmTest - 1])); } void OpenGLS:: SetScissorRectangle(const int p_intLeft, const int p_intBottom, const unsigned int p_uintWidth, const unsigned int p_uintHeight) { OGL_RUN(glScissor((GLint)(p_intLeft), (GLint)(p_intBottom), (GLsizei)(p_uintWidth), (GLsizei)(p_uintHeight))); } void OpenGLS:: SetStencilTest(const ASW::GraphicsApi::Test p_enmTest, const int p_intReference, const unsigned int p_uintMask, const bool p_blnFront) { ASW_ASSERT((int)(p_enmTest) > (int)(ASW::GraphicsApi::TEST_UNKNOWN) && (int)(p_enmTest) <= (int)(ASW::GraphicsApi::TEST_COUNT), "Invalid parameter"); if ( p_blnFront == false ) { OGL_RUN(glActiveStencilFaceEXT(GL_BACK)); OGL_RUN(glStencilFunc(OpenGLS::m_enmTests[p_enmTest - 1], (GLint)(p_intReference), (GLuint)(p_uintMask))); OGL_RUN(glActiveStencilFaceEXT(GL_FRONT)); } else { OGL_RUN(glStencilFunc(OpenGLS::m_enmTests[p_enmTest - 1], (GLint)(p_intReference), (GLuint)(p_uintMask))); } } void OpenGLS:: SetStencilWriteMask(const unsigned int p_uintMask, const bool p_blnFront) { if ( p_blnFront == false ) { OGL_RUN(glActiveStencilFaceEXT(GL_BACK)); OGL_RUN(glStencilMask((GLuint)(p_uintMask))); OGL_RUN(glActiveStencilFaceEXT(GL_FRONT)); } else OGL_RUN(glStencilMask((GLuint)(p_uintMask))); } void OpenGLS:: SetStencilOp(const ASW::GraphicsApi::StencilOp p_enmTestFail, const ASW::GraphicsApi::StencilOp p_enmTestPassDepthFail, const ASW::GraphicsApi::StencilOp p_enmTestPassDepthPass, const bool p_blnFront) { ASW_ASSERT((int)(p_enmTestFail) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestFail) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); ASW_ASSERT((int)(p_enmTestPassDepthFail) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestPassDepthFail) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); ASW_ASSERT((int)(p_enmTestPassDepthPass) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestPassDepthPass) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); if ( p_blnFront == false ) { OGL_RUN(glActiveStencilFaceEXT(GL_BACK)); OGL_RUN(glStencilOp(OpenGLS::m_enmStencilOps[p_enmTestFail - 1], // Specifies the action to take when the stencil test fails OpenGLS::m_enmStencilOps[p_enmTestPassDepthFail - 1], // Specifies the stencil action when the stencil test passes, but the depth test fails OpenGLS::m_enmStencilOps[p_enmTestPassDepthPass - 1])); // Specifies the stencil action when both the stencil test and the depth test pass, or when the stencil test passes and either there is no depth buffer or depth testing is not enabled OGL_RUN(glActiveStencilFaceEXT(GL_FRONT)); } else { OGL_RUN(glStencilOp(OpenGLS::m_enmStencilOps[p_enmTestFail - 1], OpenGLS::m_enmStencilOps[p_enmTestPassDepthFail - 1], OpenGLS::m_enmStencilOps[p_enmTestPassDepthPass - 1])); } } void OpenGLS:: SetStencilParams(const unsigned int p_uintWriteMask, const ASW::GraphicsApi::Test p_enmTest, const ASW::GraphicsApi::StencilOp p_enmTestFail, const ASW::GraphicsApi::StencilOp p_enmTestPassDepthFail, const ASW::GraphicsApi::StencilOp p_enmTestPassDepthPass, const int p_intReference, const unsigned int p_uintMask, const bool p_blnFront) { ASW_ASSERT((int)(p_enmTest) > (int)(ASW::GraphicsApi::TEST_UNKNOWN) && (int)(p_enmTest) <= (int)(ASW::GraphicsApi::TEST_COUNT), "Invalid parameter"); ASW_ASSERT((int)(p_enmTestFail) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestFail) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); ASW_ASSERT((int)(p_enmTestPassDepthFail) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestPassDepthFail) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); ASW_ASSERT((int)(p_enmTestPassDepthPass) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestPassDepthPass) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); if ( p_blnFront == false ) { OGL_RUN(glActiveStencilFaceEXT(GL_BACK)); OGL_RUN(glStencilMask((GLuint)(p_uintWriteMask))); OGL_RUN(glStencilOp(OpenGLS::m_enmStencilOps[p_enmTestFail - 1], OpenGLS::m_enmStencilOps[p_enmTestPassDepthFail - 1], OpenGLS::m_enmStencilOps[p_enmTestPassDepthPass - 1])); OGL_RUN(glStencilFunc(OpenGLS::m_enmTests[p_enmTest - 1], (GLint)(p_intReference), (GLuint)(p_uintMask))); OGL_RUN(glActiveStencilFaceEXT(GL_FRONT)); } else { OGL_RUN(glStencilMask((GLuint)(p_uintWriteMask))); OGL_RUN(glStencilOp(OpenGLS::m_enmStencilOps[p_enmTestFail - 1], OpenGLS::m_enmStencilOps[p_enmTestPassDepthFail - 1], OpenGLS::m_enmStencilOps[p_enmTestPassDepthPass - 1])); OGL_RUN(glStencilFunc(OpenGLS::m_enmTests[p_enmTest - 1], (GLint)(p_intReference), (GLuint)(p_uintMask))); } } void OpenGLS:: SetViewport(const ASW::Point4i & p_stuDimensions, const ASW::Point2f & p_stuDepthRange) { OGL_RUN(glViewport((GLint)(p_stuDimensions[0]), (GLint)(p_stuDimensions[1]), (GLsizei)(p_stuDimensions[2]), (GLsizei)(p_stuDimensions[3]))); OGL_RUN(glDepthRange(p_stuDepthRange[0], p_stuDepthRange[1])); } void OpenGLS:: Unload(ASW::Texture & p_clsTexture) { ASW_ASSERT(p_clsTexture.m_blnLoaded, "Texture is not loaded"); glDeleteTextures(1, (unsigned int *)(&(p_clsTexture.m_ptrObject))); p_clsTexture.m_ptrObject = NULL; p_clsTexture.m_blnLoaded = false; } void OpenGLS:: Unload(ASW::Buffer & p_clsBuffer, const bool p_blnRetainData) { ASW_ASSERT(&(p_clsBuffer.m_clsApi) == this, "Buffer is not loaded to this API object"); if ( p_blnRetainData == false ) { UTIL_SAFE_FREE(p_clsBuffer.m_ptrData); } if ( p_clsBuffer.m_blnIsIndexBuffer && m_ptrActiveBufferIndex == (ASW::BufferIndex *)(&p_clsBuffer) ) Bind((ASW::BufferIndex *)(NULL)); else if ( p_clsBuffer.m_blnIsIndexBuffer == false && m_ptrActiveBufferVertex == (ASW::BufferVertex *)(&p_clsBuffer) ) Bind((ASW::BufferVertex *)(NULL)); } /////////////////////////////////////////////////////////////////// // OpenGLX /////////////////////////////////////////////////////////////////// const GLenum OpenGLX::m_enmVbAccessHint[ASW::Type::ACCESS_COUNT] = { GL_READ_ONLY_ARB, GL_WRITE_ONLY_ARB, GL_WRITE_ONLY_ARB, GL_READ_WRITE_ARB, }; const GLenum OpenGLX::m_enmVbWriteHint[ASW::Type::WRITE_COUNT] = { GL_STREAM_DRAW_ARB, GL_STATIC_DRAW_ARB, GL_DYNAMIC_DRAW_ARB, }; void OpenGLX:: Bind(const ASW::BufferIndex * p_ptrBuffer) { ASW_ASSERT(p_ptrBuffer == NULL || &(p_ptrBuffer->m_clsApi) == this, "Buffer is not loaded to this API object"); if ( m_ptrActiveBufferIndex != p_ptrBuffer ) { m_ptrActiveBufferIndex = p_ptrBuffer; if ( p_ptrBuffer != NULL ) OGL_RUN(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, (unsigned int)(p_ptrBuffer->m_ptrApiObject))); else OGL_RUN(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); } } void OpenGLX:: Bind(const ASW::BufferVertex * p_ptrBuffer) { ASW_ASSERT(p_ptrBuffer == NULL || &(p_ptrBuffer->m_clsApi) == this, "Buffer is not loaded to this API object"); if ( p_ptrBuffer ) OGL_RUN(glBindBufferARB(GL_ARRAY_BUFFER_ARB, (unsigned int)(p_ptrBuffer->m_ptrApiObject))); else OGL_RUN(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); OpenGLS::Bind(p_ptrBuffer); } void OpenGLX:: Load(ASW::Buffer & p_clsBuffer) { GLenum enmTarget; const ASW::Buffer * ptrActiveBuffer; if ( p_clsBuffer.m_blnIsIndexBuffer ) { enmTarget = GL_ELEMENT_ARRAY_BUFFER_ARB; ptrActiveBuffer = (const ASW::Buffer *)(m_ptrActiveBufferIndex); } else { enmTarget = GL_ARRAY_BUFFER_ARB; ptrActiveBuffer = (const ASW::Buffer *)(m_ptrActiveBufferVertex); } OGL_RUN(glGenBuffersARB(1, (unsigned int *)(&(p_clsBuffer.m_ptrApiObject)))); OGL_RUN(glBindBufferARB(enmTarget, (unsigned int)(p_clsBuffer.m_ptrApiObject))); OGL_RUN(glBufferDataARB(enmTarget, p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize, p_clsBuffer.m_ptrData, OpenGLX::m_enmVbWriteHint[p_clsBuffer.m_enmWriteHint - 1])); if ( ptrActiveBuffer ) OGL_RUN(glBindBufferARB(enmTarget, (unsigned int)(ptrActiveBuffer->m_ptrApiObject))); free(p_clsBuffer.m_ptrData); p_clsBuffer.m_ptrData = NULL; } void * OpenGLX:: Lock(ASW::Buffer & p_clsBuffer, const unsigned int p_uintOffset, const unsigned int p_uintSize, const ASW::Type::HintAccess p_enmHint) { ASW_ASSERT(&(p_clsBuffer.m_clsApi) == this, "Buffer is not loaded to this API object"); ASW_ASSERT((int)(p_enmHint) > (int)(ASW::Type::ACCESS_UNKNOWN) && (int)(p_enmHint) <= (int)(ASW::Type::ACCESS_COUNT), "Invalid parameter"); GLenum enmTarget; const ASW::Buffer ** ptrBuffer; if ( p_clsBuffer.m_blnIsIndexBuffer ) { enmTarget = GL_ELEMENT_ARRAY_BUFFER_ARB; ptrBuffer = (const ASW::Buffer **)(&m_ptrActiveBufferIndex); } else { enmTarget = GL_ARRAY_BUFFER_ARB; ptrBuffer = (const ASW::Buffer **)(&m_ptrActiveBufferVertex); } if ( *ptrBuffer != &p_clsBuffer ) { OGL_RUN(glBindBufferARB(enmTarget, (unsigned int)(p_clsBuffer.m_ptrApiObject))); *ptrBuffer = NULL; } if ( p_enmHint == ASW::Type::ACCESS_WRITE_ALL ) { OGL_RUN(glBufferDataARB(enmTarget, p_uintSize, NULL, OpenGLX::m_enmVbWriteHint[p_clsBuffer.m_enmWriteHint - 1])); } ASW_ASSERT((int)(p_enmHint) > (int)(ASW::Type::ACCESS_UNKNOWN) && (int)(p_enmHint) <= (int)(ASW::Type::ACCESS_COUNT), "OpenGLX::Lock"); void * ptrReturn = glMapBufferARB(enmTarget, OpenGLX::m_enmVbAccessHint[p_enmHint - 1]); return ( ptrReturn != NULL ) ? ((char *)(ptrReturn)) + p_uintOffset : NULL; } void OpenGLX:: Set(ASW::Buffer & p_clsBuffer, const void * p_ptrData, const unsigned int p_uintOffset, const unsigned int p_uintSize) { ASW_ASSERT(&(p_clsBuffer.m_clsApi) == this, "Buffer is not loaded to this API object"); ASW_ASSERT((p_uintOffset + p_uintSize) <= (p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize), "Size/offset exceeds buffer size"); GLenum enmTarget; const ASW::Buffer ** ptrBuffer; if ( p_clsBuffer.m_blnIsIndexBuffer ) { ptrBuffer = (const ASW::Buffer **)(&m_ptrActiveBufferIndex); enmTarget = GL_ELEMENT_ARRAY_BUFFER_ARB; } else if ( p_clsBuffer.m_blnIsIndexBuffer == false && m_ptrActiveBufferVertex != &p_clsBuffer ) { ptrBuffer = (const ASW::Buffer **)(&m_ptrActiveBufferVertex); enmTarget = GL_ARRAY_BUFFER_ARB; } if ( &p_clsBuffer != *ptrBuffer ) { OGL_RUN(glBindBufferARB(enmTarget, (unsigned int)(p_clsBuffer.m_ptrApiObject))); *ptrBuffer = NULL; } if ( p_uintOffset == 0 && p_uintSize == (p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize) ) { OGL_RUN(glBufferDataARB(enmTarget, p_uintSize, p_ptrData, OpenGLX::m_enmVbWriteHint[p_clsBuffer.m_enmWriteHint - 1])); } else { OGL_RUN(glBufferSubDataARB(enmTarget, p_uintOffset, p_uintSize, p_ptrData)); } } void OpenGLX:: Unload(ASW::Buffer & p_clsBuffer, const bool p_blnRetainData) { ASW_ASSERT(&(p_clsBuffer.m_clsApi) == this, "Buffer is not loaded to this API object"); ASW_ASSERT(p_clsBuffer.m_ptrData == NULL, "Buffer data should be NULL"); GLenum enmTarget; const ASW::Buffer ** ptrBuffer; if ( p_clsBuffer.m_blnIsIndexBuffer ) { ptrBuffer = (const ASW::Buffer **)(&m_ptrActiveBufferIndex); enmTarget = GL_ELEMENT_ARRAY_BUFFER_ARB; } else { ptrBuffer = (const ASW::Buffer **)(&m_ptrActiveBufferVertex); enmTarget = GL_ARRAY_BUFFER_ARB; } if ( p_blnRetainData ) { if ( *ptrBuffer != &p_clsBuffer ) OGL_RUN(glBindBufferARB(enmTarget, (unsigned int)(p_clsBuffer.m_ptrApiObject))); p_clsBuffer.m_ptrData = malloc(p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize); OGL_RUN(glGetBufferSubDataARB(enmTarget, 0, p_clsBuffer.m_uintElements * p_clsBuffer.m_uchrElementSize, p_clsBuffer.m_ptrData)); if ( *ptrBuffer == &p_clsBuffer ) { OGL_RUN(glBindBufferARB(enmTarget, 0)); *ptrBuffer = NULL; } else if ( *ptrBuffer != NULL ) OGL_RUN(glBindBufferARB(enmTarget, (unsigned int)((*ptrBuffer)->m_ptrApiObject))); } else if ( *ptrBuffer == &p_clsBuffer ) { OGL_RUN(glBindBufferARB(enmTarget, 0)); *ptrBuffer = NULL; } OGL_RUN(glDeleteBuffersARB(1, (unsigned int *)(&(p_clsBuffer.m_ptrApiObject)))); p_clsBuffer.m_ptrApiObject = NULL; } void OpenGLX:: Unlock(ASW::Buffer & p_clsBuffer) { ASW_ASSERT(&(p_clsBuffer.m_clsApi) == this, "Buffer is not loaded to this API object"); GLenum enmTarget; const ASW::Buffer ** ptrBuffer; if ( p_clsBuffer.m_blnIsIndexBuffer ) { ptrBuffer = (const ASW::Buffer **)(&m_ptrActiveBufferIndex); enmTarget = GL_ELEMENT_ARRAY_BUFFER_ARB; } else { ptrBuffer = (const ASW::Buffer **)(&m_ptrActiveBufferVertex); enmTarget = GL_ARRAY_BUFFER_ARB; } if ( &p_clsBuffer != *ptrBuffer ) { OGL_RUN(glBindBufferARB(enmTarget, (unsigned int)(p_clsBuffer.m_ptrApiObject))); *ptrBuffer = NULL; } GLboolean blnResult = glUnmapBufferARB(enmTarget); ASW_ASSERT(blnResult == GL_TRUE, "glUnmapBufferARB did not return GL_TRUE"); }