leocad/common/lc_context.cpp

1291 lines
33 KiB
C++
Raw Normal View History

2016-10-05 23:28:52 +02:00
#include "lc_global.h"
#include "lc_context.h"
#include "lc_glextensions.h"
#include "lc_mesh.h"
#include "lc_texture.h"
#include "lc_colors.h"
#include "lc_mainwindow.h"
#include "lc_library.h"
2017-02-11 21:41:00 +01:00
#ifdef LC_OPENGLES
#define glEnableClientState(...)
#define glDisableClientState(...)
#define glVertexPointer(...)
#define glTexCoordPointer(...)
#define glColorPointer(...)
#define GL_ARRAY_BUFFER_ARB GL_ARRAY_BUFFER
#define GL_ELEMENT_ARRAY_BUFFER_ARB GL_ELEMENT_ARRAY_BUFFER
#define GL_STATIC_DRAW_ARB GL_STATIC_DRAW
#endif
2020-03-22 21:44:20 +01:00
lcProgram lcContext::mPrograms[static_cast<int>(lcMaterialType::Count)];
2016-10-05 23:28:52 +02:00
lcContext::lcContext()
{
mVertexBufferObject = 0;
mIndexBufferObject = 0;
mVertexBufferPointer = nullptr;
mIndexBufferPointer = nullptr;
2016-10-05 23:28:52 +02:00
mVertexBufferOffset = (char*)~0;
2017-02-18 20:12:35 +01:00
mNormalEnabled = false;
2016-10-05 23:28:52 +02:00
mTexCoordEnabled = false;
mColorEnabled = false;
2017-12-26 19:19:20 +01:00
mTexture2D = 0;
mTexture2DMS = 0;
2018-10-29 01:59:01 +01:00
mTextureCubeMap = 0;
2020-03-22 21:44:20 +01:00
mPolygonOffset = lcPolygonOffset::None;
2019-11-10 03:11:25 +01:00
mDepthWrite = true;
2016-10-05 23:28:52 +02:00
mLineWidth = 1.0f;
2017-02-11 21:41:00 +01:00
#ifndef LC_OPENGLES
2016-10-05 23:28:52 +02:00
mMatrixMode = GL_MODELVIEW;
2017-03-25 20:29:28 +01:00
mTextureEnabled = false;
2017-02-11 21:41:00 +01:00
#endif
2016-10-05 23:28:52 +02:00
mFramebufferObject = 0;
mColor = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
mWorldMatrix = lcMatrix44Identity();
mViewMatrix = lcMatrix44Identity();
mProjectionMatrix = lcMatrix44Identity();
mViewProjectionMatrix = lcMatrix44Identity();
2019-01-13 02:43:23 +01:00
mHighlightParams[0] = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
mHighlightParams[1] = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
mHighlightParams[2] = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
2019-01-20 05:04:08 +01:00
mHighlightParams[3] = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
2016-10-05 23:28:52 +02:00
mColorDirty = false;
mWorldMatrixDirty = false;
mViewMatrixDirty = false;
mProjectionMatrixDirty = false;
mViewProjectionMatrixDirty = false;
2019-01-13 02:43:23 +01:00
mHighlightParamsDirty = false;
2016-10-05 23:28:52 +02:00
2020-03-22 21:44:20 +01:00
mMaterialType = lcMaterialType::Count;
2016-10-05 23:28:52 +02:00
}
lcContext::~lcContext()
{
}
void lcContext::CreateShaderPrograms()
{
2018-11-23 01:13:02 +01:00
const char* ShaderPrefix =
{
2017-02-11 21:41:00 +01:00
#ifndef LC_OPENGLES
2018-11-23 01:13:02 +01:00
"#version 110\n"
"#define mediump\n"
"#define LC_VERTEX_INPUT attribute\n"
"#define LC_VERTEX_OUTPUT varying\n"
"#define LC_PIXEL_INPUT varying\n"
"#define LC_PIXEL_OUTPUT\n"
"#define LC_SHADER_PRECISION\n"
2017-02-11 21:41:00 +01:00
#else
2018-11-23 01:13:02 +01:00
"#version 300 es\n"
"#define texture2D texture\n"
"#define LC_VERTEX_INPUT in\n"
"#define LC_VERTEX_OUTPUT out\n"
"#define LC_PIXEL_INPUT in mediump\n"
"#define gl_FragColor FragColor\n"
"#define LC_PIXEL_OUTPUT out mediump vec4 gl_FragColor;\n"
"#define LC_SHADER_PRECISION mediump\n"
2017-02-11 21:41:00 +01:00
#endif
2018-11-23 01:13:02 +01:00
"#define LC_PIXEL_FAKE_LIGHTING \\\n"
" LC_SHADER_PRECISION vec3 Normal = normalize(PixelNormal); \\\n"
" LC_SHADER_PRECISION vec3 LightDirection = normalize(PixelPosition - LightPosition); \\\n"
" LC_SHADER_PRECISION vec3 VertexToEye = normalize(EyePosition - PixelPosition); \\\n"
" LC_SHADER_PRECISION vec3 LightReflect = normalize(reflect(-LightDirection, Normal)); \\\n"
" LC_SHADER_PRECISION float Specular = abs(dot(VertexToEye, LightReflect)); \\\n"
" Specular = min(pow(Specular, 8.0), 1.0) * 0.25; \\\n"
" LC_SHADER_PRECISION vec3 SpecularColor = vec3(Specular, Specular, Specular); \\\n"
" LC_SHADER_PRECISION float Diffuse = min(abs(dot(Normal, LightDirection)) * 0.6 + 0.65, 1.0);\n"
};
2017-03-12 01:47:21 +01:00
2020-03-23 04:18:52 +01:00
const char* const VertexShaders[static_cast<int>(lcMaterialType::Count)] =
2016-10-05 23:28:52 +02:00
{
2020-03-22 21:44:20 +01:00
":/resources/shaders/unlit_color_vs.glsl", // UnlitColor
":/resources/shaders/unlit_texture_modulate_vs.glsl", // UnlitTextureModulate
":/resources/shaders/unlit_texture_decal_vs.glsl", // UnlitTextureDecal
":/resources/shaders/unlit_vertex_color_vs.glsl", // UnlitVertexColor
":/resources/shaders/unlit_view_sphere_vs.glsl", // UnlitViewSphere
":/resources/shaders/fakelit_color_vs.glsl", // FakeLitColor
":/resources/shaders/fakelit_texture_decal_vs.glsl" // FakeLitTextureDecal
2016-10-05 23:28:52 +02:00
};
2020-03-23 04:18:52 +01:00
const char* const FragmentShaders[static_cast<int>(lcMaterialType::Count)] =
2016-10-05 23:28:52 +02:00
{
2020-03-22 21:44:20 +01:00
":/resources/shaders/unlit_color_ps.glsl", // UnlitColor
":/resources/shaders/unlit_texture_modulate_ps.glsl", // UnlitTextureModulate
":/resources/shaders/unlit_texture_decal_ps.glsl", // UnlitTextureDecal
":/resources/shaders/unlit_vertex_color_ps.glsl", // UnlitVertexColor
":/resources/shaders/unlit_view_sphere_ps.glsl", // UnlitViewSphere
":/resources/shaders/fakelit_color_ps.glsl", // FakeLitColor
":/resources/shaders/fakelit_texture_decal_ps.glsl" // FakeLitTextureDecal
2016-10-05 23:28:52 +02:00
};
2020-03-23 04:18:52 +01:00
const auto LoadShader = [ShaderPrefix](const char* FileName, GLuint ShaderType) -> GLuint
2016-10-05 23:28:52 +02:00
{
2018-11-23 01:13:02 +01:00
QResource Resource(FileName);
2016-10-05 23:28:52 +02:00
2018-11-23 01:13:02 +01:00
if (!Resource.isValid())
return 0;
2016-10-05 23:28:52 +02:00
2018-11-23 01:13:02 +01:00
QByteArray Data;
2016-10-05 23:28:52 +02:00
2018-11-23 01:13:02 +01:00
if (Resource.isCompressed())
Data = qUncompress(Resource.data(), Resource.size());
else
Data = QByteArray::fromRawData((const char*)Resource.data(), Resource.size());
2016-10-05 23:28:52 +02:00
2018-11-23 01:13:02 +01:00
Data = ShaderPrefix + Data;
const char* Source = Data.constData();
2016-10-05 23:28:52 +02:00
2020-03-23 04:18:52 +01:00
const GLuint Shader = glCreateShader(ShaderType);
2018-11-23 01:13:02 +01:00
glShaderSource(Shader, 1, &Source, nullptr);
glCompileShader(Shader);
2016-10-05 23:28:52 +02:00
#ifndef QT_NO_DEBUG
2018-11-23 01:13:02 +01:00
GLint ShaderCompiled = 0;
glGetShaderiv(Shader, GL_COMPILE_STATUS, &ShaderCompiled);
2016-10-05 23:28:52 +02:00
2018-11-23 01:13:02 +01:00
if (ShaderCompiled == GL_FALSE)
{
GLint Length = 0;
2018-11-23 01:13:02 +01:00
glGetShaderiv(Shader, GL_INFO_LOG_LENGTH, &Length);
2016-10-05 23:28:52 +02:00
QByteArray InfoLog;
InfoLog.resize(Length);
2018-11-23 01:13:02 +01:00
glGetShaderInfoLog(Shader, Length, &Length, InfoLog.data());
2016-10-05 23:28:52 +02:00
qDebug() << InfoLog;
}
2016-10-05 23:28:52 +02:00
#endif
2018-11-23 01:13:02 +01:00
return Shader;
};
2020-03-22 21:44:20 +01:00
for (int MaterialType = 0; MaterialType < static_cast<int>(lcMaterialType::Count); MaterialType++)
2018-11-23 01:13:02 +01:00
{
2020-03-23 04:18:52 +01:00
const GLuint VertexShader = LoadShader(VertexShaders[MaterialType], GL_VERTEX_SHADER);
const GLuint FragmentShader = LoadShader(FragmentShaders[MaterialType], GL_FRAGMENT_SHADER);
2018-11-23 01:13:02 +01:00
GLuint Program = glCreateProgram();
2016-10-05 23:28:52 +02:00
glAttachShader(Program, VertexShader);
glAttachShader(Program, FragmentShader);
2016-10-05 23:28:52 +02:00
glBindAttribLocation(Program, LC_ATTRIB_POSITION, "VertexPosition");
glBindAttribLocation(Program, LC_ATTRIB_NORMAL, "VertexNormal");
glBindAttribLocation(Program, LC_ATTRIB_TEXCOORD, "VertexTexCoord");
glBindAttribLocation(Program, LC_ATTRIB_COLOR, "VertexColor");
2016-10-05 23:28:52 +02:00
glLinkProgram(Program);
2016-10-05 23:28:52 +02:00
glDetachShader(Program, VertexShader);
glDetachShader(Program, FragmentShader);
glDeleteShader(VertexShader);
glDeleteShader(FragmentShader);
GLint IsLinked = 0;
glGetProgramiv(Program, GL_LINK_STATUS, &IsLinked);
2018-11-23 01:13:02 +01:00
if (IsLinked == GL_FALSE)
{
GLint Length = 0;
glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &Length);
QByteArray InfoLog;
InfoLog.resize(Length);
glGetProgramInfoLog(Program, Length, &Length, InfoLog.data());
2016-10-05 23:28:52 +02:00
glDeleteProgram(Program);
Program = 0;
}
mPrograms[MaterialType].Object = Program;
mPrograms[MaterialType].WorldViewProjectionMatrixLocation = glGetUniformLocation(Program, "WorldViewProjectionMatrix");
mPrograms[MaterialType].WorldMatrixLocation = glGetUniformLocation(Program, "WorldMatrix");
mPrograms[MaterialType].MaterialColorLocation = glGetUniformLocation(Program, "MaterialColor");
mPrograms[MaterialType].LightPositionLocation = glGetUniformLocation(Program, "LightPosition");
mPrograms[MaterialType].EyePositionLocation = glGetUniformLocation(Program, "EyePosition");
2019-01-13 02:43:23 +01:00
mPrograms[MaterialType].HighlightParamsLocation = glGetUniformLocation(Program, "HighlightParams");
2016-10-05 23:28:52 +02:00
}
}
void lcContext::CreateResources()
{
if (!gSupportsShaderObjects)
return;
CreateShaderPrograms();
}
void lcContext::DestroyResources()
{
if (!gSupportsShaderObjects)
return;
2020-03-22 21:44:20 +01:00
for (int MaterialType = 0; MaterialType < static_cast<int>(lcMaterialType::Count); MaterialType++)
{
glDeleteProgram(mPrograms[MaterialType].Object);
mPrograms[MaterialType].Object = 0;
}
2016-10-05 23:28:52 +02:00
}
void lcContext::SetDefaultState()
{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
if (gSupportsBlendFuncSeparate)
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE);
else
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2017-03-25 08:03:17 +01:00
2016-10-05 23:28:52 +02:00
if (gSupportsVertexBufferObject)
{
glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
}
if (gSupportsShaderObjects)
{
glEnableVertexAttribArray(LC_ATTRIB_POSITION);
2017-02-18 20:12:35 +01:00
glDisableVertexAttribArray(LC_ATTRIB_NORMAL);
2016-10-05 23:28:52 +02:00
glDisableVertexAttribArray(LC_ATTRIB_TEXCOORD);
glDisableVertexAttribArray(LC_ATTRIB_COLOR);
}
else
{
2017-12-07 07:08:56 +01:00
#ifndef LC_OPENGLES
2016-10-05 23:28:52 +02:00
glEnableClientState(GL_VERTEX_ARRAY);
2017-02-18 20:12:35 +01:00
glDisableClientState(GL_NORMAL_ARRAY);
2016-10-05 23:28:52 +02:00
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, nullptr);
glNormalPointer(GL_BYTE, 0, nullptr);
glTexCoordPointer(2, GL_FLOAT, 0, nullptr);
glColorPointer(4, GL_FLOAT, 0, nullptr);
2017-12-07 07:08:56 +01:00
#endif
2016-10-05 23:28:52 +02:00
}
2017-02-18 20:12:35 +01:00
mNormalEnabled = false;
2016-10-05 23:28:52 +02:00
mTexCoordEnabled = false;
mColorEnabled = false;
mVertexBufferObject = 0;
mIndexBufferObject = 0;
mVertexBufferPointer = nullptr;
mIndexBufferPointer = nullptr;
2016-10-05 23:28:52 +02:00
mVertexBufferOffset = (char*)~0;
2017-03-25 20:29:28 +01:00
glBindTexture(GL_TEXTURE_2D, 0);
2017-12-26 19:19:20 +01:00
mTexture2D = 0;
2017-12-30 21:04:12 +01:00
#ifndef LC_OPENGLES
if (gSupportsTexImage2DMultisample)
{
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
mTexture2DMS = 0;
}
2017-12-30 21:04:12 +01:00
#endif
2018-10-29 01:59:01 +01:00
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
mTextureCubeMap = 0;
2016-10-05 23:28:52 +02:00
glDisable(GL_POLYGON_OFFSET_FILL);
2020-03-22 21:44:20 +01:00
mPolygonOffset = lcPolygonOffset::None;
2019-11-10 03:11:25 +01:00
mDepthWrite = true;
glDepthMask(GL_TRUE);
2016-10-05 23:28:52 +02:00
glLineWidth(1.0f);
mLineWidth = 1.0f;
if (gSupportsShaderObjects)
{
glUseProgram(0);
2020-03-22 21:44:20 +01:00
mMaterialType = lcMaterialType::Count;
2016-10-05 23:28:52 +02:00
}
else
{
2017-02-11 21:41:00 +01:00
#ifndef LC_OPENGLES
2016-10-05 23:28:52 +02:00
glMatrixMode(GL_MODELVIEW);
mMatrixMode = GL_MODELVIEW;
2017-02-18 20:12:35 +01:00
glShadeModel(GL_FLAT);
2017-03-25 20:29:28 +01:00
glDisable(GL_TEXTURE_2D);
mTextureEnabled = false;
2017-02-11 21:41:00 +01:00
#endif
2016-10-05 23:28:52 +02:00
}
}
2017-03-25 20:29:28 +01:00
void lcContext::ClearResources()
{
ClearVertexBuffer();
ClearIndexBuffer();
2017-12-26 19:19:20 +01:00
BindTexture2D(0);
BindTexture2DMS(0);
2017-03-25 20:29:28 +01:00
}
void lcContext::SetMaterial(lcMaterialType MaterialType)
2016-10-05 23:28:52 +02:00
{
2017-03-25 02:36:58 +01:00
if (MaterialType == mMaterialType)
2016-10-05 23:28:52 +02:00
return;
mMaterialType = MaterialType;
2017-03-25 02:36:58 +01:00
if (gSupportsShaderObjects)
{
2020-03-22 21:44:20 +01:00
glUseProgram(mPrograms[static_cast<int>(MaterialType)].Object);
2017-03-25 02:36:58 +01:00
mColorDirty = true;
mWorldMatrixDirty = true; // todo: change dirty to a bitfield and set the lighting constants dirty here
mViewMatrixDirty = true;
2019-01-13 02:43:23 +01:00
mHighlightParamsDirty = true;
2017-03-25 02:36:58 +01:00
}
else
{
#ifndef LC_OPENGLES
switch (MaterialType)
{
2020-03-22 21:44:20 +01:00
case lcMaterialType::UnlitTextureModulate:
2017-03-25 02:36:58 +01:00
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2017-03-25 20:29:28 +01:00
if (!mTextureEnabled)
{
glEnable(GL_TEXTURE_2D);
mTextureEnabled = true;
}
2017-03-25 02:36:58 +01:00
break;
2020-03-22 21:44:20 +01:00
case lcMaterialType::FakeLitTextureDecal:
case lcMaterialType::UnlitTextureDecal:
2017-03-25 02:36:58 +01:00
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
2017-03-25 20:29:28 +01:00
if (!mTextureEnabled)
{
glEnable(GL_TEXTURE_2D);
mTextureEnabled = true;
}
2017-03-25 02:36:58 +01:00
break;
2020-03-22 21:44:20 +01:00
case lcMaterialType::UnlitColor:
case lcMaterialType::UnlitVertexColor:
case lcMaterialType::FakeLitColor:
2017-03-25 20:29:28 +01:00
if (mTextureEnabled)
{
glDisable(GL_TEXTURE_2D);
mTextureEnabled = false;
}
break;
2020-03-22 21:44:20 +01:00
case lcMaterialType::UnlitViewSphere:
case lcMaterialType::Count:
2017-03-25 02:36:58 +01:00
break;
}
#endif
}
2016-10-05 23:28:52 +02:00
}
void lcContext::SetViewport(int x, int y, int Width, int Height)
{
glViewport(x, y, Width, Height);
}
void lcContext::SetPolygonOffset(lcPolygonOffset PolygonOffset)
{
if (mPolygonOffset == PolygonOffset)
return;
switch (PolygonOffset)
{
2020-03-22 21:44:20 +01:00
case lcPolygonOffset::None:
glDisable(GL_POLYGON_OFFSET_FILL);
break;
2020-03-22 21:44:20 +01:00
case lcPolygonOffset::Opaque:
glPolygonOffset(0.5f, 0.1f);
glEnable(GL_POLYGON_OFFSET_FILL);
break;
2020-03-22 21:44:20 +01:00
case lcPolygonOffset::Translucent:
glPolygonOffset(0.25f, 0.1f);
glEnable(GL_POLYGON_OFFSET_FILL);
break;
}
mPolygonOffset = PolygonOffset;
}
2019-11-10 03:11:25 +01:00
void lcContext::SetDepthWrite(bool Enable)
{
if (Enable == mDepthWrite)
return;
glDepthMask(Enable ? GL_TRUE : GL_FALSE);
mDepthWrite = Enable;
}
2016-10-05 23:28:52 +02:00
void lcContext::SetLineWidth(float LineWidth)
{
if (LineWidth == mLineWidth)
return;
glLineWidth(LineWidth);
mLineWidth = LineWidth;
}
2017-04-27 07:24:54 +02:00
void lcContext::SetSmoothShading(bool Smooth)
{
#ifndef LC_OPENGLES
if (gSupportsShaderObjects)
glShadeModel(Smooth ? GL_SMOOTH : GL_FLAT);
#endif
}
2017-12-26 19:19:20 +01:00
void lcContext::BindTexture2D(GLuint Texture)
2017-03-25 20:29:28 +01:00
{
2017-12-26 19:19:20 +01:00
if (mTexture2D == Texture)
2017-03-25 20:29:28 +01:00
return;
glBindTexture(GL_TEXTURE_2D, Texture);
2017-12-26 19:19:20 +01:00
mTexture2D = Texture;
}
void lcContext::BindTexture2DMS(GLuint Texture)
{
if (mTexture2DMS == Texture)
return;
2017-12-30 21:04:12 +01:00
#ifndef LC_OPENGLES
if (gSupportsTexImage2DMultisample)
{
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, Texture);
mTexture2DMS = Texture;
}
2017-12-30 21:04:12 +01:00
#endif
2017-03-25 20:29:28 +01:00
}
2018-10-29 01:59:01 +01:00
void lcContext::BindTextureCubeMap(GLuint Texture)
{
if (mTextureCubeMap == Texture)
return;
glBindTexture(GL_TEXTURE_CUBE_MAP, Texture);
mTextureCubeMap = Texture;
}
2018-09-24 04:31:33 +02:00
void lcContext::UnbindTexture2D(GLuint Texture)
{
if (mTexture2D != Texture)
return;
glBindTexture(GL_TEXTURE_2D, 0);
mTexture2D = 0;
}
2018-10-29 01:59:01 +01:00
void lcContext::UnbindTextureCubeMap(GLuint Texture)
{
if (mTextureCubeMap != Texture)
return;
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
mTextureCubeMap = 0;
}
2016-10-05 23:28:52 +02:00
void lcContext::SetColor(float Red, float Green, float Blue, float Alpha)
{
SetColor(lcVector4(Red, Green, Blue, Alpha));
}
void lcContext::SetColorIndex(int ColorIndex)
{
SetColor(gColorList[ColorIndex].Value);
}
void lcContext::SetColorIndexTinted(int ColorIndex, lcInterfaceColor InterfaceColor, float Weight)
2016-10-05 23:28:52 +02:00
{
2020-03-23 04:18:52 +01:00
const lcVector3 Color(gColorList[ColorIndex].Value * Weight + gInterfaceColors[InterfaceColor] * (1.0f - Weight));
SetColor(lcVector4(Color, gColorList[ColorIndex].Value.w));
2016-10-05 23:28:52 +02:00
}
2020-04-20 05:21:18 +02:00
void lcContext::SetColorIndexTintedAlpha(int ColorIndex, lcInterfaceColor InterfaceColor, float Weight)
{
const lcVector3 Color(gColorList[ColorIndex].Value * Weight + gInterfaceColors[InterfaceColor] * (1.0f - Weight));
SetColor(lcVector4(Color, gColorList[ColorIndex].Value.w * gInterfaceColors[InterfaceColor].w));
}
2016-10-05 23:28:52 +02:00
void lcContext::SetEdgeColorIndex(int ColorIndex)
{
SetColor(gColorList[ColorIndex].Edge);
}
2020-04-20 05:21:18 +02:00
void lcContext::SetEdgeColorIndexTinted(int ColorIndex, lcInterfaceColor InterfaceColor, float Weight)
{
const lcVector3 Color(gColorList[ColorIndex].Edge * Weight + gInterfaceColors[InterfaceColor] * (1.0f - Weight));
SetColor(lcVector4(Color, gColorList[ColorIndex].Edge.w));
}
void lcContext::SetEdgeColorIndexTintedAlpha(int ColorIndex, lcInterfaceColor InterfaceColor, float Weight)
{
const lcVector3 Color(gColorList[ColorIndex].Edge * Weight + gInterfaceColors[InterfaceColor] * (1.0f - Weight));
SetColor(lcVector4(Color, gColorList[ColorIndex].Edge.w * gInterfaceColors[InterfaceColor].w));
}
2016-10-05 23:28:52 +02:00
void lcContext::SetInterfaceColor(lcInterfaceColor InterfaceColor)
{
SetColor(gInterfaceColors[InterfaceColor]);
}
void lcContext::ClearFramebuffer()
2016-10-05 23:28:52 +02:00
{
if (!mFramebufferObject)
return;
2016-10-05 23:28:52 +02:00
if (gSupportsFramebufferObjectARB)
glBindFramebuffer(GL_FRAMEBUFFER, 0);
#ifndef LC_OPENGLES
else if (gSupportsFramebufferObjectEXT)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
#endif
2017-12-26 19:19:20 +01:00
mFramebufferObject = 0;
}
2017-12-26 19:19:20 +01:00
lcFramebuffer lcContext::CreateFramebuffer(int Width, int Height, bool Depth, bool Multisample)
{
lcFramebuffer Framebuffer(Width, Height);
if (gSupportsFramebufferObjectARB)
{
int Samples = (Multisample && gSupportsTexImage2DMultisample && QGLFormat::defaultFormat().sampleBuffers()) ? QGLFormat::defaultFormat().samples() : 1;
glGenFramebuffers(1, &Framebuffer.mObject);
glBindFramebuffer(GL_FRAMEBUFFER, Framebuffer.mObject);
2017-12-26 19:19:20 +01:00
glGenTextures(1, &Framebuffer.mColorTexture);
if (Depth)
glGenRenderbuffers(1, &Framebuffer.mDepthRenderbuffer);
2016-10-05 23:28:52 +02:00
2017-12-26 19:19:20 +01:00
if (Samples == 1)
{
BindTexture2D(Framebuffer.mColorTexture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
BindTexture2D(0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Framebuffer.mColorTexture, 0);
if (Depth)
{
glBindRenderbuffer(GL_RENDERBUFFER, Framebuffer.mDepthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, Width, Height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, Framebuffer.mDepthRenderbuffer);
}
2017-12-26 19:19:20 +01:00
}
2017-12-30 21:04:12 +01:00
#ifndef LC_OPENGLES
2017-12-26 19:19:20 +01:00
else
{
BindTexture2DMS(Framebuffer.mColorTexture);
2017-12-26 19:19:20 +01:00
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, Samples, GL_RGBA, Width, Height, GL_TRUE);
BindTexture2DMS(0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, Framebuffer.mColorTexture, 0);
2016-10-05 23:28:52 +02:00
if (Depth)
{
glBindRenderbuffer(GL_RENDERBUFFER, Framebuffer.mDepthRenderbuffer);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, Samples, GL_DEPTH_COMPONENT24, Width, Height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, Framebuffer.mDepthRenderbuffer);
}
2017-12-26 19:19:20 +01:00
}
2017-12-30 21:04:12 +01:00
#endif
2017-12-26 19:19:20 +01:00
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
DestroyFramebuffer(Framebuffer);
2016-10-05 23:28:52 +02:00
glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferObject);
2016-10-05 23:28:52 +02:00
}
2017-02-11 21:41:00 +01:00
#ifndef LC_OPENGLES
else if (gSupportsFramebufferObjectEXT)
2016-10-05 23:28:52 +02:00
{
glGenFramebuffersEXT(1, &Framebuffer.mObject);
glGenTextures(1, &Framebuffer.mColorTexture);
2016-10-05 23:28:52 +02:00
BindTexture2D(Framebuffer.mColorTexture);
2016-10-05 23:28:52 +02:00
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2016-10-05 23:28:52 +02:00
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, Framebuffer.mObject);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, Framebuffer.mColorTexture, 0);
2016-10-05 23:28:52 +02:00
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, Framebuffer.mObject);
2016-10-05 23:28:52 +02:00
glGenRenderbuffersEXT(1, &Framebuffer.mDepthRenderbuffer);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, Framebuffer.mDepthRenderbuffer);
2016-10-05 23:28:52 +02:00
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, Width, Height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, Framebuffer.mDepthRenderbuffer);
2016-10-05 23:28:52 +02:00
2017-12-26 19:19:20 +01:00
BindTexture2D(0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, Framebuffer.mObject);
2016-10-05 23:28:52 +02:00
if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
DestroyFramebuffer(Framebuffer);
2016-10-05 23:28:52 +02:00
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFramebufferObject);
2016-10-05 23:28:52 +02:00
}
2017-02-11 21:41:00 +01:00
#endif
return Framebuffer;
2016-10-05 23:28:52 +02:00
}
void lcContext::DestroyFramebuffer(lcFramebuffer& Framebuffer)
2016-10-05 23:28:52 +02:00
{
if (gSupportsFramebufferObjectARB)
{
glDeleteFramebuffers(1, &Framebuffer.mObject);
glDeleteTextures(1, &Framebuffer.mColorTexture);
glDeleteRenderbuffers(1, &Framebuffer.mDepthRenderbuffer);
2016-10-05 23:28:52 +02:00
}
2017-02-11 21:41:00 +01:00
#ifndef LC_OPENGLES
else if (gSupportsFramebufferObjectEXT)
2016-10-05 23:28:52 +02:00
{
glDeleteFramebuffersEXT(1, &Framebuffer.mObject);
glDeleteTextures(1, &Framebuffer.mColorTexture);
glDeleteRenderbuffersEXT(1, &Framebuffer.mDepthRenderbuffer);
2016-10-05 23:28:52 +02:00
}
2017-02-11 21:41:00 +01:00
#endif
Framebuffer.mObject = 0;
Framebuffer.mColorTexture = 0;
Framebuffer.mDepthRenderbuffer = 0;
Framebuffer.mWidth = 0;
Framebuffer.mHeight = 0;
2016-10-05 23:28:52 +02:00
}
void lcContext::BindFramebuffer(GLuint FramebufferObject)
2016-10-05 23:28:52 +02:00
{
if (FramebufferObject == mFramebufferObject)
return;
2017-12-26 19:19:20 +01:00
if (gSupportsFramebufferObjectARB)
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferObject);
#ifndef LC_OPENGLES
else if (gSupportsFramebufferObjectEXT)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferObject);
#endif
mFramebufferObject = FramebufferObject;
}
std::pair<lcFramebuffer, lcFramebuffer> lcContext::CreateRenderFramebuffer(int Width, int Height)
{
if (gSupportsFramebufferObjectARB && QGLFormat::defaultFormat().sampleBuffers() && QGLFormat::defaultFormat().samples() > 1)
return std::make_pair(CreateFramebuffer(Width, Height, true, true), CreateFramebuffer(Width, Height, false, false));
else
return std::make_pair(CreateFramebuffer(Width, Height, true, false), lcFramebuffer());
}
void lcContext::DestroyRenderFramebuffer(std::pair<lcFramebuffer, lcFramebuffer>& RenderFramebuffer)
{
DestroyFramebuffer(RenderFramebuffer.first);
DestroyFramebuffer(RenderFramebuffer.second);
}
QImage lcContext::GetRenderFramebufferImage(const std::pair<lcFramebuffer, lcFramebuffer>& RenderFramebuffer)
{
QImage Image(RenderFramebuffer.first.mWidth, RenderFramebuffer.first.mHeight, QImage::Format_ARGB32);
GetRenderFramebufferImage(RenderFramebuffer, Image.bits());
2017-12-26 19:19:20 +01:00
return Image;
}
void lcContext::GetRenderFramebufferImage(const std::pair<lcFramebuffer, lcFramebuffer>& RenderFramebuffer, quint8* Buffer)
2017-12-26 19:19:20 +01:00
{
const int Width = RenderFramebuffer.first.mWidth;
const int Height = RenderFramebuffer.first.mHeight;
2020-03-23 04:18:52 +01:00
const GLuint SavedFramebuffer = mFramebufferObject;
2017-12-26 19:19:20 +01:00
if (RenderFramebuffer.second.IsValid())
{
2017-12-30 21:04:12 +01:00
#ifndef LC_OPENGLES
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, RenderFramebuffer.second.mObject);
glBindFramebuffer(GL_READ_FRAMEBUFFER, RenderFramebuffer.first.mObject);
2017-12-30 21:12:27 +01:00
glBlitFramebuffer(0, 0, Width, Height, 0, 0, Width, Height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
BindFramebuffer(RenderFramebuffer.second);
2017-12-30 21:04:12 +01:00
#endif
2017-12-26 19:19:20 +01:00
}
else
BindFramebuffer(RenderFramebuffer.first);
2016-10-05 23:28:52 +02:00
glFinish();
glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, Buffer);
BindFramebuffer(SavedFramebuffer);
2017-12-26 19:19:20 +01:00
2016-10-05 23:28:52 +02:00
for (int y = 0; y < (Height + 1) / 2; y++)
{
quint8* Top = Buffer + ((Height - y - 1) * Width * 4);
quint8* Bottom = Buffer + y * Width * 4;
2016-10-05 23:28:52 +02:00
for (int x = 0; x < Width; x++)
{
2017-12-26 19:19:20 +01:00
QRgb TopColor = qRgba(Top[0], Top[1], Top[2], Top[3]);
QRgb BottomColor = qRgba(Bottom[0], Bottom[1], Bottom[2], Bottom[3]);
2016-10-05 23:28:52 +02:00
2017-12-26 19:19:20 +01:00
*(QRgb*)Top = BottomColor;
*(QRgb*)Bottom = TopColor;
2016-10-05 23:28:52 +02:00
Top += 4;
Bottom += 4;
2016-10-05 23:28:52 +02:00
}
}
}
2016-10-05 23:28:52 +02:00
lcVertexBuffer lcContext::CreateVertexBuffer(int Size, const void* Data)
{
lcVertexBuffer VertexBuffer;
if (gSupportsVertexBufferObject)
{
glGenBuffers(1, &VertexBuffer.Object);
glBindBuffer(GL_ARRAY_BUFFER_ARB, VertexBuffer.Object);
glBufferData(GL_ARRAY_BUFFER_ARB, Size, Data, GL_STATIC_DRAW_ARB);
glBindBuffer(GL_ARRAY_BUFFER_ARB, 0); // context remove
mVertexBufferObject = 0;
}
else
{
VertexBuffer.Pointer = malloc(Size);
2017-04-03 02:15:09 +02:00
if (VertexBuffer.Pointer)
memcpy(VertexBuffer.Pointer, Data, Size);
2016-10-05 23:28:52 +02:00
}
return VertexBuffer;
}
void lcContext::DestroyVertexBuffer(lcVertexBuffer& VertexBuffer)
{
if (!VertexBuffer.IsValid())
return;
if (gSupportsVertexBufferObject)
{
if (mVertexBufferObject == VertexBuffer.Object)
{
glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
mVertexBufferObject = 0;
}
glDeleteBuffers(1, &VertexBuffer.Object);
}
else
{
free(VertexBuffer.Pointer);
}
VertexBuffer.Pointer = nullptr;
2016-10-05 23:28:52 +02:00
}
lcIndexBuffer lcContext::CreateIndexBuffer(int Size, const void* Data)
{
lcIndexBuffer IndexBuffer;
if (gSupportsVertexBufferObject)
{
glGenBuffers(1, &IndexBuffer.Object);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, IndexBuffer.Object);
glBufferData(GL_ELEMENT_ARRAY_BUFFER_ARB, Size, Data, GL_STATIC_DRAW_ARB);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); // context remove
mIndexBufferObject = 0;
}
else
{
IndexBuffer.Pointer = malloc(Size);
2017-04-03 02:15:09 +02:00
if (IndexBuffer.Pointer)
memcpy(IndexBuffer.Pointer, Data, Size);
2016-10-05 23:28:52 +02:00
}
return IndexBuffer;
}
void lcContext::DestroyIndexBuffer(lcIndexBuffer& IndexBuffer)
{
if (!IndexBuffer.IsValid())
return;
if (gSupportsVertexBufferObject)
{
if (mIndexBufferObject == IndexBuffer.Object)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
mIndexBufferObject = 0;
}
glDeleteBuffers(1, &IndexBuffer.Object);
}
else
{
free(IndexBuffer.Pointer);
}
IndexBuffer.Pointer = nullptr;
2016-10-05 23:28:52 +02:00
}
void lcContext::ClearVertexBuffer()
{
mVertexBufferPointer = nullptr;
2016-10-05 23:28:52 +02:00
mVertexBufferOffset = (char*)~0;
if (mVertexBufferObject)
{
glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
mVertexBufferObject = 0;
}
2017-03-25 20:29:28 +01:00
if (gSupportsShaderObjects)
{
if (mNormalEnabled)
glDisableVertexAttribArray(LC_ATTRIB_NORMAL);
2017-02-18 20:12:35 +01:00
2017-03-25 20:29:28 +01:00
if (mTexCoordEnabled)
glDisableVertexAttribArray(LC_ATTRIB_TEXCOORD);
2016-10-05 23:28:52 +02:00
2017-03-25 20:29:28 +01:00
if (mColorEnabled)
glDisableVertexAttribArray(LC_ATTRIB_COLOR);
glVertexAttribPointer(LC_ATTRIB_POSITION, 3, GL_FLOAT, false, 0, nullptr);
glVertexAttribPointer(LC_ATTRIB_NORMAL, 4, GL_FLOAT, false, 0, nullptr);
glVertexAttribPointer(LC_ATTRIB_TEXCOORD, 2, GL_FLOAT, false, 0, nullptr);
glVertexAttribPointer(LC_ATTRIB_COLOR, 4, GL_FLOAT, false, 0, nullptr);
2017-03-25 20:29:28 +01:00
}
else
{
2017-12-07 07:08:56 +01:00
#ifndef LC_OPENGLES
2017-03-25 20:29:28 +01:00
if (mNormalEnabled)
glDisableClientState(GL_NORMAL_ARRAY);
if (mTexCoordEnabled)
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if (mColorEnabled)
glDisableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, nullptr);
glNormalPointer(GL_BYTE, 0, nullptr);
glTexCoordPointer(2, GL_FLOAT, 0, nullptr);
glColorPointer(4, GL_FLOAT, 0, nullptr);
2017-12-07 07:08:56 +01:00
#endif
2017-03-25 20:29:28 +01:00
}
2016-10-05 23:28:52 +02:00
}
void lcContext::SetVertexBuffer(lcVertexBuffer VertexBuffer)
{
if (gSupportsVertexBufferObject)
{
2020-03-23 04:18:52 +01:00
const GLuint VertexBufferObject = VertexBuffer.Object;
mVertexBufferPointer = nullptr;
2016-10-05 23:28:52 +02:00
if (VertexBufferObject != mVertexBufferObject)
{
glBindBuffer(GL_ARRAY_BUFFER_ARB, VertexBufferObject);
mVertexBufferObject = VertexBufferObject;
mVertexBufferOffset = (char*)~0;
}
}
else
{
mVertexBufferPointer = (char*)VertexBuffer.Pointer;
mVertexBufferOffset = (char*)~0;
}
}
void lcContext::SetVertexBufferPointer(const void* VertexBuffer)
{
if (gSupportsVertexBufferObject && mVertexBufferObject)
{
glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
mVertexBufferObject = 0;
}
mVertexBufferPointer = (char*)VertexBuffer;
mVertexBufferOffset = (char*)~0;
}
2017-03-24 17:34:53 +01:00
void lcContext::SetVertexFormatPosition(int PositionSize)
2016-10-05 23:28:52 +02:00
{
2020-03-23 04:18:52 +01:00
const int VertexSize = PositionSize * sizeof(float);
2017-03-24 17:34:53 +01:00
char* VertexBufferPointer = mVertexBufferPointer;
2016-10-05 23:28:52 +02:00
2017-03-24 17:34:53 +01:00
if (gSupportsShaderObjects)
2016-10-05 23:28:52 +02:00
{
2017-03-24 17:34:53 +01:00
if (mVertexBufferOffset != mVertexBufferPointer)
{
2016-10-05 23:28:52 +02:00
glVertexAttribPointer(LC_ATTRIB_POSITION, PositionSize, GL_FLOAT, false, VertexSize, VertexBufferPointer);
2017-03-24 17:34:53 +01:00
mVertexBufferOffset = VertexBufferPointer;
}
if (mNormalEnabled)
{
glDisableVertexAttribArray(LC_ATTRIB_NORMAL);
mNormalEnabled = false;
}
if (mTexCoordEnabled)
{
glDisableVertexAttribArray(LC_ATTRIB_TEXCOORD);
mTexCoordEnabled = false;
}
if (mColorEnabled)
{
glDisableVertexAttribArray(LC_ATTRIB_COLOR);
mColorEnabled = false;
}
}
else
{
if (mVertexBufferOffset != mVertexBufferPointer)
{
2016-10-05 23:28:52 +02:00
glVertexPointer(PositionSize, GL_FLOAT, VertexSize, VertexBufferPointer);
2017-03-24 17:34:53 +01:00
mVertexBufferOffset = VertexBufferPointer;
}
if (mNormalEnabled)
{
glDisableClientState(GL_NORMAL_ARRAY);
mNormalEnabled = false;
}
if (mTexCoordEnabled)
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
mTexCoordEnabled = false;
}
2016-10-05 23:28:52 +02:00
2017-03-24 17:34:53 +01:00
if (mColorEnabled)
{
glDisableClientState(GL_COLOR_ARRAY);
mColorEnabled = false;
}
2016-10-05 23:28:52 +02:00
}
2017-03-24 17:34:53 +01:00
}
2016-10-05 23:28:52 +02:00
2017-03-24 17:34:53 +01:00
void lcContext::SetVertexFormat(int BufferOffset, int PositionSize, int NormalSize, int TexCoordSize, int ColorSize, bool EnableNormals)
{
2020-03-23 04:18:52 +01:00
const int VertexSize = (PositionSize + TexCoordSize + ColorSize) * sizeof(float) + NormalSize * sizeof(quint32);
2017-03-24 17:34:53 +01:00
char* VertexBufferPointer = mVertexBufferPointer + BufferOffset;
2017-02-18 20:12:35 +01:00
2017-03-24 17:34:53 +01:00
if (gSupportsShaderObjects)
2017-02-18 20:12:35 +01:00
{
2017-03-24 17:34:53 +01:00
if (mVertexBufferOffset != VertexBufferPointer)
{
glVertexAttribPointer(LC_ATTRIB_POSITION, PositionSize, GL_FLOAT, false, VertexSize, VertexBufferPointer);
mVertexBufferOffset = VertexBufferPointer;
}
int Offset = PositionSize * sizeof(float);
if (NormalSize && EnableNormals)
2017-02-18 20:12:35 +01:00
{
glVertexAttribPointer(LC_ATTRIB_NORMAL, 4, GL_BYTE, true, VertexSize, VertexBufferPointer + Offset);
2017-02-18 20:12:35 +01:00
if (!mNormalEnabled)
{
glEnableVertexAttribArray(LC_ATTRIB_NORMAL);
mNormalEnabled = true;
}
}
2017-03-24 17:34:53 +01:00
else if (mNormalEnabled)
2017-02-18 20:12:35 +01:00
{
glDisableClientState(GL_NORMAL_ARRAY);
2017-03-24 17:34:53 +01:00
mNormalEnabled = false;
}
2017-02-18 20:12:35 +01:00
2017-03-24 17:34:53 +01:00
Offset += NormalSize * sizeof(quint32);
2017-02-18 20:12:35 +01:00
2017-03-24 17:34:53 +01:00
if (TexCoordSize)
2016-10-05 23:28:52 +02:00
{
2017-02-18 20:12:35 +01:00
glVertexAttribPointer(LC_ATTRIB_TEXCOORD, TexCoordSize, GL_FLOAT, false, VertexSize, VertexBufferPointer + Offset);
2016-10-05 23:28:52 +02:00
if (!mTexCoordEnabled)
{
glEnableVertexAttribArray(LC_ATTRIB_TEXCOORD);
mTexCoordEnabled = true;
}
2017-03-24 17:34:53 +01:00
Offset += 2 * sizeof(float);
2016-10-05 23:28:52 +02:00
}
2017-03-24 17:34:53 +01:00
else if (mTexCoordEnabled)
2016-10-05 23:28:52 +02:00
{
2017-03-24 17:34:53 +01:00
glDisableVertexAttribArray(LC_ATTRIB_TEXCOORD);
mTexCoordEnabled = false;
}
2016-10-05 23:28:52 +02:00
2017-03-24 17:34:53 +01:00
if (ColorSize)
{
glVertexAttribPointer(LC_ATTRIB_COLOR, ColorSize, GL_FLOAT, false, VertexSize, VertexBufferPointer + Offset);
if (!mColorEnabled)
2016-10-05 23:28:52 +02:00
{
2017-03-24 17:34:53 +01:00
glEnableVertexAttribArray(LC_ATTRIB_COLOR);
mColorEnabled = true;
2016-10-05 23:28:52 +02:00
}
}
2017-03-24 17:34:53 +01:00
else if (mColorEnabled)
{
glDisableVertexAttribArray(LC_ATTRIB_COLOR);
mColorEnabled = false;
}
2016-10-05 23:28:52 +02:00
}
2017-03-24 17:34:53 +01:00
else
2016-10-05 23:28:52 +02:00
{
2017-12-07 07:08:56 +01:00
#ifndef LC_OPENGLES
2017-03-24 17:34:53 +01:00
if (mVertexBufferOffset != VertexBufferPointer)
{
glVertexPointer(PositionSize, GL_FLOAT, VertexSize, VertexBufferPointer);
mVertexBufferOffset = VertexBufferPointer;
}
2016-10-05 23:28:52 +02:00
2017-03-24 17:34:53 +01:00
int Offset = PositionSize * sizeof(float);
if (NormalSize && EnableNormals)
2016-10-05 23:28:52 +02:00
{
2017-03-24 17:34:53 +01:00
glNormalPointer(GL_BYTE, VertexSize, VertexBufferPointer + Offset);
2016-10-05 23:28:52 +02:00
2017-03-24 17:34:53 +01:00
if (!mNormalEnabled)
2016-10-05 23:28:52 +02:00
{
2017-03-24 17:34:53 +01:00
glEnableClientState(GL_NORMAL_ARRAY);
mNormalEnabled = true;
2016-10-05 23:28:52 +02:00
}
}
2017-03-24 17:34:53 +01:00
else if (mNormalEnabled)
{
glDisableClientState(GL_NORMAL_ARRAY);
mNormalEnabled = false;
}
Offset += NormalSize * sizeof(quint32);
if (TexCoordSize)
{
glTexCoordPointer(TexCoordSize, GL_FLOAT, VertexSize, VertexBufferPointer + Offset);
if (!mTexCoordEnabled)
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
mTexCoordEnabled = true;
}
Offset += 2 * sizeof(float);
}
else if (mTexCoordEnabled)
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
mTexCoordEnabled = false;
}
if (ColorSize)
2016-10-05 23:28:52 +02:00
{
2017-02-18 20:12:35 +01:00
glColorPointer(ColorSize, GL_FLOAT, VertexSize, VertexBufferPointer + Offset);
2016-10-05 23:28:52 +02:00
if (!mColorEnabled)
{
glEnableClientState(GL_COLOR_ARRAY);
mColorEnabled = true;
}
}
2017-03-24 17:34:53 +01:00
else if (mColorEnabled)
{
2016-10-05 23:28:52 +02:00
glDisableClientState(GL_COLOR_ARRAY);
2017-03-24 17:34:53 +01:00
mColorEnabled = false;
}
2017-12-07 07:08:56 +01:00
#endif
2016-10-05 23:28:52 +02:00
}
}
void lcContext::ClearIndexBuffer()
{
if (mIndexBufferObject)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
mIndexBufferObject = 0;
}
}
void lcContext::SetIndexBuffer(lcIndexBuffer IndexBuffer)
{
if (gSupportsVertexBufferObject)
{
2020-03-23 04:18:52 +01:00
const GLuint IndexBufferObject = IndexBuffer.Object;
mIndexBufferPointer = nullptr;
2016-10-05 23:28:52 +02:00
if (IndexBufferObject != mIndexBufferObject)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, IndexBufferObject);
mIndexBufferObject = IndexBufferObject;
}
}
else
{
mIndexBufferPointer = (char*)IndexBuffer.Pointer;
}
}
void lcContext::SetIndexBufferPointer(const void* IndexBuffer)
{
if (mIndexBufferObject)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
mIndexBufferObject = 0;
}
mIndexBufferPointer = (char*)IndexBuffer;
}
2017-04-02 01:53:54 +02:00
void lcContext::BindMesh(const lcMesh* Mesh)
2016-10-05 23:28:52 +02:00
{
2020-03-23 04:18:52 +01:00
const lcPiecesLibrary* const Library = lcGetPiecesLibrary();
2016-10-05 23:28:52 +02:00
if (Mesh->mVertexCacheOffset != -1)
{
2020-03-23 04:18:52 +01:00
const GLuint VertexBufferObject = Library->mVertexBuffer.Object;
const GLuint IndexBufferObject = Library->mIndexBuffer.Object;
2016-10-05 23:28:52 +02:00
if (VertexBufferObject != mVertexBufferObject)
{
glBindBuffer(GL_ARRAY_BUFFER_ARB, VertexBufferObject);
mVertexBufferObject = VertexBufferObject;
mVertexBufferPointer = nullptr;
2016-10-05 23:28:52 +02:00
mVertexBufferOffset = (char*)~0;
}
if (IndexBufferObject != mIndexBufferObject)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, IndexBufferObject);
mIndexBufferObject = IndexBufferObject;
mIndexBufferPointer = nullptr;
2016-10-05 23:28:52 +02:00
}
}
else
{
if (mVertexBufferObject)
{
glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
mVertexBufferObject = 0;
}
if (mIndexBufferObject)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
mIndexBufferObject = 0;
}
mVertexBufferPointer = (char*)Mesh->mVertexData;
mIndexBufferPointer = (char*)Mesh->mIndexData;
mVertexBufferOffset = (char*)~0;
}
}
void lcContext::FlushState()
{
if (gSupportsShaderObjects)
{
2020-03-22 21:44:20 +01:00
const lcProgram& Program = mPrograms[static_cast<int>(mMaterialType)];
2016-10-05 23:28:52 +02:00
if (mWorldMatrixDirty || mViewMatrixDirty || mProjectionMatrixDirty)
{
if (mViewProjectionMatrixDirty)
{
mViewProjectionMatrix = lcMul(mViewMatrix, mProjectionMatrix);
mViewProjectionMatrixDirty = false;
}
2017-03-12 01:47:21 +01:00
if (mWorldMatrixDirty)
{
2017-03-12 01:47:21 +01:00
if (Program.WorldMatrixLocation != -1)
glUniformMatrix4fv(Program.WorldMatrixLocation, 1, false, mWorldMatrix);
}
if (mViewMatrixDirty)
{
2020-03-23 04:18:52 +01:00
const lcMatrix44 InverseViewMatrix = lcMatrix44AffineInverse(mViewMatrix);
2017-03-12 01:47:21 +01:00
lcVector3 ViewPosition = lcMul30(-mViewMatrix.GetTranslation(), InverseViewMatrix);
if (Program.LightPositionLocation != -1)
{
2017-03-12 01:47:21 +01:00
lcVector3 LightPosition = ViewPosition + lcMul30(lcVector3(300.0f, 300.0f, 0.0f), InverseViewMatrix);
glUniform3fv(Program.LightPositionLocation, 1, LightPosition);
}
if (Program.EyePositionLocation != -1)
glUniform3fv(Program.EyePositionLocation, 1, ViewPosition);
}
2017-03-12 01:47:21 +01:00
glUniformMatrix4fv(Program.WorldViewProjectionMatrixLocation, 1, false, lcMul(mWorldMatrix, mViewProjectionMatrix));
2016-10-05 23:28:52 +02:00
mWorldMatrixDirty = false;
mViewMatrixDirty = false;
mProjectionMatrixDirty = false;
}
2017-03-12 01:47:21 +01:00
if (mColorDirty && Program.MaterialColorLocation != -1)
2016-10-05 23:28:52 +02:00
{
2017-03-12 01:47:21 +01:00
glUniform4fv(Program.MaterialColorLocation, 1, mColor);
2016-10-05 23:28:52 +02:00
mColorDirty = false;
}
2018-10-29 01:59:01 +01:00
2019-01-13 02:43:23 +01:00
if (mHighlightParamsDirty && Program.HighlightParamsLocation != -1)
2018-10-29 01:59:01 +01:00
{
lcMatrix44 InverseViewMatrix = lcMatrix44AffineInverse(mViewMatrix);
mHighlightParams[4] = InverseViewMatrix[2];
glUniform4fv(Program.HighlightParamsLocation, 5, mHighlightParams[0]);
2019-01-13 02:43:23 +01:00
mHighlightParamsDirty = false;
2018-10-29 01:59:01 +01:00
}
2016-10-05 23:28:52 +02:00
}
else
{
2017-02-11 21:41:00 +01:00
#ifndef LC_OPENGLES
2016-10-05 23:28:52 +02:00
glColor4fv(mColor);
if (mWorldMatrixDirty || mViewMatrixDirty)
{
if (mMatrixMode != GL_MODELVIEW)
{
glMatrixMode(GL_MODELVIEW);
mMatrixMode = GL_MODELVIEW;
}
glLoadMatrixf(lcMul(mWorldMatrix, mViewMatrix));
mWorldMatrixDirty = false;
mViewMatrixDirty = false;
}
if (mProjectionMatrixDirty)
{
if (mMatrixMode != GL_PROJECTION)
{
glMatrixMode(GL_PROJECTION);
mMatrixMode = GL_PROJECTION;
}
glLoadMatrixf(mProjectionMatrix);
mProjectionMatrixDirty = false;
}
2017-02-11 21:41:00 +01:00
#endif
2016-10-05 23:28:52 +02:00
}
}
void lcContext::DrawPrimitives(GLenum Mode, GLint First, GLsizei Count)
{
FlushState();
glDrawArrays(Mode, First, Count);
}
void lcContext::DrawIndexedPrimitives(GLenum Mode, GLsizei Count, GLenum Type, int Offset)
{
FlushState();
glDrawElements(Mode, Count, Type, mIndexBufferPointer + Offset);
}