/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ /* * Copyright (C) 2006-2010 - Frictional Games * * This file is part of HPL1 Engine. */ #include "hpl1/engine/impl/LowLevelGraphicsSDL.h" #include "hpl1/engine/graphics/font_data.h" #include "hpl1/engine/graphics/bitmap2D.h" #include "hpl1/engine/graphics/font_data.h" #include "hpl1/engine/impl/CGProgram.h" #include "hpl1/engine/impl/SDLTexture.h" #include "hpl1/engine/impl/VertexBufferOGL.h" #include "hpl1/engine/impl/VertexBufferVBO.h" #include "hpl1/engine/system/low_level_system.h" #include "common/algorithm.h" #include "common/config-manager.h" #include "common/system.h" #include "engines/util.h" #include "hpl1/debug.h" #include "hpl1/engine/impl/OcclusionQueryOGL.h" #include "hpl1/graphics.h" #ifdef HPL1_USE_OPENGL namespace hpl { GLenum ColorFormatToGL(eColorDataFormat format) { switch (format) { case eColorDataFormat_RGB: return GL_RGB; case eColorDataFormat_RGBA: return GL_RGBA; case eColorDataFormat_ALPHA: return GL_ALPHA; case eColorDataFormat_BGR: return GL_BGR; case eColorDataFormat_BGRA: return GL_BGRA; default: break; } Hpl1::logError(Hpl1::kDebugOpenGL, "invalid color format (%d)\n", format); return GL_RGB; } GLenum TextureTargetToGL(eTextureTarget target) { switch (target) { case eTextureTarget_1D: return GL_TEXTURE_1D; case eTextureTarget_2D: return GL_TEXTURE_2D; case eTextureTarget_Rect: return GL_TEXTURE_RECTANGLE; case eTextureTarget_CubeMap: return GL_TEXTURE_CUBE_MAP; case eTextureTarget_3D: return GL_TEXTURE_3D; default: break; } Hpl1::logError(Hpl1::kDebugOpenGL, "invalid texture target (%d)\n", target); return GL_TEXTURE_1D; } cLowLevelGraphicsSDL::cLowLevelGraphicsSDL() { mlBatchArraySize = 20000; mlVertexCount = 0; mlIndexCount = 0; mlMultisampling = 0; mvVirtualSize.x = 800; mvVirtualSize.y = 600; mfGammaCorrection = 1.0; mpRenderTarget = nullptr; mpPixelFormat = Graphics::PixelFormat::createFormatRGBA32(); Common::fill(mpCurrentTexture, mpCurrentTexture + MAX_TEXTUREUNITS, nullptr); mbClearColor = true; mbClearDepth = true; mbClearStencil = false; // Create the batch arrays: mlBatchStride = 13; // 3 Pos floats, 4 color floats, 3 Tex coord floats . mpVertexArray = (float *)hplMalloc(sizeof(float) * mlBatchStride * mlBatchArraySize); mpIndexArray = (unsigned int *)hplMalloc(sizeof(unsigned int) * mlBatchArraySize); // Index is one int. for (int i = 0; i < MAX_TEXTUREUNITS; i++) { mpTexCoordArray[i] = (float *)hplMalloc(sizeof(float) * 3 * mlBatchArraySize); mbTexCoordArrayActive[i] = false; mlTexCoordArrayCount[i] = 0; } } cLowLevelGraphicsSDL::~cLowLevelGraphicsSDL() { // SDL_SetGammaRamp(mvStartGammaArray[0],mvStartGammaArray[1],mvStartGammaArray[2]); hplFree(mpVertexArray); hplFree(mpIndexArray); for (int i = 0; i < MAX_TEXTUREUNITS; i++) hplFree(mpTexCoordArray[i]); hplDelete(_gammaCorrectionProgram); hplDelete(_screenBuffer); } bool cLowLevelGraphicsSDL::Init(int alWidth, int alHeight, int alBpp, int abFullscreen, int alMultisampling, const tString &asWindowCaption) { if (abFullscreen) { int viewportSize[4]; GL_CHECK(glGetIntegerv(GL_VIEWPORT, viewportSize)); mvScreenSize.x = viewportSize[2]; mvScreenSize.y = viewportSize[3]; } else { mvScreenSize.x = alWidth; mvScreenSize.y = alHeight; } mlBpp = alBpp; mlMultisampling = alMultisampling; initGraphics3d(mvScreenSize.x, mvScreenSize.y); SetupGL(); ShowCursor(false); // CheckMultisampleCaps(); g_system->updateScreen(); _gammaCorrectionProgram = CreateGpuProgram("hpl1_gamma_correction", "hpl1_gamma_correction"); _screenBuffer = CreateTexture(cVector2l( (int)mvScreenSize.x, (int)mvScreenSize.y), 32, cColor(0, 0, 0, 0), false, eTextureType_Normal, eTextureTarget_Rect); return true; } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::CheckMultisampleCaps() { } //----------------------------------------------------------------------- static void logOGLInfo(const cLowLevelGraphicsSDL &graphics) { Hpl1::logInfo(Hpl1::kDebugOpenGL, "Max texture image units: %d\n", graphics.GetCaps(eGraphicCaps_MaxTextureImageUnits)); Hpl1::logInfo(Hpl1::kDebugOpenGL, "Max texture coord units: %d\n", graphics.GetCaps(eGraphicCaps_MaxTextureCoordUnits)); Hpl1::logInfo(Hpl1::kDebugOpenGL, "Two sided stencil: %d\n", graphics.GetCaps(eGraphicCaps_TwoSideStencil)); Hpl1::logInfo(Hpl1::kDebugOpenGL, "Vertex Buffer Object: %d\n", graphics.GetCaps(eGraphicCaps_VertexBufferObject)); Hpl1::logInfo(Hpl1::kDebugOpenGL, "Anisotropic filtering: %d\n", graphics.GetCaps(eGraphicCaps_AnisotropicFiltering)); Hpl1::logInfo(Hpl1::kDebugOpenGL, "Max Anisotropic degree: %d\n", graphics.GetCaps(eGraphicCaps_MaxAnisotropicFiltering)); Hpl1::logInfo(Hpl1::kDebugOpenGL, "Multisampling: %d\n", graphics.GetCaps(eGraphicCaps_Multisampling)); } void cLowLevelGraphicsSDL::SetupGL() { GL_CHECK(glViewport(0, 0, mvScreenSize.x, mvScreenSize.y)); // Inits GL stuff // Set Shade model and clear color. GL_CHECK(glShadeModel(GL_SMOOTH)); GL_CHECK(glClearColor(0.0f, 0.0f, 0.0f, 0.0f)); // Depth Test setup GL_CHECK(glClearDepth(1.0f)); // VAlues buffer is cleared with GL_CHECK(glEnable(GL_DEPTH_TEST)); // enable depth testing GL_CHECK(glDepthFunc(GL_LEQUAL)); // function to do depth test with GL_CHECK(glDisable(GL_ALPHA_TEST)); // Set best perspective correction GL_CHECK(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)); // Stencil setup GL_CHECK(glClearStencil(0)); // Clear the screen GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)); GL_CHECK(glMatrixMode(GL_MODELVIEW)); GL_CHECK(glLoadIdentity()); GL_CHECK(glMatrixMode(GL_PROJECTION)); GL_CHECK(glLoadIdentity()); ///// BEGIN BATCH ARRAY STUFF /////////////// // Enable all the vertex arrays that are used: GL_CHECK(glEnableClientState(GL_VERTEX_ARRAY)); // The positions GL_CHECK(glEnableClientState(GL_COLOR_ARRAY)); // The color GL_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); // Tex coords GL_CHECK(glDisableClientState(GL_NORMAL_ARRAY)); // Disable the once not used. GL_CHECK(glDisableClientState(GL_INDEX_ARRAY)); // color index GL_CHECK(glDisableClientState(GL_EDGE_FLAG_ARRAY)); ///// END BATCH ARRAY STUFF /////////////// logOGLInfo(*this); } //----------------------------------------------------------------------- int cLowLevelGraphicsSDL::GetCaps(eGraphicCaps type) const { switch (type) { // Texture Rectangle case eGraphicCaps_TextureTargetRectangle: return 1; // Vertex Buffer Object case eGraphicCaps_VertexBufferObject: return 1; // gl 2.0 // Two Sided Stencil case eGraphicCaps_TwoSideStencil: return 1; // gl 2.0 // Max Texture Image Units case eGraphicCaps_MaxTextureImageUnits: { int lUnits; GL_CHECK(glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (GLint *)&lUnits)); return lUnits; } // Max Texture Coord Units case eGraphicCaps_MaxTextureCoordUnits: { int lUnits = 0; GL_CHECK(glGetIntegerv(GL_MAX_TEXTURE_COORDS, (GLint *)&lUnits)); return lUnits; } // Texture Anisotropy case eGraphicCaps_AnisotropicFiltering: return 0; // gl 4.6 // Texture Anisotropy case eGraphicCaps_MaxAnisotropicFiltering: return 0; // gl 4.6 // Multisampling case eGraphicCaps_Multisampling: return 1; // gl 1.3 // GL shaders case eGraphicCaps_GL_GpuPrograms: return Hpl1::areShadersAvailable(); // gl 2.0 case eGraphicCaps_GL_BlendFunctionSeparate: return 1; // gl 1.4 case eGraphicCaps_GL_MultiTexture: return 1; // gl 1.2.1 default: break; } Hpl1::logWarning(Hpl1::kDebugGraphics, "graphic options %d is not supported\n", type); return 0; } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::ShowCursor(bool toggle) { g_system->showMouse(toggle); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetMultisamplingActive(bool toggle) { if (!GetCaps(eGraphicCaps_Multisampling) || mlMultisampling <= 0) return; if (toggle) glEnable(GL_MULTISAMPLE); else glDisable(GL_MULTISAMPLE); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetGammaCorrection(float afX) { mfGammaCorrection = afX; } float cLowLevelGraphicsSDL::GetGammaCorrection() { return mfGammaCorrection; } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetClipPlane(int alIdx, const cPlanef &aPlane) { mvClipPlanes[alIdx] = aPlane; double vPlane[4]; vPlane[0] = aPlane.a; vPlane[1] = aPlane.b; vPlane[2] = aPlane.c; vPlane[3] = aPlane.d; GL_CHECK(glClipPlane(GL_CLIP_PLANE0 + alIdx, vPlane)); } cPlanef cLowLevelGraphicsSDL::GetClipPlane(int alIdx, const cPlanef &aPlane) { return mvClipPlanes[alIdx]; } void cLowLevelGraphicsSDL::SetClipPlaneActive(int alIdx, bool toggle) { if (toggle) glEnable(GL_CLIP_PLANE0 + alIdx); else glDisable(GL_CLIP_PLANE0 + alIdx); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SaveScreenToBMP(const tString &asFile) { GL_CHECK(glFinish()); g_system->saveScreenshot(); } //----------------------------------------------------------------------- Bitmap2D *cLowLevelGraphicsSDL::CreateBitmap2D(const cVector2l &size) { return hplNew(Bitmap2D, (size, mpPixelFormat)); } //----------------------------------------------------------------------- FontData *cLowLevelGraphicsSDL::CreateFontData(const tString &asName) { return hplNew(FontData, (asName, this)); } //----------------------------------------------------------------------- iGpuProgram *cLowLevelGraphicsSDL::CreateGpuProgram(const tString &vertex, const tString &fragment) { return hplNew(cCGProgram, (vertex, fragment)); } //----------------------------------------------------------------------- Graphics::PixelFormat *cLowLevelGraphicsSDL::GetPixelFormat() { return &mpPixelFormat; } //----------------------------------------------------------------------- iTexture *cLowLevelGraphicsSDL::CreateTexture(bool abUseMipMaps, eTextureType aType, eTextureTarget aTarget) { return hplNew(cSDLTexture, ("", &mpPixelFormat, this, aType, abUseMipMaps, aTarget)); } //----------------------------------------------------------------------- iTexture *cLowLevelGraphicsSDL::CreateTexture(const tString &asName, bool abUseMipMaps, eTextureType aType, eTextureTarget aTarget) { return hplNew(cSDLTexture, (asName, &mpPixelFormat, this, aType, abUseMipMaps, aTarget)); } //----------------------------------------------------------------------- iTexture *cLowLevelGraphicsSDL::CreateTexture(Bitmap2D *apBmp, bool abUseMipMaps, eTextureType aType, eTextureTarget aTarget) { cSDLTexture *pTex = hplNew(cSDLTexture, ("", &mpPixelFormat, this, aType, abUseMipMaps, aTarget)); pTex->CreateFromBitmap(apBmp); return pTex; } //----------------------------------------------------------------------- iTexture *cLowLevelGraphicsSDL::CreateTexture(const cVector2l &avSize, int alBpp, cColor aFillCol, bool abUseMipMaps, eTextureType aType, eTextureTarget aTarget) { cSDLTexture *pTex = NULL; if (aType == eTextureType_RenderTarget) { pTex = hplNew(cSDLTexture, ("", &mpPixelFormat, this, aType, abUseMipMaps, aTarget)); pTex->Create(avSize.x, avSize.y, aFillCol); } else { Bitmap2D *pBmp = CreateBitmap2D(avSize); pBmp->fillRect(cRect2l(0, 0, 0, 0), aFillCol); pTex = hplNew(cSDLTexture, ("", &mpPixelFormat, this, aType, abUseMipMaps, aTarget)); bool bRet = pTex->CreateFromBitmap(pBmp); hplDelete(pBmp); if (bRet == false) { hplDelete(pTex); return NULL; } } return pTex; } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::PushMatrix(eMatrix aMtxType) { SetMatrixMode(aMtxType); GL_CHECK(glPushMatrix()); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::PopMatrix(eMatrix aMtxType) { SetMatrixMode(aMtxType); GL_CHECK(glPopMatrix()); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetMatrix(eMatrix aMtxType, const cMatrixf &a_mtxA) { SetMatrixMode(aMtxType); cMatrixf mtxTranpose = a_mtxA.GetTranspose(); GL_CHECK(glLoadMatrixf(mtxTranpose.v)); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetIdentityMatrix(eMatrix aMtxType) { SetMatrixMode(aMtxType); GL_CHECK(glLoadIdentity()); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::TranslateMatrix(eMatrix aMtxType, const cVector3f &avPos) { SetMatrixMode(aMtxType); GL_CHECK(glTranslatef(avPos.x, avPos.y, avPos.z)); } //----------------------------------------------------------------------- /** * \todo fix so that there are X, Y , Z versions of this one. * \param aMtxType * \param &avRot */ void cLowLevelGraphicsSDL::RotateMatrix(eMatrix aMtxType, const cVector3f &avRot) { SetMatrixMode(aMtxType); GL_CHECK(glRotatef(1, avRot.x, avRot.y, avRot.z)); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::ScaleMatrix(eMatrix aMtxType, const cVector3f &avScale) { SetMatrixMode(aMtxType); GL_CHECK(glScalef(avScale.x, avScale.y, avScale.z)); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetOrthoProjection(const cVector2f &avSize, float afMin, float afMax) { GL_CHECK(glMatrixMode(GL_PROJECTION)); GL_CHECK(glLoadIdentity()); GL_CHECK(glOrtho(0, avSize.x, avSize.y, 0, afMin, afMax)); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetTexture(unsigned int alUnit, iTexture *apTex) { if (apTex == mpCurrentTexture[alUnit]) return; GLenum NewTarget = 0; if (apTex) NewTarget = GetGLTextureTargetEnum(apTex->GetTarget()); GLenum LastTarget = 0; if (mpCurrentTexture[alUnit]) LastTarget = GetGLTextureTargetEnum(mpCurrentTexture[alUnit]->GetTarget()); // Check if multi texturing is supported. if (GetCaps(eGraphicCaps_GL_MultiTexture)) { GL_CHECK(glActiveTexture(GL_TEXTURE0 + alUnit)); } // If the current texture in this unit is a render target, unbind it. if (mpCurrentTexture[alUnit] && mpCurrentTexture[alUnit]->GetTextureType() == eTextureType_RenderTarget) error("render target not supported"); // Disable this unit if NULL if (apTex == NULL) { GL_CHECK(glDisable(LastTarget)); // glBindTexture(LastTarget,0); // Enable the unit, set the texture handle and bind the pbuffer } else { if (NewTarget != LastTarget && LastTarget != 0) GL_CHECK(glDisable(LastTarget)); cSDLTexture *pSDLTex = static_cast(apTex); GL_CHECK(glBindTexture(NewTarget, pSDLTex->GetTextureHandle())); GL_CHECK(glEnable(NewTarget)); // if it is a render target we need to do some more binding. if (pSDLTex->GetTextureType() == eTextureType_RenderTarget) { error("render target not supported"); } } mpCurrentTexture[alUnit] = apTex; } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetActiveTextureUnit(unsigned int alUnit) { GL_CHECK(glActiveTexture(GL_TEXTURE0 + alUnit)); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetTextureEnv(eTextureParam aParam, int alVal) { GLenum lParam = GetGLTextureParamEnum(aParam); GL_CHECK(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE)); if (aParam == eTextureParam_ColorFunc || aParam == eTextureParam_AlphaFunc) { glTexEnvi(GL_TEXTURE_ENV, lParam, GetGLTextureFuncEnum((eTextureFunc)alVal)); } else if (aParam >= eTextureParam_ColorSource0 && aParam <= eTextureParam_AlphaSource2) { glTexEnvi(GL_TEXTURE_ENV, lParam, GetGLTextureSourceEnum((eTextureSource)alVal)); } else if (aParam >= eTextureParam_ColorOp0 && aParam <= eTextureParam_AlphaOp2) { glTexEnvi(GL_TEXTURE_ENV, lParam, GetGLTextureOpEnum((eTextureOp)alVal)); } else { glTexEnvi(GL_TEXTURE_ENV, lParam, alVal); } GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetTextureConstantColor(const cColor &color) { float vColor[] = {color.r, color.g, color.b, color.a}; GL_CHECK(glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &vColor[0])); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetColor(const cColor &aColor) { GL_CHECK(glColor4f(aColor.r, aColor.g, aColor.b, aColor.a)); } //----------------------------------------------------------------------- iVertexBuffer *cLowLevelGraphicsSDL::CreateVertexBuffer(tVertexFlag aFlags, eVertexBufferDrawType aDrawType, eVertexBufferUsageType aUsageType, int alReserveVtxSize, int alReserveIdxSize) { if (GetCaps(eGraphicCaps_VertexBufferObject)) return hplNew(cVertexBufferVBO, (this, aFlags, aDrawType, aUsageType, alReserveVtxSize, alReserveIdxSize)); return hplNew(cVertexBufferOGL, (this, aFlags, aDrawType, aUsageType, alReserveVtxSize, alReserveIdxSize)); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::DrawRect(const cVector2f &avPos, const cVector2f &avSize, float afZ) { glColor4f(1, 1, 1, 1); glBegin(GL_QUADS); { glTexCoord2f(0.0, 0.0); glVertex3f(avPos.x, avPos.y, afZ); glTexCoord2f(1.0, 0.0); glVertex3f(avPos.x + avSize.x, avPos.y, afZ); glTexCoord2f(1.0, 1.0); glVertex3f(avPos.x + avSize.x, avPos.y + avSize.y, afZ); glTexCoord2f(0.0, 1.0); glVertex3f(avPos.x, avPos.y + avSize.y, afZ); } glEnd(); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::FlushRendering() { GL_CHECK(glFlush()); } void cLowLevelGraphicsSDL::applyGammaCorrection() { if (!_gammaCorrectionProgram) return; SetBlendActive(false); // Copy screen to texture CopyContextToTexure(_screenBuffer, 0, cVector2l((int)mvScreenSize.x, (int)mvScreenSize.y)); tVertexVec vVtx; vVtx.push_back(cVertex(cVector3f(-1.0, 1.0, 0), cVector2f(0, mvScreenSize.y), cColor(0))); vVtx.push_back(cVertex(cVector3f(1.0, 1.0, 0), cVector2f(mvScreenSize.x, mvScreenSize.y), cColor(0))); vVtx.push_back(cVertex(cVector3f(1.0, -1.0, 0), cVector2f(mvScreenSize.x, 0), cColor(0))); vVtx.push_back(cVertex(cVector3f(-1.0, -1.0, 0), cVector2f(0, 0), cColor(0))); _gammaCorrectionProgram->Bind(); SetTexture(0, _screenBuffer); _gammaCorrectionProgram->SetFloat("gamma", mfGammaCorrection); DrawQuad(vVtx); _gammaCorrectionProgram->UnBind(); } void cLowLevelGraphicsSDL::SwapBuffers() { applyGammaCorrection(); GL_CHECK(glFlush()); g_system->updateScreen(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::DrawTri(const tVertexVec &avVtx) { assert(avVtx.size() == 3); glBegin(GL_TRIANGLES); { for (int i = 0; i < 3; i++) { glTexCoord3f(avVtx[i].tex.x, avVtx[i].tex.y, avVtx[i].tex.z); glColor4f(avVtx[i].col.r, avVtx[i].col.g, avVtx[i].col.b, avVtx[i].col.a); glVertex3f(avVtx[i].pos.x, avVtx[i].pos.y, avVtx[i].pos.z); } } glEnd(); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::DrawTri(const cVertex *avVtx) { glBegin(GL_TRIANGLES); { for (int i = 0; i < 3; i++) { glTexCoord3f(avVtx[i].tex.x, avVtx[i].tex.y, avVtx[i].tex.z); glColor4f(avVtx[i].col.r, avVtx[i].col.g, avVtx[i].col.b, avVtx[i].col.a); glVertex3f(avVtx[i].pos.x, avVtx[i].pos.y, avVtx[i].pos.z); } } glEnd(); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::DrawQuad(const tVertexVec &avVtx) { assert(avVtx.size() == 4); glBegin(GL_QUADS); { for (int i = 0; i < 4; i++) { glTexCoord3f(avVtx[i].tex.x, avVtx[i].tex.y, avVtx[i].tex.z); glColor4f(avVtx[i].col.r, avVtx[i].col.g, avVtx[i].col.b, avVtx[i].col.a); glVertex3f(avVtx[i].pos.x, avVtx[i].pos.y, avVtx[i].pos.z); } } glEnd(); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::DrawQuadMultiTex(const tVertexVec &avVtx, const tVector3fVec &avExtraUvs) { int lExtraUnits = (int)avExtraUvs.size() / 4; glBegin(GL_QUADS); { for (int i = 0; i < 4; i++) { glMultiTexCoord3fARB(GL_TEXTURE0_ARB, avVtx[i].tex.x, avVtx[i].tex.y, avVtx[i].tex.z); for (int unit = 0; unit < lExtraUnits; ++unit) { glMultiTexCoord3fARB(GL_TEXTURE0_ARB + unit + 1, avExtraUvs[unit * 4 + i].x, avExtraUvs[unit * 4 + i].y, avExtraUvs[unit * 4 + i].z); } glColor4f(avVtx[i].col.r, avVtx[i].col.g, avVtx[i].col.b, avVtx[i].col.a); glVertex3f(avVtx[i].pos.x, avVtx[i].pos.y, avVtx[i].pos.z); } } glEnd(); GL_CHECK_FN(); } //----------------------------------------------------------------------- iOcclusionQuery *cLowLevelGraphicsSDL::CreateOcclusionQuery() { return hplNew(cOcclusionQueryOGL, ()); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::DestroyOcclusionQuery(iOcclusionQuery *apQuery) { if (apQuery) hplDelete(apQuery); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::ClearScreen() { GLbitfield bitmask = 0; if (mbClearColor) bitmask |= GL_COLOR_BUFFER_BIT; if (mbClearDepth) bitmask |= GL_DEPTH_BUFFER_BIT; if (mbClearStencil) bitmask |= GL_STENCIL_BUFFER_BIT; GL_CHECK(glClear(bitmask)); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetClearColor(const cColor &aCol) { GL_CHECK(glClearColor(aCol.r, aCol.g, aCol.b, aCol.a)); } void cLowLevelGraphicsSDL::SetClearDepth(float afDepth) { GL_CHECK(glClearDepth(afDepth)); } void cLowLevelGraphicsSDL::SetClearStencil(int alVal) { GL_CHECK(glClearStencil(alVal)); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetClearColorActive(bool abX) { mbClearColor = abX; } void cLowLevelGraphicsSDL::SetClearDepthActive(bool abX) { mbClearDepth = abX; } void cLowLevelGraphicsSDL::SetClearStencilActive(bool abX) { mbClearStencil = abX; } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetColorWriteActive(bool abR, bool abG, bool abB, bool abA) { glColorMask(abR, abG, abB, abA); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetDepthWriteActive(bool abX) { glDepthMask(abX); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetDepthTestActive(bool abX) { if (abX) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetDepthTestFunc(eDepthTestFunc aFunc) { GL_CHECK(glDepthFunc(GetGLDepthTestFuncEnum(aFunc))); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetAlphaTestActive(bool abX) { if (abX) glEnable(GL_ALPHA_TEST); else glDisable(GL_ALPHA_TEST); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetAlphaTestFunc(eAlphaTestFunc aFunc, float afRef) { GL_CHECK(glAlphaFunc(GetGLAlphaTestFuncEnum(aFunc), afRef)); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetStencilActive(bool abX) { if (abX) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST); GL_CHECK_FN(); } //----------------------------------------------------------------------- /*void cLowLevelGraphicsSDL::SetStencilTwoSideActive(bool abX) { if(GLEE_EXT_stencil_two_side) { glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT); } } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetStencilFace(eStencilFace aFace) { if(GLEE_EXT_stencil_two_side) { if(aFace == eStencilFace_Front) glActiveStencilFaceEXT(GL_FRONT); else glActiveStencilFaceEXT(GL_BACK); } } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetStencilFunc(eStencilFunc aFunc,int alRef, unsigned int aMask) { glStencilFunc(GetGLStencilFuncEnum(aFunc), alRef, aMask); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetStencilOp(eStencilOp aFailOp,eStencilOp aZFailOp,eStencilOp aZPassOp) { glStencilOp(GetGLStencilOpEnum(aFailOp), GetGLStencilOpEnum(aZFailOp), GetGLStencilOpEnum(aZPassOp)); }*/ //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetStencil(eStencilFunc aFunc, int alRef, unsigned int aMask, eStencilOp aFailOp, eStencilOp aZFailOp, eStencilOp aZPassOp) { #if 0 if (GetCaps(eGraphicCaps_TwoSideStencil)) { //glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);//shouldn't be needed.. //glActiveStencilFace(GL_FRONT); } #endif GL_CHECK(glStencilFunc(GetGLStencilFuncEnum(aFunc), alRef, aMask)); GL_CHECK(glStencilOp(GetGLStencilOpEnum(aFailOp), GetGLStencilOpEnum(aZFailOp), GetGLStencilOpEnum(aZPassOp))); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetStencilTwoSide(eStencilFunc aFrontFunc, eStencilFunc aBackFunc, int alRef, unsigned int aMask, eStencilOp aFrontFailOp, eStencilOp aFrontZFailOp, eStencilOp aFrontZPassOp, eStencilOp aBackFailOp, eStencilOp aBackZFailOp, eStencilOp aBackZPassOp) { if (GetCaps(eGraphicCaps_TwoSideStencil)) { GL_CHECK(glStencilFuncSeparate(GL_FRONT, GetGLStencilFuncEnum(aFrontFunc), alRef, aMask)); GL_CHECK(glStencilOpSeparate(GL_FRONT, GetGLStencilOpEnum(aFrontFailOp), GetGLStencilOpEnum(aFrontZFailOp), GetGLStencilOpEnum(aFrontZPassOp))) GL_CHECK(glStencilFuncSeparate(GL_BACK, GetGLStencilFuncEnum(aBackFunc), alRef, aMask)); GL_CHECK(glStencilOpSeparate(GL_BACK, GetGLStencilOpEnum(aBackFailOp), GetGLStencilOpEnum(aBackZFailOp), GetGLStencilOpEnum(aBackZPassOp))); } else error("Only single sided stencil supported"); } void cLowLevelGraphicsSDL::SetStencilTwoSide(bool abX) { if (!GetCaps(eGraphicCaps_TwoSideStencil)) Hpl1::logError(Hpl1::kDebugOpenGL, "call to setStencilTwoSide with two side stencil disabled%c\n", '.'); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetCullActive(bool abX) { if (abX) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); GL_CHECK_FN(); GL_CHECK(glCullFace(GL_BACK)); } void cLowLevelGraphicsSDL::SetCullMode(eCullMode aMode) { GL_CHECK(glCullFace(GL_BACK)); if (aMode == eCullMode_Clockwise) glFrontFace(GL_CCW); else glFrontFace(GL_CW); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetScissorActive(bool toggle) { if (toggle) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetScissorRect(const cRect2l &aRect) { glScissor(aRect.x, (mvScreenSize.y - aRect.y - 1) - aRect.h, aRect.w, aRect.h); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetBlendActive(bool abX) { if (abX) glEnable(GL_BLEND); else glDisable(GL_BLEND); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetBlendFunc(eBlendFunc aSrcFactor, eBlendFunc aDestFactor) { GL_CHECK(glBlendFunc(GetGLBlendEnum(aSrcFactor), GetGLBlendEnum(aDestFactor))); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetBlendFuncSeparate(eBlendFunc aSrcFactorColor, eBlendFunc aDestFactorColor, eBlendFunc aSrcFactorAlpha, eBlendFunc aDestFactorAlpha) { if (GetCaps(eGraphicCaps_GL_BlendFunctionSeparate)) { glBlendFuncSeparate(GetGLBlendEnum(aSrcFactorColor), GetGLBlendEnum(aDestFactorColor), GetGLBlendEnum(aSrcFactorAlpha), GetGLBlendEnum(aDestFactorAlpha)); } else { glBlendFunc(GetGLBlendEnum(aSrcFactorColor), GetGLBlendEnum(aDestFactorColor)); } } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::DrawQuad(const tVertexVec &avVtx, const cColor aCol) { assert(avVtx.size() == 4); glBegin(GL_QUADS); { // Make all this inline?? for (int i = 0; i < 4; i++) { glTexCoord3f(avVtx[i].tex.x, avVtx[i].tex.y, avVtx[i].tex.z); glColor4f(aCol.r, aCol.g, aCol.b, aCol.a); glVertex3f(avVtx[i].pos.x, avVtx[i].pos.y, avVtx[i].pos.z); } } glEnd(); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::DrawQuad(const tVertexVec &avVtx, const float afZ) { assert(avVtx.size() == 4); glBegin(GL_QUADS); { // Make all this inline?? for (int i = 0; i < 4; i++) { glTexCoord3f(avVtx[i].tex.x, avVtx[i].tex.y, afZ); glColor4f(avVtx[i].col.r, avVtx[i].col.g, avVtx[i].col.b, avVtx[i].col.a); glVertex3f(avVtx[i].pos.x, avVtx[i].pos.y, avVtx[i].pos.z); } } GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::DrawQuad(const tVertexVec &avVtx, const float afZ, const cColor &aCol) { assert(avVtx.size() == 4); glBegin(GL_QUADS); { // Make all this inline?? for (int i = 0; i < 4; i++) { glTexCoord3f(avVtx[i].tex.x, avVtx[i].tex.y, afZ); glColor4f(aCol.r, aCol.g, aCol.b, aCol.a); glVertex3f(avVtx[i].pos.x, avVtx[i].pos.y, avVtx[i].pos.z); } } glEnd(); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::AddVertexToBatch(const cVertex &apVtx) { // Coord mpVertexArray[mlVertexCount + 0] = apVtx.pos.x; mpVertexArray[mlVertexCount + 1] = apVtx.pos.y; mpVertexArray[mlVertexCount + 2] = apVtx.pos.z; // Color mpVertexArray[mlVertexCount + 3] = apVtx.col.r; mpVertexArray[mlVertexCount + 4] = apVtx.col.g; mpVertexArray[mlVertexCount + 5] = apVtx.col.b; mpVertexArray[mlVertexCount + 6] = apVtx.col.a; // Texture coord mpVertexArray[mlVertexCount + 7] = apVtx.tex.x; mpVertexArray[mlVertexCount + 8] = apVtx.tex.y; mpVertexArray[mlVertexCount + 9] = apVtx.tex.z; // Normal coord mpVertexArray[mlVertexCount + 10] = apVtx.norm.x; mpVertexArray[mlVertexCount + 11] = apVtx.norm.y; mpVertexArray[mlVertexCount + 12] = apVtx.norm.z; mlVertexCount = mlVertexCount + mlBatchStride; if (mlVertexCount / mlBatchStride >= mlBatchArraySize) { // Make the array larger. } } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::AddVertexToBatch(const cVertex *apVtx, const cVector3f *avTransform) { // Coord mpVertexArray[mlVertexCount + 0] = apVtx->pos.x + avTransform->x; mpVertexArray[mlVertexCount + 1] = apVtx->pos.y + avTransform->y; mpVertexArray[mlVertexCount + 2] = apVtx->pos.z + avTransform->z; /*Log("Trans: %s\n",avTransform->ToString().c_str()); Log("Adding: %f:%f:%f\n",mpVertexArray[mlVertexCount + 0], mpVertexArray[mlVertexCount + 1], mpVertexArray[mlVertexCount + 2]);*/ // Color mpVertexArray[mlVertexCount + 3] = apVtx->col.r; mpVertexArray[mlVertexCount + 4] = apVtx->col.g; mpVertexArray[mlVertexCount + 5] = apVtx->col.b; mpVertexArray[mlVertexCount + 6] = apVtx->col.a; // Texture coord mpVertexArray[mlVertexCount + 7] = apVtx->tex.x; mpVertexArray[mlVertexCount + 8] = apVtx->tex.y; mpVertexArray[mlVertexCount + 9] = apVtx->tex.z; /*Log("Tex: %f:%f:%f\n",mpVertexArray[mlVertexCount + 7], mpVertexArray[mlVertexCount + 8], mpVertexArray[mlVertexCount + 9]);*/ // Normal coord mpVertexArray[mlVertexCount + 10] = apVtx->norm.x; mpVertexArray[mlVertexCount + 11] = apVtx->norm.y; mpVertexArray[mlVertexCount + 12] = apVtx->norm.z; mlVertexCount = mlVertexCount + mlBatchStride; if (mlVertexCount / mlBatchStride >= mlBatchArraySize) { // Make the array larger. } } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::AddVertexToBatch(const cVertex *apVtx, const cMatrixf *aMtx) { } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::AddVertexToBatch_Size2D(const cVertex *apVtx, const cVector3f *avTransform, const cColor *apCol, const float &mfW, const float &mfH) { // Coord mpVertexArray[mlVertexCount + 0] = avTransform->x + mfW; mpVertexArray[mlVertexCount + 1] = avTransform->y + mfH; mpVertexArray[mlVertexCount + 2] = avTransform->z; // Color mpVertexArray[mlVertexCount + 3] = apCol->r; mpVertexArray[mlVertexCount + 4] = apCol->g; mpVertexArray[mlVertexCount + 5] = apCol->b; mpVertexArray[mlVertexCount + 6] = apCol->a; // Texture coord mpVertexArray[mlVertexCount + 7] = apVtx->tex.x; mpVertexArray[mlVertexCount + 8] = apVtx->tex.y; mpVertexArray[mlVertexCount + 9] = apVtx->tex.z; mlVertexCount = mlVertexCount + mlBatchStride; if (mlVertexCount / mlBatchStride >= mlBatchArraySize) { // Make the array larger. } } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::AddVertexToBatch_Raw(const cVector3f &avPos, const cColor &aColor, const cVector3f &avTex) { // Coord mpVertexArray[mlVertexCount + 0] = avPos.x; mpVertexArray[mlVertexCount + 1] = avPos.y; mpVertexArray[mlVertexCount + 2] = avPos.z; // Color mpVertexArray[mlVertexCount + 3] = aColor.r; mpVertexArray[mlVertexCount + 4] = aColor.g; mpVertexArray[mlVertexCount + 5] = aColor.b; mpVertexArray[mlVertexCount + 6] = aColor.a; // Texture coord mpVertexArray[mlVertexCount + 7] = avTex.x; mpVertexArray[mlVertexCount + 8] = avTex.y; mpVertexArray[mlVertexCount + 9] = avTex.z; mlVertexCount = mlVertexCount + mlBatchStride; } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::AddIndexToBatch(int alIndex) { mpIndexArray[mlIndexCount] = alIndex; mlIndexCount++; if (mlIndexCount >= mlBatchArraySize) { // Make the array larger. } } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::AddTexCoordToBatch(unsigned int alUnit, const cVector3f *apCoord) { unsigned int lCount = mlTexCoordArrayCount[alUnit]; mpTexCoordArray[alUnit][lCount + 0] = apCoord->x; mpTexCoordArray[alUnit][lCount + 1] = apCoord->y; mpTexCoordArray[alUnit][lCount + 2] = apCoord->z; mlTexCoordArrayCount[alUnit] += 3; } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetBatchTextureUnitActive(unsigned int alUnit, bool active) { GL_CHECK(glClientActiveTextureARB(GL_TEXTURE0_ARB + alUnit)); if (active) glTexCoordPointer(3, GL_FLOAT, 0, &mpTexCoordArray[alUnit][0]); else glTexCoordPointer(3, GL_FLOAT, sizeof(float) * mlBatchStride, &mpVertexArray[7]); GL_CHECK_FN(); } //----------------------------------------------------------------------- static void flushAutoClear(unsigned &indexCount, unsigned &vertexCount, unsigned *texCoordArray) { indexCount = 0; vertexCount = 0; Common::fill(texCoordArray, texCoordArray + MAX_TEXTUREUNITS, 0); } void cLowLevelGraphicsSDL::FlushTriBatch(tVtxBatchFlag aTypeFlags, bool abAutoClear) { SetVtxBatchStates(aTypeFlags); SetUpBatchArrays(); GL_CHECK(glDrawElements(GL_TRIANGLES, mlIndexCount, GL_UNSIGNED_INT, mpIndexArray)); if (abAutoClear) flushAutoClear(mlIndexCount, mlVertexCount, mlTexCoordArrayCount); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::FlushQuadBatch(tVtxBatchFlag aTypeFlags, bool abAutoClear) { SetVtxBatchStates(aTypeFlags); SetUpBatchArrays(); GL_CHECK(glDrawElements(GL_QUADS, mlIndexCount, GL_UNSIGNED_INT, mpIndexArray)); if (abAutoClear) flushAutoClear(mlIndexCount, mlVertexCount, mlTexCoordArrayCount); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::ClearBatch() { mlIndexCount = 0; mlVertexCount = 0; } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::DrawLine(const cVector3f &avBegin, const cVector3f &avEnd, cColor aCol) { SetTexture(0, nullptr); // SetBlendActive(false); glColor4f(aCol.r, aCol.g, aCol.b, aCol.a); glBegin(GL_LINES); { glVertex3f(avBegin.x, avBegin.y, avBegin.z); glVertex3f(avEnd.x, avEnd.y, avEnd.z); } glEnd(); GL_CHECK_FN(); } void cLowLevelGraphicsSDL::DrawBoxMaxMin(const cVector3f &avMax, const cVector3f &avMin, cColor aCol) { SetTexture(0, NULL); SetBlendActive(false); glColor4f(aCol.r, aCol.g, aCol.b, aCol.a); glBegin(GL_LINES); { // Pos Z Quad glVertex3f(avMax.x, avMax.y, avMax.z); glVertex3f(avMin.x, avMax.y, avMax.z); glVertex3f(avMax.x, avMax.y, avMax.z); glVertex3f(avMax.x, avMin.y, avMax.z); glVertex3f(avMin.x, avMax.y, avMax.z); glVertex3f(avMin.x, avMin.y, avMax.z); glVertex3f(avMin.x, avMin.y, avMax.z); glVertex3f(avMax.x, avMin.y, avMax.z); // Neg Z Quad glVertex3f(avMax.x, avMax.y, avMin.z); glVertex3f(avMin.x, avMax.y, avMin.z); glVertex3f(avMax.x, avMax.y, avMin.z); glVertex3f(avMax.x, avMin.y, avMin.z); glVertex3f(avMin.x, avMax.y, avMin.z); glVertex3f(avMin.x, avMin.y, avMin.z); glVertex3f(avMin.x, avMin.y, avMin.z); glVertex3f(avMax.x, avMin.y, avMin.z); // Lines between glVertex3f(avMax.x, avMax.y, avMax.z); glVertex3f(avMax.x, avMax.y, avMin.z); glVertex3f(avMin.x, avMax.y, avMax.z); glVertex3f(avMin.x, avMax.y, avMin.z); glVertex3f(avMin.x, avMin.y, avMax.z); glVertex3f(avMin.x, avMin.y, avMin.z); glVertex3f(avMax.x, avMin.y, avMax.z); glVertex3f(avMax.x, avMin.y, avMin.z); } glEnd(); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::DrawSphere(const cVector3f &avPos, float afRadius, cColor aCol) { int alSegments = 32; float afAngleStep = k2Pif / (float)alSegments; SetTexture(0, nullptr); SetBlendActive(false); glColor4f(aCol.r, aCol.g, aCol.b, aCol.a); glBegin(GL_LINES); { // X Circle: for (float a = 0; a < k2Pif; a += afAngleStep) { glVertex3f(avPos.x, avPos.y + sin(a) * afRadius, avPos.z + cos(a) * afRadius); glVertex3f(avPos.x, avPos.y + sin(a + afAngleStep) * afRadius, avPos.z + cos(a + afAngleStep) * afRadius); } // Y Circle: for (float a = 0; a < k2Pif; a += afAngleStep) { glVertex3f(avPos.x + cos(a) * afRadius, avPos.y, avPos.z + sin(a) * afRadius); glVertex3f(avPos.x + cos(a + afAngleStep) * afRadius, avPos.y, avPos.z + sin(a + afAngleStep) * afRadius); } // Z Circle: for (float a = 0; a < k2Pif; a += afAngleStep) { glVertex3f(avPos.x + cos(a) * afRadius, avPos.y + sin(a) * afRadius, avPos.z); glVertex3f(avPos.x + cos(a + afAngleStep) * afRadius, avPos.y + sin(a + afAngleStep) * afRadius, avPos.z); } } glEnd(); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::DrawLine2D(const cVector2f &avBegin, const cVector2f &avEnd, float afZ, cColor aCol) { SetTexture(0, NULL); SetBlendActive(false); glColor4f(aCol.r, aCol.g, aCol.b, aCol.a); glBegin(GL_LINES); { glVertex3f(avBegin.x, avBegin.y, afZ); glVertex3f(avEnd.x, avEnd.y, afZ); } glEnd(); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::DrawLineRect2D(const cRect2f &aRect, float afZ, cColor aCol) { SetTexture(0, nullptr); SetBlendActive(false); glColor4f(aCol.r, aCol.g, aCol.b, aCol.a); glBegin(GL_LINE_STRIP); { glVertex3f(aRect.x, aRect.y, afZ); glVertex3f(aRect.x + aRect.w, aRect.y, afZ); glVertex3f(aRect.x + aRect.w, aRect.y + aRect.h, afZ); glVertex3f(aRect.x, aRect.y + aRect.h, afZ); glVertex3f(aRect.x, aRect.y, afZ); } glEnd(); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::DrawFilledRect2D(const cRect2f &aRect, float afZ, cColor aCol) { SetTexture(0, NULL); glColor4f(aCol.r, aCol.g, aCol.b, aCol.a); glBegin(GL_QUADS); { glVertex3f(aRect.x, aRect.y, afZ); glVertex3f(aRect.x + aRect.w, aRect.y, afZ); glVertex3f(aRect.x + aRect.w, aRect.y + aRect.h, afZ); glVertex3f(aRect.x, aRect.y + aRect.h, afZ); } glEnd(); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::DrawLineCircle2D(const cVector2f &avCenter, float afRadius, float afZ, cColor aCol) { // Implement later } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::CopyContextToTexure(iTexture *apTex, const cVector2l &avPos, const cVector2l &avSize, const cVector2l &avTexOffset) { if (apTex == nullptr) return; int lScreenY = (mvScreenSize.y - avSize.y) - avPos.y; int lTexY = (apTex->getHeight() - avSize.y) - avTexOffset.y; // Log("TExoffset: %d %d\n",avTexOffset.x,lTexY); // Log("ScreenOffset: %d %d (h: %d s: %d p: %d)\n",avPos.x,lScreenY,mvScreenSize.y, // avSize.y,avPos.y); g_system->presentBuffer(); SetTexture(0, apTex); GL_CHECK(glCopyTexSubImage2D(GetGLTextureTargetEnum(apTex->GetTarget()), 0, avTexOffset.x, lTexY, avPos.x, lScreenY, avSize.x, avSize.y)); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetRenderTarget(iTexture *pTex) { #if 0 if(pTex == mpRenderTarget)return; mpRenderTarget = pTex; if(pTex==NULL) { #ifdef WIN32 if (!wglMakeCurrent(mDeviceContext, mGLContext)){ Log("Something went wrong..."); } #elif defined(__linux__) /*if (!glXMakeCurrent(dpy, gPBuffer, glCtx)) { Log("Something went wrong..."); }*/ #endif } else { if(pTex->GetTextureType() != eTextureType_RenderTarget)return; cSDLTexture* pSDLTex = static_cast(pTex); cPBuffer* pPBuffer = pSDLTex->GetPBuffer(); //pPBuffer->UnBind();//needed? if (!pPBuffer->MakeCurrentContext()){ Log("PBuffer::Activate() failed.\n"); } } //Old OGL 1.1 Code: /*FlushRenderTarget(); mpRenderTarget = pTex; if(mpRenderTarget==NULL) glViewport(0,0,mvScreenSize.x,mvScreenSize.y); else glViewport(0,0,pTex->GetWidth(),pTex->GetHeight());*/ #endif } //----------------------------------------------------------------------- bool cLowLevelGraphicsSDL::RenderTargetHasZBuffer() { return true; } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::FlushRenderTarget() { // Old OGL 1.1 Code: /*if(mpRenderTarget!=NULL) { SetTexture(0, mpRenderTarget); //Log("w: %d\n",mpRenderTarget->GetWidth()); glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, mpRenderTarget->GetWidth(), mpRenderTarget->GetHeight(), 0); }*/ } //----------------------------------------------------------------------- cVector2f cLowLevelGraphicsSDL::GetScreenSize() { return cVector2f((float)mvScreenSize.x, (float)mvScreenSize.y); } //----------------------------------------------------------------------- cVector2f cLowLevelGraphicsSDL::GetVirtualSize() { return mvVirtualSize; } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetVirtualSize(cVector2f avSize) { mvVirtualSize = avSize; } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // PRIVATE METHODS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetUpBatchArrays() { // Set the arrays glVertexPointer(3, GL_FLOAT, sizeof(float) * mlBatchStride, mpVertexArray); glColorPointer(4, GL_FLOAT, sizeof(float) * mlBatchStride, &mpVertexArray[3]); glNormalPointer(GL_FLOAT, sizeof(float) * mlBatchStride, &mpVertexArray[10]); glClientActiveTextureARB(GL_TEXTURE0_ARB); glTexCoordPointer(3, GL_FLOAT, sizeof(float) * mlBatchStride, &mpVertexArray[7]); glClientActiveTextureARB(GL_TEXTURE1_ARB); glTexCoordPointer(3, GL_FLOAT, sizeof(float) * mlBatchStride, &mpVertexArray[7]); glClientActiveTextureARB(GL_TEXTURE2_ARB); glTexCoordPointer(3, GL_FLOAT, sizeof(float) * mlBatchStride, &mpVertexArray[7]); GL_CHECK_FN(); } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetVtxBatchStates(tVtxBatchFlag flags) { if (flags & eVtxBatchFlag_Position) { GL_CHECK(glEnableClientState(GL_VERTEX_ARRAY)); } else { GL_CHECK(glDisableClientState(GL_VERTEX_ARRAY)); } if (flags & eVtxBatchFlag_Color0) { GL_CHECK(glEnableClientState(GL_COLOR_ARRAY)); } else { GL_CHECK(glDisableClientState(GL_COLOR_ARRAY)); } if (flags & eVtxBatchFlag_Normal) { GL_CHECK(glEnableClientState(GL_NORMAL_ARRAY)); } else { GL_CHECK(glDisableClientState(GL_NORMAL_ARRAY)); } if (flags & eVtxBatchFlag_Texture0) { GL_CHECK(glClientActiveTextureARB(GL_TEXTURE0_ARB)); GL_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); } else { GL_CHECK(glClientActiveTextureARB(GL_TEXTURE0_ARB)); GL_CHECK(glDisableClientState(GL_TEXTURE_COORD_ARRAY)); } if (flags & eVtxBatchFlag_Texture1) { GL_CHECK(glClientActiveTextureARB(GL_TEXTURE1_ARB)); GL_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); } else { GL_CHECK(glClientActiveTextureARB(GL_TEXTURE1_ARB)); GL_CHECK(glDisableClientState(GL_TEXTURE_COORD_ARRAY)); } if (flags & eVtxBatchFlag_Texture2) { GL_CHECK(glClientActiveTextureARB(GL_TEXTURE2_ARB)); GL_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); } else { GL_CHECK(glClientActiveTextureARB(GL_TEXTURE2_ARB)); GL_CHECK(glDisableClientState(GL_TEXTURE_COORD_ARRAY)); } } //----------------------------------------------------------------------- GLenum cLowLevelGraphicsSDL::GetGLBlendEnum(eBlendFunc type) { switch (type) { case eBlendFunc_Zero: return GL_ZERO; case eBlendFunc_One: return GL_ONE; case eBlendFunc_SrcColor: return GL_SRC_COLOR; case eBlendFunc_OneMinusSrcColor: return GL_ONE_MINUS_SRC_COLOR; case eBlendFunc_DestColor: return GL_DST_COLOR; case eBlendFunc_OneMinusDestColor: return GL_ONE_MINUS_DST_COLOR; case eBlendFunc_SrcAlpha: return GL_SRC_ALPHA; case eBlendFunc_OneMinusSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA; case eBlendFunc_DestAlpha: return GL_DST_ALPHA; case eBlendFunc_OneMinusDestAlpha: return GL_ONE_MINUS_DST_ALPHA; case eBlendFunc_SrcAlphaSaturate: return GL_SRC_ALPHA_SATURATE; default: break; } Hpl1::logError(Hpl1::kDebugOpenGL, "invalid blend op (%d)", type); return 0; } //----------------------------------------------------------------------- GLenum cLowLevelGraphicsSDL::GetGLTextureParamEnum(eTextureParam type) { switch (type) { case eTextureParam_ColorFunc: return GL_COMBINE_RGB; case eTextureParam_AlphaFunc: return GL_COMBINE_ALPHA; case eTextureParam_ColorSource0: return GL_SOURCE0_RGB; case eTextureParam_ColorSource1: return GL_SOURCE1_RGB; case eTextureParam_ColorSource2: return GL_SOURCE2_RGB; case eTextureParam_AlphaSource0: return GL_SOURCE0_ALPHA; case eTextureParam_AlphaSource1: return GL_SOURCE1_ALPHA; case eTextureParam_AlphaSource2: return GL_SOURCE2_ALPHA; case eTextureParam_ColorOp0: return GL_OPERAND0_RGB; case eTextureParam_ColorOp1: return GL_OPERAND1_RGB; case eTextureParam_ColorOp2: return GL_OPERAND2_RGB; case eTextureParam_AlphaOp0: return GL_OPERAND0_ALPHA; case eTextureParam_AlphaOp1: return GL_OPERAND1_ALPHA; case eTextureParam_AlphaOp2: return GL_OPERAND2_ALPHA; case eTextureParam_ColorScale: return GL_RGB_SCALE; case eTextureParam_AlphaScale: return GL_ALPHA_SCALE; default: break; } Hpl1::logError(Hpl1::kDebugOpenGL, "invalid texture parameter (%d)", type); return 0; } //----------------------------------------------------------------------- GLenum cLowLevelGraphicsSDL::GetGLTextureOpEnum(eTextureOp type) { switch (type) { case eTextureOp_Color: return GL_SRC_COLOR; case eTextureOp_OneMinusColor: return GL_ONE_MINUS_SRC_COLOR; case eTextureOp_Alpha: return GL_SRC_ALPHA; case eTextureOp_OneMinusAlpha: return GL_ONE_MINUS_SRC_ALPHA; default: break; } Hpl1::logError(Hpl1::kDebugOpenGL, "invalid texture op (%d)", type); return 0; } //----------------------------------------------------------------------- GLenum cLowLevelGraphicsSDL::GetGLTextureSourceEnum(eTextureSource type) { switch (type) { case eTextureSource_Texture: return GL_TEXTURE; case eTextureSource_Constant: return GL_CONSTANT; case eTextureSource_Primary: return GL_PRIMARY_COLOR; case eTextureSource_Previous: return GL_PREVIOUS; default: break; } Hpl1::logError(Hpl1::kDebugOpenGL, "invalid texture source (%d)", type); return 0; } //----------------------------------------------------------------------- GLenum cLowLevelGraphicsSDL::GetGLTextureTargetEnum(eTextureTarget type) { switch (type) { case eTextureTarget_1D: return GL_TEXTURE_1D; case eTextureTarget_2D: return GL_TEXTURE_2D; case eTextureTarget_Rect: return GL_TEXTURE_RECTANGLE; case eTextureTarget_CubeMap: return GL_TEXTURE_CUBE_MAP; case eTextureTarget_3D: return GL_TEXTURE_3D; default: break; } Hpl1::logError(Hpl1::kDebugOpenGL, "invalid texture target (%d)", type); return 0; } //----------------------------------------------------------------------- GLenum cLowLevelGraphicsSDL::GetGLTextureFuncEnum(eTextureFunc type) { switch (type) { case eTextureFunc_Modulate: return GL_MODULATE; case eTextureFunc_Replace: return GL_REPLACE; case eTextureFunc_Add: return GL_ADD; case eTextureFunc_Subtract: return GL_SUBTRACT; case eTextureFunc_AddSigned: return GL_ADD_SIGNED; case eTextureFunc_Interpolate: return GL_INTERPOLATE; case eTextureFunc_Dot3RGB: return GL_DOT3_RGB; case eTextureFunc_Dot3RGBA: return GL_DOT3_RGBA; default: break; } Hpl1::logError(Hpl1::kDebugOpenGL, "invalid texture function (%d)", type); return 0; } //----------------------------------------------------------------------- GLenum cLowLevelGraphicsSDL::GetGLDepthTestFuncEnum(eDepthTestFunc type) { switch (type) { case eDepthTestFunc_Never: return GL_NEVER; case eDepthTestFunc_Less: return GL_LESS; case eDepthTestFunc_LessOrEqual: return GL_LEQUAL; case eDepthTestFunc_Greater: return GL_GREATER; case eDepthTestFunc_GreaterOrEqual: return GL_GEQUAL; case eDepthTestFunc_Equal: return GL_EQUAL; case eDepthTestFunc_NotEqual: return GL_NOTEQUAL; case eDepthTestFunc_Always: return GL_ALWAYS; default: break; } Hpl1::logError(Hpl1::kDebugOpenGL, "invalid depth test function (%d)", type); return 0; } //----------------------------------------------------------------------- GLenum cLowLevelGraphicsSDL::GetGLAlphaTestFuncEnum(eAlphaTestFunc type) { switch (type) { case eAlphaTestFunc_Never: return GL_NEVER; case eAlphaTestFunc_Less: return GL_LESS; case eAlphaTestFunc_LessOrEqual: return GL_LEQUAL; case eAlphaTestFunc_Greater: return GL_GREATER; case eAlphaTestFunc_GreaterOrEqual: return GL_GEQUAL; case eAlphaTestFunc_Equal: return GL_EQUAL; case eAlphaTestFunc_NotEqual: return GL_NOTEQUAL; case eAlphaTestFunc_Always: return GL_ALWAYS; default: break; } Hpl1::logError(Hpl1::kDebugOpenGL, "invalid alpha test function (%d)", type); return 0; } //----------------------------------------------------------------------- GLenum cLowLevelGraphicsSDL::GetGLStencilFuncEnum(eStencilFunc type) { switch (type) { case eStencilFunc_Never: return GL_NEVER; case eStencilFunc_Less: return GL_LESS; case eStencilFunc_LessOrEqual: return GL_LEQUAL; case eStencilFunc_Greater: return GL_GREATER; case eStencilFunc_GreaterOrEqual: return GL_GEQUAL; case eStencilFunc_Equal: return GL_EQUAL; case eStencilFunc_NotEqual: return GL_NOTEQUAL; case eStencilFunc_Always: return GL_ALWAYS; default: break; } Hpl1::logError(Hpl1::kDebugOpenGL, "invalid stencil function (%d)", type); return 0; } //----------------------------------------------------------------------- GLenum cLowLevelGraphicsSDL::GetGLStencilOpEnum(eStencilOp type) { switch (type) { case eStencilOp_Keep: return GL_KEEP; case eStencilOp_Zero: return GL_ZERO; case eStencilOp_Replace: return GL_REPLACE; case eStencilOp_Increment: return GL_INCR; case eStencilOp_Decrement: return GL_DECR; case eStencilOp_Invert: return GL_INVERT; case eStencilOp_IncrementWrap: return GL_INCR_WRAP; case eStencilOp_DecrementWrap: return GL_DECR_WRAP; default: break; } Hpl1::logError(Hpl1::kDebugOpenGL, "invalid stencil op (%d)", type); return 0; } //----------------------------------------------------------------------- void cLowLevelGraphicsSDL::SetMatrixMode(eMatrix type) { switch (type) { case eMatrix_ModelView: GL_CHECK(glMatrixMode(GL_MODELVIEW)); break; case eMatrix_Projection: GL_CHECK(glMatrixMode(GL_PROJECTION)); break; case eMatrix_Texture: GL_CHECK(glMatrixMode(GL_TEXTURE)); break; default: Hpl1::logError(Hpl1::kDebugOpenGL, "invalid matrix mode (%d)", type); } } //----------------------------------------------------------------------- } // namespace hpl #endif // HPL1_USE_OPENGL