/* 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 .
*
*/
#include "hpl1/engine/impl/low_level_graphics_tgl.h"
#include "hpl1/engine/graphics/bitmap2D.h"
#include "hpl1/engine/graphics/font_data.h"
#include "hpl1/engine/impl/occlusion_query_tgl.h"
#include "hpl1/engine/impl/texture_tgl.h"
#include "hpl1/engine/impl/vertex_buffer_tgl.h"
#include "hpl1/engine/system/low_level_system.h"
#include "common/algorithm.h"
#include "common/system.h"
#include "engines/util.h"
#include "graphics/tinygl/tinygl.h"
#include "hpl1/debug.h"
#include "hpl1/graphics.h"
namespace hpl {
TGLenum ColorFormatToTGL(eColorDataFormat format) {
switch (format) {
case eColorDataFormat_RGB:
return TGL_RGB;
case eColorDataFormat_RGBA:
return TGL_RGBA;
case eColorDataFormat_ALPHA:
return TGL_ALPHA;
case eColorDataFormat_BGR:
return TGL_BGR;
case eColorDataFormat_BGRA:
return TGL_BGRA;
default:
break;
}
Hpl1::logError(Hpl1::kDebugOpenGL, "invalid color format (%d)\n", format);
return 0;
}
TGLenum TextureTargetToTGL(eTextureTarget target) {
switch (target) {
case eTextureTarget_1D:
case eTextureTarget_2D:
return TGL_TEXTURE_2D;
case eTextureTarget_Rect:
case eTextureTarget_CubeMap:
case eTextureTarget_3D:
case eTextureTarget_LastEnum:
break;
}
Hpl1::logError(Hpl1::kDebugOpenGL, "invalid texture target (%d)\n", target);
return 0;
}
TGLenum GetGLBlendEnum(eBlendFunc type) {
switch (type) {
case eBlendFunc_Zero:
return TGL_ZERO;
case eBlendFunc_One:
return TGL_ONE;
case eBlendFunc_SrcColor:
return TGL_SRC_COLOR;
case eBlendFunc_OneMinusSrcColor:
return TGL_ONE_MINUS_SRC_COLOR;
case eBlendFunc_DestColor:
return TGL_DST_COLOR;
case eBlendFunc_OneMinusDestColor:
return TGL_ONE_MINUS_DST_COLOR;
case eBlendFunc_SrcAlpha:
return TGL_SRC_ALPHA;
case eBlendFunc_OneMinusSrcAlpha:
return TGL_ONE_MINUS_SRC_ALPHA;
case eBlendFunc_DestAlpha:
return TGL_DST_ALPHA;
case eBlendFunc_OneMinusDestAlpha:
return TGL_ONE_MINUS_DST_ALPHA;
case eBlendFunc_SrcAlphaSaturate:
return TGL_SRC_ALPHA_SATURATE;
default:
break;
}
Hpl1::logError(Hpl1::kDebugOpenGL, "invalid blend op (%d)", type);
return 0;
}
//-----------------------------------------------------------------------
TGLenum GetGLTextureParamEnum(eTextureParam type) {
switch (type) {
case eTextureParam_AlphaScale:
return TGL_ALPHA_SCALE;
default:
break;
}
Hpl1::logError(Hpl1::kDebugOpenGL, "invalid texture parameter (%d)", type);
return 0;
}
//-----------------------------------------------------------------------
TGLenum GetGLTextureOpEnum(eTextureOp type) {
switch (type) {
case eTextureOp_Color:
return TGL_SRC_COLOR;
case eTextureOp_OneMinusColor:
return TGL_ONE_MINUS_SRC_COLOR;
case eTextureOp_Alpha:
return TGL_SRC_ALPHA;
case eTextureOp_OneMinusAlpha:
return TGL_ONE_MINUS_SRC_ALPHA;
default:
break;
}
Hpl1::logError(Hpl1::kDebugOpenGL, "invalid texture op (%d)", type);
return 0;
}
//-----------------------------------------------------------------------
TGLenum GetGLTextureSourceEnum(eTextureSource type) {
switch (type) {
case eTextureSource_Texture:
return TGL_TEXTURE;
default:
break;
}
Hpl1::logError(Hpl1::kDebugOpenGL, "invalid texture source (%d)", type);
return 0;
}
//-----------------------------------------------------------------------
TGLenum GetTGLTextureTargetEnum(eTextureTarget type) {
return TGL_TEXTURE_2D;
Hpl1::logError(Hpl1::kDebugOpenGL, "invalid texture target (%d)", type);
return 0;
}
//-----------------------------------------------------------------------
TGLenum GetGLTextureFuncEnum(eTextureFunc type) {
switch (type) {
case eTextureFunc_Modulate:
return TGL_MODULATE;
case eTextureFunc_Replace:
return TGL_REPLACE;
case eTextureFunc_Add:
return TGL_ADD;
case eTextureFunc_Subtract:
case eTextureFunc_AddSigned:
case eTextureFunc_Interpolate:
case eTextureFunc_Dot3RGB:
case eTextureFunc_Dot3RGBA:
case eTextureFunc_LastEnum:
break;
}
Hpl1::logError(Hpl1::kDebugOpenGL, "invalid texture function (%d)", type);
return 0;
}
//-----------------------------------------------------------------------
TGLenum GetGLDepthTestFuncEnum(eDepthTestFunc type) {
switch (type) {
case eDepthTestFunc_Never:
return TGL_NEVER;
case eDepthTestFunc_Less:
return TGL_LESS;
case eDepthTestFunc_LessOrEqual:
return TGL_LEQUAL;
case eDepthTestFunc_Greater:
return TGL_GREATER;
case eDepthTestFunc_GreaterOrEqual:
return TGL_GEQUAL;
case eDepthTestFunc_Equal:
return TGL_EQUAL;
case eDepthTestFunc_NotEqual:
return TGL_NOTEQUAL;
case eDepthTestFunc_Always:
return TGL_ALWAYS;
default:
break;
}
Hpl1::logError(Hpl1::kDebugOpenGL, "invalid depth test function (%d)", type);
return 0;
}
//-----------------------------------------------------------------------
TGLenum GetGLAlphaTestFuncEnum(eAlphaTestFunc type) {
switch (type) {
case eAlphaTestFunc_Never:
return TGL_NEVER;
case eAlphaTestFunc_Less:
return TGL_LESS;
case eAlphaTestFunc_LessOrEqual:
return TGL_LEQUAL;
case eAlphaTestFunc_Greater:
return TGL_GREATER;
case eAlphaTestFunc_GreaterOrEqual:
return TGL_GEQUAL;
case eAlphaTestFunc_Equal:
return TGL_EQUAL;
case eAlphaTestFunc_NotEqual:
return TGL_NOTEQUAL;
case eAlphaTestFunc_Always:
return TGL_ALWAYS;
default:
break;
}
Hpl1::logError(Hpl1::kDebugOpenGL, "invalid alpha test function (%d)", type);
return 0;
}
//-----------------------------------------------------------------------
TGLenum GetGLStencilFuncEnum(eStencilFunc type) {
switch (type) {
case eStencilFunc_Never:
return TGL_NEVER;
case eStencilFunc_Less:
return TGL_LESS;
case eStencilFunc_LessOrEqual:
return TGL_LEQUAL;
case eStencilFunc_Greater:
return TGL_GREATER;
case eStencilFunc_GreaterOrEqual:
return TGL_GEQUAL;
case eStencilFunc_Equal:
return TGL_EQUAL;
case eStencilFunc_NotEqual:
return TGL_NOTEQUAL;
case eStencilFunc_Always:
return TGL_ALWAYS;
default:
break;
}
Hpl1::logError(Hpl1::kDebugOpenGL, "invalid stencil function (%d)", type);
return 0;
}
//-----------------------------------------------------------------------
TGLenum GetGLStencilOpEnum(eStencilOp type) {
switch (type) {
case eStencilOp_Keep:
return TGL_KEEP;
case eStencilOp_Zero:
return TGL_ZERO;
case eStencilOp_Replace:
return TGL_REPLACE;
case eStencilOp_Increment:
return TGL_INCR;
case eStencilOp_Decrement:
return TGL_DECR;
case eStencilOp_Invert:
return TGL_INVERT;
case eStencilOp_IncrementWrap:
return TGL_INCR_WRAP;
case eStencilOp_DecrementWrap:
return TGL_DECR_WRAP;
default:
break;
}
Hpl1::logError(Hpl1::kDebugOpenGL, "invalid stencil op (%d)", type);
return 0;
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetMatrixMode(eMatrix type) {
switch (type) {
case eMatrix_ModelView:
tglMatrixMode(TGL_MODELVIEW);
break;
case eMatrix_Projection:
tglMatrixMode(TGL_PROJECTION);
break;
case eMatrix_Texture:
tglMatrixMode(TGL_TEXTURE);
break;
default:
Hpl1::logError(Hpl1::kDebugOpenGL, "invalid matrix mode (%d)", type);
}
}
LowLevelGraphicsTGL::LowLevelGraphicsTGL() {
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;
}
}
LowLevelGraphicsTGL::~LowLevelGraphicsTGL() {
// SDL_SetGammaRamp(mvStartGammaArray[0],mvStartGammaArray[1],mvStartGammaArray[2]);
hplFree(mpVertexArray);
hplFree(mpIndexArray);
for (int i = 0; i < MAX_TEXTUREUNITS; i++)
hplFree(mpTexCoordArray[i]);
}
bool LowLevelGraphicsTGL::Init(int alWidth, int alHeight, int alBpp, int abFullscreen,
int alMultisampling, const tString &asWindowCaption) {
mvScreenSize.x = alWidth;
mvScreenSize.y = alHeight;
mlBpp = alBpp;
mlMultisampling = alMultisampling;
initGraphics(alWidth, alHeight, nullptr);
TinyGL::createContext(alWidth, alHeight, mpPixelFormat, 256, false, true, 60 * 1024 * 1024);
SetupGL();
ShowCursor(false);
g_system->updateScreen();
return true;
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::CheckMultisampleCaps() {
}
//-----------------------------------------------------------------------
static void logOGLInfo(const LowLevelGraphicsTGL &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 LowLevelGraphicsTGL::SetupGL() {
// Inits GL stuff
// Set Shade model and clear color.
tglShadeModel(TGL_SMOOTH);
tglClearColor(0.0f, 0.0f, 0.0f, 0.0f);
tglViewport(0, 0, mvScreenSize.x, mvScreenSize.y);
// Depth Test setup
tglClearDepthf(1.0f); // VAlues buffer is cleared with
tglEnable(TGL_DEPTH_TEST); // enable depth testing
tglDepthFunc(TGL_LEQUAL); // function to do depth test with
tglDisable(TGL_ALPHA_TEST);
// Set best perspective correction
tglHint(TGL_PERSPECTIVE_CORRECTION_HINT, TGL_NICEST);
// Stencil setup
tglClearStencil(0);
// Clear the screen
tglClear(TGL_COLOR_BUFFER_BIT | TGL_DEPTH_BUFFER_BIT /*| TGL_STENCIL_BUFFER_BIT*/);
tglMatrixMode(TGL_MODELVIEW);
tglLoadIdentity();
tglMatrixMode(TGL_PROJECTION);
tglLoadIdentity();
///// BEGIN BATCH ARRAY STUFF ///////////////
// Enable all the vertex arrays that are used:
tglEnableClientState(TGL_VERTEX_ARRAY); // The positions
tglEnableClientState(TGL_COLOR_ARRAY); // The color
tglEnableClientState(TGL_TEXTURE_COORD_ARRAY); // Tex coords
tglDisableClientState(TGL_NORMAL_ARRAY);
// Disable the once not used.
// tglDisableClientState(TGL_INDEX_ARRAY); // color index
// tglDisableClientState(TGL_EDGE_FLAG_ARRAY);
///// END BATCH ARRAY STUFF ///////////////
logOGLInfo(*this);
}
//-----------------------------------------------------------------------
int LowLevelGraphicsTGL::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:
return 0;
// Max Texture Coord Units
case eGraphicCaps_MaxTextureCoordUnits:
return 0;
// 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 0; // gl 2.0
case eGraphicCaps_GL_BlendFunctionSeparate:
return 1; // gl 1.4
case eGraphicCaps_GL_MultiTexture:
return 0; // gl 1.4
default:
break;
}
Hpl1::logWarning(Hpl1::kDebugGraphics, "graphic options %d is not supported\n", type);
return 0;
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::ShowCursor(bool toggle) {
g_system->showMouse(toggle);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetMultisamplingActive(bool toggle) {
return;
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetGammaCorrection(float afX) {
mfGammaCorrection = afX;
}
float LowLevelGraphicsTGL::GetGammaCorrection() {
return mfGammaCorrection;
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetClipPlane(int alIdx, const cPlanef &aPlane) {
HPL1_UNIMPLEMENTED(LowLevelGraphicsTGL::SetClipPlane);
}
cPlanef LowLevelGraphicsTGL::GetClipPlane(int alIdx, const cPlanef &aPlane) {
return mvClipPlanes[alIdx];
}
void LowLevelGraphicsTGL::SetClipPlaneActive(int alIdx, bool toggle) {
HPL1_UNIMPLEMENTED(LowLevelGraphicsTGL::SetClipPlaneActive);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SaveScreenToBMP(const tString &asFile) {
g_system->saveScreenshot();
}
//-----------------------------------------------------------------------
Bitmap2D *LowLevelGraphicsTGL::CreateBitmap2D(const cVector2l &size) {
return hplNew(Bitmap2D, (size, mpPixelFormat));
}
//-----------------------------------------------------------------------
FontData *LowLevelGraphicsTGL::CreateFontData(const tString &asName) {
return hplNew(FontData, (asName, this));
}
//-----------------------------------------------------------------------
iGpuProgram *LowLevelGraphicsTGL::CreateGpuProgram(const tString &vertex, const tString &fragment) {
HPL1_UNIMPLEMENTED(LowLevelGraphicsTGL::CreateGpuProgram);
}
//-----------------------------------------------------------------------
Graphics::PixelFormat *LowLevelGraphicsTGL::GetPixelFormat() {
return &mpPixelFormat;
}
//-----------------------------------------------------------------------
iTexture *LowLevelGraphicsTGL::CreateTexture(bool abUseMipMaps, eTextureType aType, eTextureTarget aTarget) {
if (aTarget != eTextureTarget_2D)
return nullptr;
return hplNew(TGLTexture, ("", &mpPixelFormat, this, aType, abUseMipMaps, aTarget));
}
//-----------------------------------------------------------------------
iTexture *LowLevelGraphicsTGL::CreateTexture(const tString &asName, bool abUseMipMaps, eTextureType aType, eTextureTarget aTarget) {
if (aTarget != eTextureTarget_2D)
return nullptr;
return hplNew(TGLTexture, (asName, &mpPixelFormat, this, aType, abUseMipMaps, aTarget));
}
//-----------------------------------------------------------------------
iTexture *LowLevelGraphicsTGL::CreateTexture(Bitmap2D *apBmp, bool abUseMipMaps, eTextureType aType,
eTextureTarget aTarget) {
if (aTarget != eTextureTarget_2D)
return nullptr;
TGLTexture *pTex = hplNew(TGLTexture, ("", &mpPixelFormat, this, aType, abUseMipMaps, aTarget));
pTex->CreateFromBitmap(apBmp);
return pTex;
}
//-----------------------------------------------------------------------
iTexture *LowLevelGraphicsTGL::CreateTexture(const cVector2l &avSize, int alBpp, cColor aFillCol,
bool abUseMipMaps, eTextureType aType, eTextureTarget aTarget) {
if (aTarget != eTextureTarget_2D)
return nullptr;
TGLTexture *pTex = NULL;
if (aType == eTextureType_RenderTarget) {
pTex = hplNew(TGLTexture, ("", &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(TGLTexture, ("", &mpPixelFormat, this, aType, abUseMipMaps, aTarget));
bool bRet = pTex->CreateFromBitmap(pBmp);
hplDelete(pBmp);
if (bRet == false) {
hplDelete(pTex);
return NULL;
}
}
return pTex;
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::PushMatrix(eMatrix aMtxType) {
SetMatrixMode(aMtxType);
tglPushMatrix();
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::PopMatrix(eMatrix aMtxType) {
SetMatrixMode(aMtxType);
tglPopMatrix();
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetMatrix(eMatrix aMtxType, const cMatrixf &a_mtxA) {
SetMatrixMode(aMtxType);
cMatrixf mtxTranpose = a_mtxA.GetTranspose();
tglLoadMatrixf(mtxTranpose.v);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetIdentityMatrix(eMatrix aMtxType) {
SetMatrixMode(aMtxType);
tglLoadIdentity();
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::TranslateMatrix(eMatrix aMtxType, const cVector3f &avPos) {
SetMatrixMode(aMtxType);
tglTranslatef(avPos.x, avPos.y, avPos.z);
}
//-----------------------------------------------------------------------
/**
* \todo fix so that there are X, Y , Z versions of this one.
* \param aMtxType
* \param &avRot
*/
void LowLevelGraphicsTGL::RotateMatrix(eMatrix aMtxType, const cVector3f &avRot) {
SetMatrixMode(aMtxType);
tglRotatef(1, avRot.x, avRot.y, avRot.z);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::ScaleMatrix(eMatrix aMtxType, const cVector3f &avScale) {
SetMatrixMode(aMtxType);
tglScalef(avScale.x, avScale.y, avScale.z);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetOrthoProjection(const cVector2f &avSize, float afMin, float afMax) {
tglMatrixMode(TGL_PROJECTION);
tglLoadIdentity();
tglOrthof(0, avSize.x, avSize.y, 0, afMin, afMax);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetTexture(unsigned int alUnit, iTexture *apTex) {
if (apTex == mpCurrentTexture[alUnit])
return;
TGLenum NewTarget = 0;
if (apTex)
NewTarget = GetTGLTextureTargetEnum(apTex->GetTarget());
TGLenum LastTarget = 0;
if (mpCurrentTexture[alUnit])
LastTarget = GetTGLTextureTargetEnum(mpCurrentTexture[alUnit]->GetTarget());
// 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) {
tglDisable(LastTarget);
// tglBindTexture(LastTarget,0);
// Enable the unit, set the texture handle and bind the pbuffer
} else {
if (NewTarget != LastTarget && LastTarget != 0)
tglDisable(LastTarget);
TGLTexture *pSDLTex = static_cast(apTex);
tglBindTexture(NewTarget, pSDLTex->GetTextureHandle());
tglEnable(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 LowLevelGraphicsTGL::SetActiveTextureUnit(unsigned int alUnit) {
// tglActiveTexture(GL_TEXTURE0 + alUnit);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetTextureEnv(eTextureParam aParam, int alVal) {
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetTextureConstantColor(const cColor &color) {
// float vColor[] = {color.r, color.g, color.b, color.a};
// tglTexEnvfv(TGL_TEXTURE_ENV, TGL_TEXTURE_ENV_COLOR, &vColor[0]);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetColor(const cColor &aColor) {
tglColor4f(aColor.r, aColor.g, aColor.b, aColor.a);
}
//-----------------------------------------------------------------------
iVertexBuffer *LowLevelGraphicsTGL::CreateVertexBuffer(tVertexFlag aFlags,
eVertexBufferDrawType aDrawType, eVertexBufferUsageType aUsageType, int alReserveVtxSize, int alReserveIdxSize) {
return hplNew(VertexBufferTGL, (this, aFlags, aDrawType, aUsageType, alReserveVtxSize, alReserveIdxSize));
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::DrawRect(const cVector2f &avPos, const cVector2f &avSize, float afZ) {
tglColor4f(1, 1, 1, 1);
tglBegin(TGL_QUADS);
{
tglTexCoord2f(0.0, 0.0);
tglVertex3f(avPos.x, avPos.y, afZ);
tglTexCoord2f(1.0, 0.0);
tglVertex3f(avPos.x + avSize.x, avPos.y, afZ);
tglTexCoord2f(1.0, 1.0);
tglVertex3f(avPos.x + avSize.x, avPos.y + avSize.y, afZ);
tglTexCoord2f(0.0, 1.0);
tglVertex3f(avPos.x, avPos.y + avSize.y, afZ);
}
tglEnd();
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::FlushRendering() {
tglFlush();
}
void LowLevelGraphicsTGL::SwapBuffers() {
tglFlush();
TinyGL::presentBuffer();
Graphics::Surface glBuffer;
TinyGL::getSurfaceRef(glBuffer);
g_system->copyRectToScreen(glBuffer.getPixels(), glBuffer.pitch,
0, 0, glBuffer.w, glBuffer.h);
g_system->updateScreen();
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::DrawTri(const tVertexVec &avVtx) {
assert(avVtx.size() == 3);
tglBegin(TGL_TRIANGLES);
{
for (int i = 0; i < 3; i++) {
tglTexCoord3f(avVtx[i].tex.x, avVtx[i].tex.y, avVtx[i].tex.z);
tglColor4f(avVtx[i].col.r, avVtx[i].col.g, avVtx[i].col.b, avVtx[i].col.a);
tglVertex3f(avVtx[i].pos.x, avVtx[i].pos.y, avVtx[i].pos.z);
}
}
tglEnd();
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::DrawTri(const cVertex *avVtx) {
tglBegin(TGL_TRIANGLES);
{
for (int i = 0; i < 3; i++) {
tglTexCoord3f(avVtx[i].tex.x, avVtx[i].tex.y, avVtx[i].tex.z);
tglColor4f(avVtx[i].col.r, avVtx[i].col.g, avVtx[i].col.b, avVtx[i].col.a);
tglVertex3f(avVtx[i].pos.x, avVtx[i].pos.y, avVtx[i].pos.z);
}
}
tglEnd();
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::DrawQuad(const tVertexVec &avVtx) {
assert(avVtx.size() == 4);
tglBegin(TGL_QUADS);
{
for (int i = 0; i < 4; i++) {
tglTexCoord3f(avVtx[i].tex.x, avVtx[i].tex.y, avVtx[i].tex.z);
tglColor4f(avVtx[i].col.r, avVtx[i].col.g, avVtx[i].col.b, avVtx[i].col.a);
tglVertex3f(avVtx[i].pos.x, avVtx[i].pos.y, avVtx[i].pos.z);
}
}
tglEnd();
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::DrawQuadMultiTex(const tVertexVec &avVtx, const tVector3fVec &avExtraUvs) {
return;
}
//-----------------------------------------------------------------------
iOcclusionQuery *LowLevelGraphicsTGL::CreateOcclusionQuery() {
return hplNew(OcclusionQueryTGL, ());
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::DestroyOcclusionQuery(iOcclusionQuery *apQuery) {
if (apQuery)
hplDelete(apQuery);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::ClearScreen() {
TGLbitfield bitmask = 0;
if (mbClearColor)
bitmask |= TGL_COLOR_BUFFER_BIT;
if (mbClearDepth)
bitmask |= TGL_DEPTH_BUFFER_BIT;
// if (mbClearStencil)
// bitmask |= TGL_STENCIL_BUFFER_BIT;
tglClear(bitmask);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetClearColor(const cColor &aCol) {
tglClearColor(aCol.r, aCol.g, aCol.b, aCol.a);
}
void LowLevelGraphicsTGL::SetClearDepth(float afDepth) {
tglClearDepthf(afDepth);
}
void LowLevelGraphicsTGL::SetClearStencil(int alVal) {
tglClearStencil(alVal);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetClearColorActive(bool abX) {
mbClearColor = abX;
}
void LowLevelGraphicsTGL::SetClearDepthActive(bool abX) {
mbClearDepth = abX;
}
void LowLevelGraphicsTGL::SetClearStencilActive(bool abX) {
mbClearStencil = abX;
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetColorWriteActive(bool abR, bool abG, bool abB, bool abA) {
tglColorMask(abR, abG, abB, abA);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetDepthWriteActive(bool abX) {
tglDepthMask(abX);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetDepthTestActive(bool abX) {
if (abX)
tglEnable(TGL_DEPTH_TEST);
else
tglDisable(TGL_DEPTH_TEST);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetDepthTestFunc(eDepthTestFunc aFunc) {
tglDepthFunc(GetGLDepthTestFuncEnum(aFunc));
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetAlphaTestActive(bool abX) {
if (abX)
tglEnable(TGL_ALPHA_TEST);
else
tglDisable(TGL_ALPHA_TEST);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetAlphaTestFunc(eAlphaTestFunc aFunc, float afRef) {
tglAlphaFunc(GetGLAlphaTestFuncEnum(aFunc), afRef);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetStencilActive(bool abX) {
if (abX)
tglEnable(TGL_STENCIL_TEST);
else
tglDisable(TGL_STENCIL_TEST);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetStencil(eStencilFunc aFunc, int alRef, unsigned int aMask,
eStencilOp aFailOp, eStencilOp aZFailOp, eStencilOp aZPassOp) {
tglStencilFunc(GetGLStencilFuncEnum(aFunc), alRef, aMask);
tglStencilOp(GetGLStencilOpEnum(aFailOp), GetGLStencilOpEnum(aZFailOp),
GetGLStencilOpEnum(aZPassOp));
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetStencilTwoSide(eStencilFunc aFrontFunc, eStencilFunc aBackFunc,
int alRef, unsigned int aMask, eStencilOp aFrontFailOp, eStencilOp aFrontZFailOp, eStencilOp aFrontZPassOp,
eStencilOp aBackFailOp, eStencilOp aBackZFailOp, eStencilOp aBackZPassOp) {
error("Only single sided stencil supported");
}
void LowLevelGraphicsTGL::SetStencilTwoSide(bool abX) {
if (!GetCaps(eGraphicCaps_TwoSideStencil))
Hpl1::logError(Hpl1::kDebugOpenGL, "call to setStencilTwoSide with two side stencil disabled%c\n", '.');
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetCullActive(bool abX) {
if (abX)
tglEnable(TGL_CULL_FACE);
else
tglDisable(TGL_CULL_FACE);
tglCullFace(TGL_BACK);
}
void LowLevelGraphicsTGL::SetCullMode(eCullMode aMode) {
tglCullFace(TGL_BACK);
if (aMode == eCullMode_Clockwise)
tglFrontFace(TGL_CCW);
else
tglFrontFace(TGL_CW);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetScissorActive(bool toggle) {
if (toggle)
tglEnable(TGL_SCISSOR_TEST);
else
tglDisable(TGL_SCISSOR_TEST);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetScissorRect(const cRect2l &aRect) {
// tglScissor(aRect.x, (mvScreenSize.y - aRect.y - 1) - aRect.h, aRect.w, aRect.h);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetBlendActive(bool abX) {
if (abX)
tglEnable(TGL_BLEND);
else
tglDisable(TGL_BLEND);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetBlendFunc(eBlendFunc aSrcFactor, eBlendFunc aDestFactor) {
tglBlendFunc(GetGLBlendEnum(aSrcFactor), GetGLBlendEnum(aDestFactor));
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetBlendFuncSeparate(eBlendFunc aSrcFactorColor, eBlendFunc aDestFactorColor,
eBlendFunc aSrcFactorAlpha, eBlendFunc aDestFactorAlpha) {
HPL1_UNIMPLEMENTED(LowLevelGraphicsTGL::SetBlendFuncSeparate);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::DrawQuad(const tVertexVec &avVtx, const cColor aCol) {
assert(avVtx.size() == 4);
tglBegin(TGL_QUADS);
{
// Make all this inline??
for (int i = 0; i < 4; i++) {
tglTexCoord3f(avVtx[i].tex.x, avVtx[i].tex.y, avVtx[i].tex.z);
tglColor4f(aCol.r, aCol.g, aCol.b, aCol.a);
tglVertex3f(avVtx[i].pos.x, avVtx[i].pos.y, avVtx[i].pos.z);
}
}
tglEnd();
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::DrawQuad(const tVertexVec &avVtx, const float afZ) {
assert(avVtx.size() == 4);
tglBegin(TGL_QUADS);
{
// Make all this inline??
for (int i = 0; i < 4; i++) {
tglTexCoord3f(avVtx[i].tex.x, avVtx[i].tex.y, afZ);
tglColor4f(avVtx[i].col.r, avVtx[i].col.g, avVtx[i].col.b, avVtx[i].col.a);
tglVertex3f(avVtx[i].pos.x, avVtx[i].pos.y, avVtx[i].pos.z);
}
}
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::DrawQuad(const tVertexVec &avVtx, const float afZ, const cColor &aCol) {
assert(avVtx.size() == 4);
tglBegin(TGL_QUADS);
{
// Make all this inline??
for (int i = 0; i < 4; i++) {
tglTexCoord3f(avVtx[i].tex.x, avVtx[i].tex.y, afZ);
tglColor4f(aCol.r, aCol.g, aCol.b, aCol.a);
tglVertex3f(avVtx[i].pos.x, avVtx[i].pos.y, avVtx[i].pos.z);
}
}
tglEnd();
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::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 LowLevelGraphicsTGL::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 LowLevelGraphicsTGL::AddVertexToBatch(const cVertex *apVtx, const cMatrixf *aMtx) {
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::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 LowLevelGraphicsTGL::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 LowLevelGraphicsTGL::AddIndexToBatch(int alIndex) {
mpIndexArray[mlIndexCount] = alIndex;
mlIndexCount++;
if (mlIndexCount >= mlBatchArraySize) {
// Make the array larger.
}
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::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 LowLevelGraphicsTGL::SetBatchTextureUnitActive(unsigned int alUnit, bool active) {
return;
}
//-----------------------------------------------------------------------
static void flushAutoClear(unsigned &indexCount, unsigned &vertexCount, unsigned *texCoordArray) {
indexCount = 0;
vertexCount = 0;
Common::fill(texCoordArray, texCoordArray + MAX_TEXTUREUNITS, 0);
}
void LowLevelGraphicsTGL::FlushTriBatch(tVtxBatchFlag aTypeFlags, bool abAutoClear) {
SetVtxBatchStates(aTypeFlags);
SetUpBatchArrays();
tglDrawElements(TGL_TRIANGLES, mlIndexCount, TGL_UNSIGNED_INT, mpIndexArray);
if (abAutoClear)
flushAutoClear(mlIndexCount, mlVertexCount, mlTexCoordArrayCount);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::FlushQuadBatch(tVtxBatchFlag aTypeFlags, bool abAutoClear) {
SetVtxBatchStates(aTypeFlags);
SetUpBatchArrays();
tglDrawElements(TGL_QUADS, mlIndexCount, TGL_UNSIGNED_INT, mpIndexArray);
if (abAutoClear)
flushAutoClear(mlIndexCount, mlVertexCount, mlTexCoordArrayCount);
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::ClearBatch() {
mlIndexCount = 0;
mlVertexCount = 0;
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::DrawLine(const cVector3f &avBegin, const cVector3f &avEnd, cColor aCol) {
SetTexture(0, nullptr);
// SetBlendActive(false);
tglColor4f(aCol.r, aCol.g, aCol.b, aCol.a);
tglBegin(TGL_LINES);
{
tglVertex3f(avBegin.x, avBegin.y, avBegin.z);
tglVertex3f(avEnd.x, avEnd.y, avEnd.z);
}
tglEnd();
}
void LowLevelGraphicsTGL::DrawBoxMaxMin(const cVector3f &avMax, const cVector3f &avMin, cColor aCol) {
SetTexture(0, NULL);
SetBlendActive(false);
tglColor4f(aCol.r, aCol.g, aCol.b, aCol.a);
tglBegin(TGL_LINES);
{
// Pos Z Quad
tglVertex3f(avMax.x, avMax.y, avMax.z);
tglVertex3f(avMin.x, avMax.y, avMax.z);
tglVertex3f(avMax.x, avMax.y, avMax.z);
tglVertex3f(avMax.x, avMin.y, avMax.z);
tglVertex3f(avMin.x, avMax.y, avMax.z);
tglVertex3f(avMin.x, avMin.y, avMax.z);
tglVertex3f(avMin.x, avMin.y, avMax.z);
tglVertex3f(avMax.x, avMin.y, avMax.z);
// Neg Z Quad
tglVertex3f(avMax.x, avMax.y, avMin.z);
tglVertex3f(avMin.x, avMax.y, avMin.z);
tglVertex3f(avMax.x, avMax.y, avMin.z);
tglVertex3f(avMax.x, avMin.y, avMin.z);
tglVertex3f(avMin.x, avMax.y, avMin.z);
tglVertex3f(avMin.x, avMin.y, avMin.z);
tglVertex3f(avMin.x, avMin.y, avMin.z);
tglVertex3f(avMax.x, avMin.y, avMin.z);
// Lines between
tglVertex3f(avMax.x, avMax.y, avMax.z);
tglVertex3f(avMax.x, avMax.y, avMin.z);
tglVertex3f(avMin.x, avMax.y, avMax.z);
tglVertex3f(avMin.x, avMax.y, avMin.z);
tglVertex3f(avMin.x, avMin.y, avMax.z);
tglVertex3f(avMin.x, avMin.y, avMin.z);
tglVertex3f(avMax.x, avMin.y, avMax.z);
tglVertex3f(avMax.x, avMin.y, avMin.z);
}
tglEnd();
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::DrawSphere(const cVector3f &avPos, float afRadius, cColor aCol) {
int alSegments = 32;
float afAngleStep = k2Pif / (float)alSegments;
SetTexture(0, nullptr);
SetBlendActive(false);
tglColor4f(aCol.r, aCol.g, aCol.b, aCol.a);
tglBegin(TGL_LINES);
{
// X Circle:
for (float a = 0; a < k2Pif; a += afAngleStep) {
tglVertex3f(avPos.x, avPos.y + sin(a) * afRadius,
avPos.z + cos(a) * afRadius);
tglVertex3f(avPos.x, avPos.y + sin(a + afAngleStep) * afRadius,
avPos.z + cos(a + afAngleStep) * afRadius);
}
// Y Circle:
for (float a = 0; a < k2Pif; a += afAngleStep) {
tglVertex3f(avPos.x + cos(a) * afRadius, avPos.y,
avPos.z + sin(a) * afRadius);
tglVertex3f(avPos.x + cos(a + afAngleStep) * afRadius, avPos.y,
avPos.z + sin(a + afAngleStep) * afRadius);
}
// Z Circle:
for (float a = 0; a < k2Pif; a += afAngleStep) {
tglVertex3f(avPos.x + cos(a) * afRadius, avPos.y + sin(a) * afRadius, avPos.z);
tglVertex3f(avPos.x + cos(a + afAngleStep) * afRadius,
avPos.y + sin(a + afAngleStep) * afRadius,
avPos.z);
}
}
tglEnd();
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::DrawLine2D(const cVector2f &avBegin, const cVector2f &avEnd, float afZ, cColor aCol) {
SetTexture(0, NULL);
SetBlendActive(false);
tglColor4f(aCol.r, aCol.g, aCol.b, aCol.a);
tglBegin(TGL_LINES);
{
tglVertex3f(avBegin.x, avBegin.y, afZ);
tglVertex3f(avEnd.x, avEnd.y, afZ);
}
tglEnd();
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::DrawLineRect2D(const cRect2f &aRect, float afZ, cColor aCol) {
SetTexture(0, nullptr);
SetBlendActive(false);
tglColor4f(aCol.r, aCol.g, aCol.b, aCol.a);
tglBegin(TGL_LINE_STRIP);
{
tglVertex3f(aRect.x, aRect.y, afZ);
tglVertex3f(aRect.x + aRect.w, aRect.y, afZ);
tglVertex3f(aRect.x + aRect.w, aRect.y + aRect.h, afZ);
tglVertex3f(aRect.x, aRect.y + aRect.h, afZ);
tglVertex3f(aRect.x, aRect.y, afZ);
}
tglEnd();
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::DrawFilledRect2D(const cRect2f &aRect, float afZ, cColor aCol) {
SetTexture(0, NULL);
tglColor4f(aCol.r, aCol.g, aCol.b, aCol.a);
tglBegin(TGL_QUADS);
{
tglVertex3f(aRect.x, aRect.y, afZ);
tglVertex3f(aRect.x + aRect.w, aRect.y, afZ);
tglVertex3f(aRect.x + aRect.w, aRect.y + aRect.h, afZ);
tglVertex3f(aRect.x, aRect.y + aRect.h, afZ);
}
tglEnd();
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::DrawLineCircle2D(const cVector2f &avCenter, float afRadius, float afZ, cColor aCol) {
// Implement later
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::CopyContextToTexure(iTexture *apTex, const cVector2l &avPos,
const cVector2l &avSize, const cVector2l &avTexOffset) {
#if 0
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);
SetTexture(0, apTex);
tglCopyTexSubImage2D(GetGLTextureTargetEnum(apTex->GetTarget(), 0,
avTexOffset.x, lTexY, avPos.x, lScreenY, avSize.x, avSize.y));
#endif
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetRenderTarget(iTexture *pTex) {
HPL1_UNIMPLEMENTED(LowLevelGraphicsTGL::SetRenderTarget);
}
//-----------------------------------------------------------------------
bool LowLevelGraphicsTGL::RenderTargetHasZBuffer() {
return true;
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::FlushRenderTarget() {
HPL1_UNIMPLEMENTED(LowLevelGraphicsTGL::FlushRenderTarget);
}
//-----------------------------------------------------------------------
cVector2f LowLevelGraphicsTGL::GetScreenSize() {
return cVector2f((float)mvScreenSize.x, (float)mvScreenSize.y);
}
//-----------------------------------------------------------------------
cVector2f LowLevelGraphicsTGL::GetVirtualSize() {
return mvVirtualSize;
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetVirtualSize(cVector2f avSize) {
mvVirtualSize = avSize;
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetUpBatchArrays() {
// Set the arrays
tglVertexPointer(3, TGL_FLOAT, sizeof(float) * mlBatchStride, mpVertexArray);
tglColorPointer(4, TGL_FLOAT, sizeof(float) * mlBatchStride, &mpVertexArray[3]);
tglNormalPointer(TGL_FLOAT, sizeof(float) * mlBatchStride, &mpVertexArray[10]);
tglTexCoordPointer(3, TGL_FLOAT, sizeof(float) * mlBatchStride, &mpVertexArray[7]);
#if 0
tglClientActiveTextureARB(GL_TEXTURE1_ARB);
tglTexCoordPointer(3, TGL_FLOAT, sizeof(float) * mlBatchStride, &mpVertexArray[7]);
tglClientActiveTextureARB(GL_TEXTURE2_ARB);
tglTexCoordPointer(3, TGL_FLOAT, sizeof(float) * mlBatchStride, &mpVertexArray[7]);
#endif
}
//-----------------------------------------------------------------------
void LowLevelGraphicsTGL::SetVtxBatchStates(tVtxBatchFlag flags) {
if (flags & eVtxBatchFlag_Position) {
tglEnableClientState(TGL_VERTEX_ARRAY);
} else {
tglDisableClientState(TGL_VERTEX_ARRAY);
}
if (flags & eVtxBatchFlag_Color0) {
tglEnableClientState(TGL_COLOR_ARRAY);
} else {
tglDisableClientState(TGL_COLOR_ARRAY);
}
if (flags & eVtxBatchFlag_Normal) {
tglEnableClientState(TGL_NORMAL_ARRAY);
} else {
tglDisableClientState(TGL_NORMAL_ARRAY);
}
if (flags & eVtxBatchFlag_Texture0) {
// tglClientActiveTexture(TGL_TEXTURE);
tglEnableClientState(TGL_TEXTURE_COORD_ARRAY);
} else {
// tglClientActiveTextureARB(TGL_TEXTURE0_ARB);
tglDisableClientState(TGL_TEXTURE_COORD_ARRAY);
}
#if 0
if (flags & eVtxBatchFlag_Texture1) {
GL_CHECK(glClientActiveTextureARB(TGL_TEXTURE1_ARB));
tglEnableClientState(GL_TEXTURE_COORD_ARRAY);
} else {
tglClientActiveTextureARB(GL_TEXTURE1_ARB);
tglDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (flags & eVtxBatchFlag_Texture2) {
tglClientActiveTextureARB(GL_TEXTURE2_ARB);
tglEnableClientState(GL_TEXTURE_COORD_ARRAY);
} else {
tglClientActiveTextureARB(GL_TEXTURE2_ARB);
tglDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
#endif
}
} // namespace hpl