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
|
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
lcProgram lcContext::mPrograms[LC_NUM_MATERIALS];
|
2016-10-05 23:28:52 +02:00
|
|
|
|
|
|
|
lcContext::lcContext()
|
|
|
|
{
|
|
|
|
mVertexBufferObject = 0;
|
|
|
|
mIndexBufferObject = 0;
|
2017-04-14 02:26:40 +02:00
|
|
|
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;
|
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();
|
2018-10-29 01:59:01 +01:00
|
|
|
mHighlightColor = 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;
|
2018-10-29 01:59:01 +01:00
|
|
|
mHighlightColorDirty = false;
|
2016-10-05 23:28:52 +02:00
|
|
|
|
2017-03-01 00:20:34 +01:00
|
|
|
mMaterialType = LC_NUM_MATERIALS;
|
2016-10-05 23:28:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
lcContext::~lcContext()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void lcContext::CreateShaderPrograms()
|
|
|
|
{
|
2017-02-11 21:41:00 +01:00
|
|
|
#ifndef LC_OPENGLES
|
2017-02-11 21:43:47 +01:00
|
|
|
#define LC_SHADER_VERSION "#version 110\n#define mediump\n"
|
2017-02-11 21:41:00 +01:00
|
|
|
#define LC_VERTEX_INPUT "attribute "
|
|
|
|
#define LC_VERTEX_OUTPUT "varying "
|
|
|
|
#define LC_PIXEL_INPUT "varying "
|
|
|
|
#define LC_PIXEL_OUTPUT
|
2017-12-30 21:04:12 +01:00
|
|
|
#define LC_SHADER_PRECISION
|
2017-02-11 21:41:00 +01:00
|
|
|
#else
|
|
|
|
#define LC_SHADER_VERSION "#version 300 es\n#define texture2D texture\n"
|
|
|
|
#define LC_VERTEX_INPUT "in "
|
|
|
|
#define LC_VERTEX_OUTPUT "out "
|
|
|
|
#define LC_PIXEL_INPUT "in mediump "
|
|
|
|
#define LC_PIXEL_OUTPUT "#define gl_FragColor FragColor\nout mediump vec4 gl_FragColor;\n"
|
2017-12-30 21:04:12 +01:00
|
|
|
#define LC_SHADER_PRECISION "mediump "
|
2017-02-11 21:41:00 +01:00
|
|
|
#endif
|
2017-03-12 01:47:21 +01:00
|
|
|
#define LC_PIXEL_FAKE_LIGHTING \
|
2017-12-30 21:04:12 +01:00
|
|
|
LC_SHADER_PRECISION " vec3 Normal = normalize(PixelNormal);\n" \
|
|
|
|
LC_SHADER_PRECISION " vec3 LightDirection = normalize(PixelPosition - LightPosition);" \
|
|
|
|
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" \
|
2017-03-12 01:47:21 +01:00
|
|
|
" Specular = min(pow(Specular, 8.0), 1.0) * 0.25;\n" \
|
2017-12-30 21:04:12 +01:00
|
|
|
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
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
const char* VertexShaders[LC_NUM_MATERIALS] =
|
2016-10-05 23:28:52 +02:00
|
|
|
{
|
2017-03-12 21:51:14 +01:00
|
|
|
// LC_MATERIAL_UNLIT_COLOR
|
|
|
|
LC_SHADER_VERSION
|
|
|
|
LC_VERTEX_INPUT "vec3 VertexPosition;\n"
|
|
|
|
"uniform mat4 WorldViewProjectionMatrix;\n"
|
|
|
|
"void main()\n"
|
|
|
|
"{\n"
|
|
|
|
" gl_Position = WorldViewProjectionMatrix * vec4(VertexPosition, 1.0);\n"
|
|
|
|
"}\n",
|
|
|
|
// LC_MATERIAL_UNLIT_TEXTURE_MODULATE
|
|
|
|
LC_SHADER_VERSION
|
|
|
|
LC_VERTEX_INPUT "vec3 VertexPosition;\n"
|
|
|
|
LC_VERTEX_INPUT "vec2 VertexTexCoord;\n"
|
|
|
|
LC_VERTEX_OUTPUT "vec2 PixelTexCoord;\n"
|
|
|
|
"uniform mat4 WorldViewProjectionMatrix;\n"
|
|
|
|
"void main()\n"
|
|
|
|
"{\n"
|
|
|
|
" gl_Position = WorldViewProjectionMatrix * vec4(VertexPosition, 1.0);\n"
|
|
|
|
" PixelTexCoord = VertexTexCoord;\n"
|
|
|
|
"}\n",
|
|
|
|
// LC_MATERIAL_UNLIT_TEXTURE_DECAL
|
|
|
|
LC_SHADER_VERSION
|
|
|
|
LC_VERTEX_INPUT "vec3 VertexPosition;\n"
|
|
|
|
LC_VERTEX_INPUT "vec2 VertexTexCoord;\n"
|
|
|
|
LC_VERTEX_OUTPUT "vec2 PixelTexCoord;\n"
|
|
|
|
"uniform mat4 WorldViewProjectionMatrix;\n"
|
|
|
|
"void main()\n"
|
|
|
|
"{\n"
|
|
|
|
" gl_Position = WorldViewProjectionMatrix * vec4(VertexPosition, 1.0);\n"
|
|
|
|
" PixelTexCoord = VertexTexCoord;\n"
|
|
|
|
"}\n",
|
|
|
|
// LC_MATERIAL_UNLIT_VERTEX_COLOR
|
|
|
|
LC_SHADER_VERSION
|
|
|
|
LC_VERTEX_INPUT "vec3 VertexPosition;\n"
|
|
|
|
LC_VERTEX_INPUT "vec4 VertexColor;\n"
|
|
|
|
LC_VERTEX_OUTPUT "vec4 PixelColor;\n"
|
|
|
|
"uniform mat4 WorldViewProjectionMatrix;\n"
|
|
|
|
"void main()\n"
|
|
|
|
"{\n"
|
|
|
|
" gl_Position = WorldViewProjectionMatrix * vec4(VertexPosition, 1.0);\n"
|
|
|
|
" PixelColor = VertexColor;\n"
|
|
|
|
"}\n",
|
2018-10-29 01:59:01 +01:00
|
|
|
// LC_MATERIAL_UNLIT_VIEW_SPHERE
|
|
|
|
LC_SHADER_VERSION
|
|
|
|
LC_VERTEX_INPUT "vec3 VertexPosition;\n"
|
|
|
|
LC_VERTEX_OUTPUT "vec3 PixelNormal;\n"
|
|
|
|
"uniform mat4 WorldViewProjectionMatrix;\n"
|
|
|
|
"void main()\n"
|
|
|
|
"{\n"
|
|
|
|
" PixelNormal = normalize(VertexPosition);\n"
|
|
|
|
" gl_Position = WorldViewProjectionMatrix * vec4(VertexPosition, 1.0);\n"
|
|
|
|
"}\n",
|
2017-03-12 21:51:14 +01:00
|
|
|
// LC_MATERIAL_FAKELIT_COLOR
|
|
|
|
LC_SHADER_VERSION
|
|
|
|
LC_VERTEX_INPUT "vec3 VertexPosition;\n"
|
|
|
|
LC_VERTEX_INPUT "vec3 VertexNormal;\n"
|
|
|
|
LC_VERTEX_OUTPUT "vec3 PixelPosition;\n"
|
|
|
|
LC_VERTEX_OUTPUT "vec3 PixelNormal;\n"
|
|
|
|
"uniform mat4 WorldViewProjectionMatrix;\n"
|
|
|
|
"uniform mat4 WorldMatrix;\n"
|
|
|
|
"void main()\n"
|
|
|
|
"{\n"
|
|
|
|
" PixelPosition = (WorldMatrix * vec4(VertexPosition, 1.0)).xyz;\n"
|
|
|
|
" PixelNormal = (WorldMatrix * vec4(VertexNormal, 0.0)).xyz;\n"
|
|
|
|
" gl_Position = WorldViewProjectionMatrix * vec4(VertexPosition, 1.0);\n"
|
|
|
|
"}\n",
|
|
|
|
// LC_MATERIAL_FAKELIT_TEXTURE_DECAL
|
|
|
|
LC_SHADER_VERSION
|
|
|
|
LC_VERTEX_INPUT "vec3 VertexPosition;\n"
|
|
|
|
LC_VERTEX_INPUT "vec3 VertexNormal;\n"
|
|
|
|
LC_VERTEX_INPUT "vec2 VertexTexCoord;\n"
|
|
|
|
LC_VERTEX_OUTPUT "vec3 PixelPosition;\n"
|
|
|
|
LC_VERTEX_OUTPUT "vec3 PixelNormal;\n"
|
|
|
|
LC_VERTEX_OUTPUT "vec2 PixelTexCoord;\n"
|
|
|
|
"uniform mat4 WorldViewProjectionMatrix;\n"
|
|
|
|
"uniform mat4 WorldMatrix;\n"
|
|
|
|
"void main()\n"
|
|
|
|
"{\n"
|
|
|
|
" PixelPosition = (WorldMatrix * vec4(VertexPosition, 1.0)).xyz;\n"
|
|
|
|
" PixelNormal = (WorldMatrix * vec4(VertexNormal, 0.0)).xyz;\n"
|
|
|
|
" gl_Position = WorldViewProjectionMatrix * vec4(VertexPosition, 1.0);\n"
|
|
|
|
" PixelTexCoord = VertexTexCoord;\n"
|
|
|
|
"}\n"
|
2016-10-05 23:28:52 +02:00
|
|
|
};
|
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
const char* FragmentShaders[LC_NUM_MATERIALS] =
|
2016-10-05 23:28:52 +02:00
|
|
|
{
|
2017-03-12 21:51:14 +01:00
|
|
|
// LC_MATERIAL_UNLIT_COLOR
|
|
|
|
LC_SHADER_VERSION
|
|
|
|
LC_PIXEL_OUTPUT
|
|
|
|
"uniform mediump vec4 MaterialColor;\n"
|
|
|
|
"void main()\n"
|
|
|
|
"{\n"
|
|
|
|
" gl_FragColor = MaterialColor;\n"
|
|
|
|
"}\n",
|
|
|
|
// LC_MATERIAL_UNLIT_TEXTURE_MODULATE
|
|
|
|
LC_SHADER_VERSION
|
|
|
|
LC_PIXEL_INPUT "vec2 PixelTexCoord;\n"
|
|
|
|
LC_PIXEL_OUTPUT
|
|
|
|
"uniform mediump vec4 MaterialColor;\n"
|
|
|
|
"uniform sampler2D Texture;\n"
|
|
|
|
"void main()\n"
|
|
|
|
"{\n"
|
2018-10-29 01:59:01 +01:00
|
|
|
LC_SHADER_PRECISION " vec4 TexelColor = texture2D(Texture, PixelTexCoord);\n"
|
2017-03-12 21:51:14 +01:00
|
|
|
" gl_FragColor = vec4(MaterialColor.rgb, TexelColor.a * MaterialColor.a);\n"
|
|
|
|
"}\n",
|
|
|
|
// LC_MATERIAL_UNLIT_TEXTURE_DECAL
|
|
|
|
LC_SHADER_VERSION
|
|
|
|
LC_PIXEL_INPUT "vec2 PixelTexCoord;\n"
|
|
|
|
LC_PIXEL_OUTPUT
|
|
|
|
"uniform mediump vec4 MaterialColor;\n"
|
|
|
|
"uniform sampler2D Texture;\n"
|
|
|
|
"void main()\n"
|
|
|
|
"{\n"
|
2018-10-29 01:59:01 +01:00
|
|
|
LC_SHADER_PRECISION " vec4 TexelColor = texture2D(Texture, PixelTexCoord);\n"
|
2018-01-13 06:44:49 +01:00
|
|
|
" gl_FragColor = mix(MaterialColor, TexelColor, TexelColor.a);\n"
|
2017-03-12 21:51:14 +01:00
|
|
|
"}\n",
|
|
|
|
// LC_MATERIAL_UNLIT_VERTEX_COLOR
|
|
|
|
LC_SHADER_VERSION
|
|
|
|
LC_PIXEL_INPUT "vec4 PixelColor;\n"
|
|
|
|
LC_PIXEL_OUTPUT
|
|
|
|
"void main()\n"
|
|
|
|
"{\n"
|
|
|
|
" gl_FragColor = PixelColor;\n"
|
|
|
|
"}\n",
|
2018-10-29 01:59:01 +01:00
|
|
|
// LC_MATERIAL_UNLIT_VIEW_SPHERE
|
|
|
|
LC_SHADER_VERSION
|
|
|
|
LC_PIXEL_INPUT "vec3 PixelNormal;\n"
|
|
|
|
LC_PIXEL_OUTPUT
|
|
|
|
"uniform mediump vec4 MaterialColor;\n"
|
|
|
|
"uniform mediump vec4 HighlightColor;\n"
|
|
|
|
"uniform samplerCube Texture;\n"
|
|
|
|
"void main()\n"
|
|
|
|
"{\n"
|
|
|
|
" float TexelAlpha = textureCube(Texture, PixelNormal).a;\n"
|
|
|
|
" gl_FragColor = mix(MaterialColor, HighlightColor, TexelAlpha);\n"
|
|
|
|
"}\n",
|
2017-03-12 21:51:14 +01:00
|
|
|
// LC_MATERIAL_FAKELIT_COLOR
|
|
|
|
LC_SHADER_VERSION
|
|
|
|
LC_PIXEL_INPUT "vec3 PixelPosition;\n"
|
|
|
|
LC_PIXEL_INPUT "vec3 PixelNormal;\n"
|
|
|
|
LC_PIXEL_OUTPUT
|
|
|
|
"uniform mediump vec4 MaterialColor;\n"
|
|
|
|
"uniform mediump vec3 LightPosition;\n"
|
|
|
|
"uniform mediump vec3 EyePosition;\n"
|
|
|
|
"void main()\n"
|
|
|
|
"{\n"
|
|
|
|
LC_PIXEL_FAKE_LIGHTING
|
2017-12-30 21:04:12 +01:00
|
|
|
LC_SHADER_PRECISION " vec3 DiffuseColor = MaterialColor.rgb * Diffuse;\n"
|
2017-03-12 21:51:14 +01:00
|
|
|
" gl_FragColor = vec4(DiffuseColor + SpecularColor, MaterialColor.a);\n"
|
|
|
|
"}\n",
|
|
|
|
// LC_MATERIAL_FAKELIT_TEXTURE_DECAL
|
|
|
|
LC_SHADER_VERSION
|
|
|
|
LC_PIXEL_INPUT "vec3 PixelPosition;\n"
|
|
|
|
LC_PIXEL_INPUT "vec3 PixelNormal;\n"
|
|
|
|
LC_PIXEL_INPUT "vec2 PixelTexCoord;\n"
|
|
|
|
LC_PIXEL_OUTPUT
|
|
|
|
"uniform mediump vec4 MaterialColor;\n"
|
|
|
|
"uniform mediump vec3 LightPosition;\n"
|
|
|
|
"uniform mediump vec3 EyePosition;\n"
|
|
|
|
"uniform sampler2D Texture;\n"
|
|
|
|
"void main()\n"
|
|
|
|
"{\n"
|
|
|
|
LC_PIXEL_FAKE_LIGHTING
|
2017-12-30 21:04:12 +01:00
|
|
|
LC_SHADER_PRECISION " vec4 TexelColor = texture2D(Texture, PixelTexCoord);"
|
2018-01-13 06:44:49 +01:00
|
|
|
LC_SHADER_PRECISION " vec4 DiffuseColor = mix(MaterialColor, TexelColor, TexelColor.a);\n"
|
|
|
|
" gl_FragColor = vec4(vec3(DiffuseColor) * Diffuse + SpecularColor, DiffuseColor.a);\n"
|
2017-03-12 21:51:14 +01:00
|
|
|
"}\n"
|
2016-10-05 23:28:52 +02:00
|
|
|
};
|
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
for (int MaterialType = 0; MaterialType < LC_NUM_MATERIALS; MaterialType++)
|
2016-10-05 23:28:52 +02:00
|
|
|
{
|
2017-03-12 21:51:14 +01:00
|
|
|
GLuint VertexShader = glCreateShader(GL_VERTEX_SHADER);
|
2017-04-14 02:26:40 +02:00
|
|
|
glShaderSource(VertexShader, 1, &VertexShaders[MaterialType], nullptr);
|
2017-03-12 21:51:14 +01:00
|
|
|
glCompileShader(VertexShader);
|
2016-10-05 23:28:52 +02:00
|
|
|
|
|
|
|
#ifndef QT_NO_DEBUG
|
2017-03-12 21:51:14 +01:00
|
|
|
GLint VertexShaderCompiled = 0;
|
|
|
|
glGetShaderiv(VertexShader, GL_COMPILE_STATUS, &VertexShaderCompiled);
|
2016-10-05 23:28:52 +02:00
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
if (VertexShaderCompiled == GL_FALSE)
|
|
|
|
{
|
|
|
|
GLint Length = 0;
|
|
|
|
glGetShaderiv(VertexShader, GL_INFO_LOG_LENGTH, &Length);
|
2016-10-05 23:28:52 +02:00
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
QByteArray InfoLog;
|
|
|
|
InfoLog.resize(Length);
|
|
|
|
glGetShaderInfoLog(VertexShader, Length, &Length, InfoLog.data());
|
2016-10-05 23:28:52 +02:00
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
qDebug() << InfoLog;
|
|
|
|
}
|
2016-10-05 23:28:52 +02:00
|
|
|
#endif
|
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
GLuint FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
2017-04-14 02:26:40 +02:00
|
|
|
glShaderSource(FragmentShader, 1, &FragmentShaders[MaterialType], nullptr);
|
2017-03-12 21:51:14 +01:00
|
|
|
glCompileShader(FragmentShader);
|
2016-10-05 23:28:52 +02:00
|
|
|
|
|
|
|
#ifndef QT_NO_DEBUG
|
2017-03-12 21:51:14 +01:00
|
|
|
GLint FragmentShaderCompiled = 0;
|
|
|
|
glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, &FragmentShaderCompiled);
|
2016-10-05 23:28:52 +02:00
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
if (FragmentShaderCompiled == GL_FALSE)
|
|
|
|
{
|
|
|
|
GLint Length = 0;
|
|
|
|
glGetShaderiv(FragmentShader, GL_INFO_LOG_LENGTH, &Length);
|
2016-10-05 23:28:52 +02:00
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
QByteArray InfoLog;
|
|
|
|
InfoLog.resize(Length);
|
|
|
|
glGetShaderInfoLog(FragmentShader, Length, &Length, InfoLog.data());
|
2016-10-05 23:28:52 +02:00
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
qDebug() << InfoLog;
|
|
|
|
}
|
2016-10-05 23:28:52 +02:00
|
|
|
#endif
|
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
GLuint Program = glCreateProgram();
|
2016-10-05 23:28:52 +02:00
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
glAttachShader(Program, VertexShader);
|
|
|
|
glAttachShader(Program, FragmentShader);
|
2016-10-05 23:28:52 +02:00
|
|
|
|
2017-03-12 21:51:14 +01: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
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
glLinkProgram(Program);
|
2016-10-05 23:28:52 +02:00
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
glDetachShader(Program, VertexShader);
|
|
|
|
glDetachShader(Program, FragmentShader);
|
|
|
|
glDeleteShader(VertexShader);
|
|
|
|
glDeleteShader(FragmentShader);
|
2017-03-01 00:20:34 +01:00
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
GLint IsLinked = 0;
|
|
|
|
glGetProgramiv(Program, GL_LINK_STATUS, &IsLinked);
|
|
|
|
if (IsLinked == GL_FALSE)
|
|
|
|
{
|
|
|
|
GLint Length = 0;
|
|
|
|
glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &Length);
|
2017-03-01 00:20:34 +01:00
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
QByteArray InfoLog;
|
|
|
|
InfoLog.resize(Length);
|
|
|
|
glGetProgramInfoLog(Program, Length, &Length, InfoLog.data());
|
2016-10-05 23:28:52 +02:00
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
glDeleteProgram(Program);
|
|
|
|
Program = 0;
|
2017-03-01 00:20:34 +01:00
|
|
|
}
|
2017-03-12 21:51:14 +01:00
|
|
|
|
|
|
|
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");
|
2018-10-29 01:59:01 +01:00
|
|
|
mPrograms[MaterialType].HighlightColorLocation = glGetUniformLocation(Program, "HighlightColor");
|
2016-10-05 23:28:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void lcContext::CreateResources()
|
|
|
|
{
|
|
|
|
if (!gSupportsShaderObjects)
|
|
|
|
return;
|
|
|
|
|
|
|
|
CreateShaderPrograms();
|
|
|
|
}
|
|
|
|
|
|
|
|
void lcContext::DestroyResources()
|
|
|
|
{
|
|
|
|
if (!gSupportsShaderObjects)
|
|
|
|
return;
|
|
|
|
|
2017-03-12 21:51:14 +01:00
|
|
|
for (int MaterialType = 0; MaterialType < LC_NUM_MATERIALS; 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);
|
|
|
|
|
2018-07-04 20:19:15 +02:00
|
|
|
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
|
|
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
|
|
|
glPolygonOffset(0.5f, 0.1f);
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2017-04-14 02:26:40 +02:00
|
|
|
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;
|
2017-04-14 02:26:40 +02:00
|
|
|
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
|
2017-12-30 22:03:47 +01:00
|
|
|
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
|
|
|
|
|
|
|
glLineWidth(1.0f);
|
|
|
|
mLineWidth = 1.0f;
|
|
|
|
|
|
|
|
if (gSupportsShaderObjects)
|
|
|
|
{
|
|
|
|
glUseProgram(0);
|
2017-03-01 00:20:34 +01:00
|
|
|
mMaterialType = LC_NUM_MATERIALS;
|
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
|
|
|
}
|
|
|
|
|
2017-03-01 00:20:34 +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;
|
|
|
|
|
2017-03-01 00:20:34 +01:00
|
|
|
mMaterialType = MaterialType;
|
2017-03-25 02:36:58 +01:00
|
|
|
|
|
|
|
if (gSupportsShaderObjects)
|
|
|
|
{
|
|
|
|
glUseProgram(mPrograms[MaterialType].Object);
|
|
|
|
mColorDirty = true;
|
|
|
|
mWorldMatrixDirty = true; // todo: change dirty to a bitfield and set the lighting constants dirty here
|
|
|
|
mViewMatrixDirty = true;
|
2018-10-29 01:59:01 +01:00
|
|
|
mHighlightColorDirty = true;
|
2017-03-25 02:36:58 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#ifndef LC_OPENGLES
|
|
|
|
switch (MaterialType)
|
|
|
|
{
|
|
|
|
case LC_MATERIAL_UNLIT_TEXTURE_MODULATE:
|
|
|
|
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;
|
|
|
|
|
|
|
|
case LC_MATERIAL_FAKELIT_TEXTURE_DECAL:
|
|
|
|
case LC_MATERIAL_UNLIT_TEXTURE_DECAL:
|
|
|
|
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;
|
|
|
|
|
|
|
|
case LC_MATERIAL_UNLIT_COLOR:
|
|
|
|
case LC_MATERIAL_UNLIT_VERTEX_COLOR:
|
|
|
|
case LC_MATERIAL_FAKELIT_COLOR:
|
2017-03-25 20:29:28 +01:00
|
|
|
if (mTextureEnabled)
|
|
|
|
{
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
mTextureEnabled = false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2017-03-25 02:36:58 +01:00
|
|
|
case LC_NUM_MATERIALS:
|
|
|
|
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::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
|
2017-12-30 22:03:47 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2018-03-29 19:20:36 +02:00
|
|
|
void lcContext::SetColorIndexTinted(int ColorIndex, lcInterfaceColor InterfaceColor, float Weight)
|
2016-10-05 23:28:52 +02:00
|
|
|
{
|
2018-03-29 19:20:36 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
void lcContext::SetEdgeColorIndex(int ColorIndex)
|
|
|
|
{
|
|
|
|
SetColor(gColorList[ColorIndex].Edge);
|
|
|
|
}
|
|
|
|
|
|
|
|
void lcContext::SetInterfaceColor(lcInterfaceColor InterfaceColor)
|
|
|
|
{
|
|
|
|
SetColor(gInterfaceColors[InterfaceColor]);
|
|
|
|
}
|
|
|
|
|
2017-12-29 15:50:18 +01:00
|
|
|
void lcContext::ClearFramebuffer()
|
2016-10-05 23:28:52 +02:00
|
|
|
{
|
2017-12-29 15:50:18 +01:00
|
|
|
if (!mFramebufferObject)
|
|
|
|
return;
|
|
|
|
|
2016-10-05 23:28:52 +02:00
|
|
|
if (gSupportsFramebufferObjectARB)
|
2017-12-29 15:50:18 +01:00
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
|
|
#ifndef LC_OPENGLES
|
|
|
|
else if (gSupportsFramebufferObjectEXT)
|
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
|
|
#endif
|
2017-12-26 19:19:20 +01:00
|
|
|
|
2017-12-29 15:50:18 +01:00
|
|
|
mFramebufferObject = 0;
|
|
|
|
}
|
2017-12-26 19:19:20 +01:00
|
|
|
|
2017-12-29 15:50:18 +01:00
|
|
|
lcFramebuffer lcContext::CreateFramebuffer(int Width, int Height, bool Depth, bool Multisample)
|
|
|
|
{
|
|
|
|
lcFramebuffer Framebuffer(Width, Height);
|
|
|
|
|
|
|
|
if (gSupportsFramebufferObjectARB)
|
|
|
|
{
|
2018-02-25 03:22:53 +01:00
|
|
|
int Samples = (Multisample && gSupportsTexImage2DMultisample && QGLFormat::defaultFormat().sampleBuffers()) ? QGLFormat::defaultFormat().samples() : 1;
|
2017-12-29 15:50:18 +01:00
|
|
|
|
|
|
|
glGenFramebuffers(1, &Framebuffer.mObject);
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, Framebuffer.mObject);
|
2017-12-26 19:19:20 +01:00
|
|
|
|
2017-12-29 15:50:18 +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)
|
|
|
|
{
|
2017-12-29 15:50:18 +01:00
|
|
|
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
|
|
|
|
{
|
2017-12-29 15:50:18 +01:00
|
|
|
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);
|
2017-12-29 15:50:18 +01:00
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, Framebuffer.mColorTexture, 0);
|
2016-10-05 23:28:52 +02:00
|
|
|
|
2017-12-29 15:50:18 +01: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)
|
2017-12-29 15:50:18 +01:00
|
|
|
DestroyFramebuffer(Framebuffer);
|
2016-10-05 23:28:52 +02:00
|
|
|
|
2017-12-29 15:50:18 +01:00
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferObject);
|
2016-10-05 23:28:52 +02:00
|
|
|
}
|
2017-02-11 21:41:00 +01:00
|
|
|
#ifndef LC_OPENGLES
|
2017-12-29 15:50:18 +01:00
|
|
|
else if (gSupportsFramebufferObjectEXT)
|
2016-10-05 23:28:52 +02:00
|
|
|
{
|
2017-12-29 15:50:18 +01:00
|
|
|
glGenFramebuffersEXT(1, &Framebuffer.mObject);
|
|
|
|
glGenTextures(1, &Framebuffer.mColorTexture);
|
2016-10-05 23:28:52 +02:00
|
|
|
|
2017-12-29 15:50:18 +01:00
|
|
|
BindTexture2D(Framebuffer.mColorTexture);
|
2016-10-05 23:28:52 +02:00
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
2017-04-14 02:26:40 +02:00
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
2016-10-05 23:28:52 +02:00
|
|
|
|
2017-12-29 15:50:18 +01: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
|
|
|
|
2017-12-29 15:50:18 +01:00
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, Framebuffer.mObject);
|
2016-10-05 23:28:52 +02:00
|
|
|
|
2017-12-29 15:50:18 +01: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);
|
|
|
|
|
2017-12-29 15:50:18 +01:00
|
|
|
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);
|
2017-12-29 15:50:18 +01:00
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, Framebuffer.mObject);
|
2016-10-05 23:28:52 +02:00
|
|
|
|
|
|
|
if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
|
2017-12-29 15:50:18 +01:00
|
|
|
DestroyFramebuffer(Framebuffer);
|
2016-10-05 23:28:52 +02:00
|
|
|
|
2017-12-29 15:50:18 +01:00
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFramebufferObject);
|
2016-10-05 23:28:52 +02:00
|
|
|
}
|
2017-02-11 21:41:00 +01:00
|
|
|
#endif
|
2017-12-29 15:50:18 +01:00
|
|
|
|
|
|
|
return Framebuffer;
|
2016-10-05 23:28:52 +02:00
|
|
|
}
|
|
|
|
|
2017-12-29 15:50:18 +01:00
|
|
|
void lcContext::DestroyFramebuffer(lcFramebuffer& Framebuffer)
|
2016-10-05 23:28:52 +02:00
|
|
|
{
|
|
|
|
if (gSupportsFramebufferObjectARB)
|
|
|
|
{
|
2017-12-29 15:50:18 +01:00
|
|
|
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
|
2017-12-29 15:50:18 +01:00
|
|
|
else if (gSupportsFramebufferObjectEXT)
|
2016-10-05 23:28:52 +02:00
|
|
|
{
|
2017-12-29 15:50:18 +01: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
|
2017-12-29 15:50:18 +01:00
|
|
|
|
|
|
|
Framebuffer.mObject = 0;
|
|
|
|
Framebuffer.mColorTexture = 0;
|
|
|
|
Framebuffer.mDepthRenderbuffer = 0;
|
|
|
|
Framebuffer.mWidth = 0;
|
|
|
|
Framebuffer.mHeight = 0;
|
2016-10-05 23:28:52 +02:00
|
|
|
}
|
|
|
|
|
2017-12-29 15:50:18 +01:00
|
|
|
void lcContext::BindFramebuffer(GLuint FramebufferObject)
|
2016-10-05 23:28:52 +02:00
|
|
|
{
|
2017-12-29 15:50:18 +01:00
|
|
|
if (FramebufferObject == mFramebufferObject)
|
|
|
|
return;
|
2017-12-26 19:19:20 +01:00
|
|
|
|
2017-12-29 15:50:18 +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)
|
|
|
|
{
|
2018-02-25 03:22:53 +01:00
|
|
|
if (gSupportsFramebufferObjectARB && QGLFormat::defaultFormat().sampleBuffers() && QGLFormat::defaultFormat().samples() > 1)
|
2017-12-29 15:50:18 +01:00
|
|
|
return std::make_pair(CreateFramebuffer(Width, Height, true, true), CreateFramebuffer(Width, Height, false, false));
|
|
|
|
else
|
2017-12-30 22:03:47 +01:00
|
|
|
return std::make_pair(CreateFramebuffer(Width, Height, true, false), lcFramebuffer());
|
2017-12-29 15:50:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-12-29 15:50:18 +01:00
|
|
|
void lcContext::GetRenderFramebufferImage(const std::pair<lcFramebuffer, lcFramebuffer>& RenderFramebuffer, quint8* Buffer)
|
2017-12-26 19:19:20 +01:00
|
|
|
{
|
2017-12-29 15:50:18 +01:00
|
|
|
const int Width = RenderFramebuffer.first.mWidth;
|
|
|
|
const int Height = RenderFramebuffer.first.mHeight;
|
|
|
|
GLuint SavedFramebuffer = mFramebufferObject;
|
2017-12-26 19:19:20 +01:00
|
|
|
|
2017-12-29 15:50:18 +01:00
|
|
|
if (RenderFramebuffer.second.IsValid())
|
|
|
|
{
|
2017-12-30 21:04:12 +01:00
|
|
|
#ifndef LC_OPENGLES
|
2017-12-29 15:50:18 +01:00
|
|
|
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);
|
2017-12-29 15:50:18 +01:00
|
|
|
BindFramebuffer(RenderFramebuffer.second);
|
2017-12-30 21:04:12 +01:00
|
|
|
#endif
|
2017-12-26 19:19:20 +01:00
|
|
|
}
|
2017-12-29 15:50:18 +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);
|
2017-12-29 15:50:18 +01:00
|
|
|
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++)
|
|
|
|
{
|
2016-12-16 18:14:19 +01:00
|
|
|
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;
|
2016-12-16 18:14:19 +01:00
|
|
|
Bottom += 4;
|
2016-10-05 23:28:52 +02:00
|
|
|
}
|
|
|
|
}
|
2016-12-16 18:14:19 +01: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);
|
|
|
|
}
|
|
|
|
|
2017-04-14 02:26:40 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2017-04-14 02:26:40 +02:00
|
|
|
IndexBuffer.Pointer = nullptr;
|
2016-10-05 23:28:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void lcContext::ClearVertexBuffer()
|
|
|
|
{
|
2017-04-14 02:26:40 +02:00
|
|
|
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);
|
|
|
|
|
2017-04-14 02:26:40 +02:00
|
|
|
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);
|
|
|
|
|
2017-04-14 02:26:40 +02:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
GLuint VertexBufferObject = VertexBuffer.Object;
|
2017-04-14 02:26:40 +02:00
|
|
|
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
|
|
|
{
|
2017-03-24 17:34:53 +01:00
|
|
|
int VertexSize = PositionSize * sizeof(float);
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
int VertexSize = (PositionSize + TexCoordSize + ColorSize) * sizeof(float) + NormalSize * sizeof(quint32);
|
|
|
|
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
|
|
|
{
|
2017-03-06 07:14:50 +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)
|
|
|
|
{
|
|
|
|
GLuint IndexBufferObject = IndexBuffer.Object;
|
2017-04-14 02:26:40 +02:00
|
|
|
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
|
|
|
{
|
|
|
|
lcPiecesLibrary* Library = lcGetPiecesLibrary();
|
|
|
|
|
|
|
|
if (Mesh->mVertexCacheOffset != -1)
|
|
|
|
{
|
|
|
|
GLuint VertexBufferObject = Library->mVertexBuffer.Object;
|
|
|
|
GLuint IndexBufferObject = Library->mIndexBuffer.Object;
|
|
|
|
|
|
|
|
if (VertexBufferObject != mVertexBufferObject)
|
|
|
|
{
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER_ARB, VertexBufferObject);
|
|
|
|
mVertexBufferObject = VertexBufferObject;
|
2017-04-14 02:26:40 +02:00
|
|
|
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;
|
2017-04-14 02:26:40 +02:00
|
|
|
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)
|
|
|
|
{
|
2017-03-12 21:51:14 +01:00
|
|
|
const lcProgram& Program = mPrograms[mMaterialType];
|
2017-03-01 00:20:34 +01:00
|
|
|
|
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-06 07:14:50 +01:00
|
|
|
{
|
2017-03-12 01:47:21 +01:00
|
|
|
if (Program.WorldMatrixLocation != -1)
|
|
|
|
glUniformMatrix4fv(Program.WorldMatrixLocation, 1, false, mWorldMatrix);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mViewMatrixDirty)
|
|
|
|
{
|
|
|
|
lcMatrix44 InverseViewMatrix = lcMatrix44AffineInverse(mViewMatrix);
|
|
|
|
lcVector3 ViewPosition = lcMul30(-mViewMatrix.GetTranslation(), InverseViewMatrix);
|
|
|
|
|
|
|
|
if (Program.LightPositionLocation != -1)
|
2017-03-06 07:14:50 +01:00
|
|
|
{
|
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-06 07:14:50 +01:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
if (mHighlightColorDirty && Program.HighlightColorLocation != -1)
|
|
|
|
{
|
|
|
|
glUniform4fv(Program.HighlightColorLocation, 1, mHighlightColor);
|
|
|
|
mHighlightColorDirty = false;
|
|
|
|
}
|
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);
|
|
|
|
}
|