X-Git-Url: https://ecere.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ecere%2Fsrc%2Fgfx%2Fdrivers%2FOpenGLDisplayDriver.ec;h=289d9817f3f0510d0dba905199251f5dc22b47dd;hb=8d4a267a681da78408bf758106ca32be3a021dd7;hp=17e89305118d012d2229a272633e2c3ee5d6a213;hpb=24066d0ca9923a4584380591d1fd858fb5c34716;p=sdk diff --git a/ecere/src/gfx/drivers/OpenGLDisplayDriver.ec b/ecere/src/gfx/drivers/OpenGLDisplayDriver.ec index 17e8930..289d981 100644 --- a/ecere/src/gfx/drivers/OpenGLDisplayDriver.ec +++ b/ecere/src/gfx/drivers/OpenGLDisplayDriver.ec @@ -1,56 +1,50 @@ -namespace gfx::drivers; +#if defined(__WIN32__) || defined(__unix__) || defined(__APPLE__) -#if defined(_GLES) -#define ES1_1 -#else -// #define SHADERS +// #define DIAGNOSTICS +#if defined(_DEBUG) && !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__) + #define GL_DEBUGGING #endif -#define GL_BGRA_EXT 0x80E1 - -#if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__) -# if defined(SHADERS) -# include "gl_core_3_3.h" -# else -# include "gl_compat_4_4.h" -# endif -#endif +import "Display" import "glab" import "immediate" import "matrixStack" -import "shading" +import "defaultShader" -#ifdef SHADERS +namespace gfx::drivers; -#undef glEnableClientState -#undef glDisableClientState -#undef GL_VERTEX_ARRAY -#undef GL_NORMAL_ARRAY -#undef GL_TEXTURE_COORD_ARRAY -#undef GL_COLOR_ARRAY +#include "gl123es.h" -#define glEnableClientState glEnableVertexAttribArray -#define glDisableClientState glDisableVertexAttribArray -#define GL_VERTEX_ARRAY GLBufferContents::vertex -#define GL_NORMAL_ARRAY GLBufferContents::normal -#define GL_TEXTURE_COORD_ARRAY GLBufferContents::texCoord -#define GL_COLOR_ARRAY GLBufferContents::color +// ********** GL PLATFORMS INCLUDES ********** +// UNIX +#if defined(__unix__) || defined(__APPLE__) -#endif + // EGL + #if defined(__ANDROID__) || defined(__ODROID__) + import "egl" -// We were using PBUFFER for alpha compositing on Linux before, but it does not seem to work, nor be required anymore. -// #define USEPBUFFER -#if defined(__unix__) || defined(__APPLE__) + #if defined(__ANDROID__) + #include + #include + #define printf(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "ecere-app", __VA_ARGS__)) + #endif -#if !defined(__MINGW32__) - #define GL_GLEXT_PROTOTYPES -#endif + // Emscripten + #elif defined(__EMSCRIPTEN__) + #define property _property + #define uint _uint -#define pointer _pointer + #include + #include + #undef property + #undef uint - #if !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__) + // GLX + #elif !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__) + #define pointer _pointer + #define GL_GLEXT_PROTOTYPES #define property _property #define new _new @@ -87,306 +81,168 @@ import "shading" #undef new #undef property #undef class + #undef pointer - #endif + #if !defined(__APPLE__) + default GLAPI void APIENTRY glLockArraysEXT (GLint first, GLsizei count); + default GLAPI void APIENTRY glUnlockArraysEXT (void); + #endif -#endif + import "XInterface" -#if defined(__APPLE__) -#include -#endif + // We were using PBUFFER for alpha compositing on Linux before, but it does not seem to work, nor be required anymore. + // #define USEPBUFFER -#if defined(__WIN32__) || defined(__unix__) || defined(__APPLE__) + #endif -#if defined(__WIN32__) +// Apple +#elif defined(__APPLE__) + #include + +// WGL +#elif defined(__WIN32__) //#define WIN32_LEAN_AND_MEAN #undef _WIN32_WINNT #define _WIN32_WINNT 0x0502 #define String Sting_ #include #undef String -#endif - -#if defined(__ANDROID__) || defined(__ODROID__) - -#define uint _uint -#define property _property -#define new _new -#define class _class -#define Window X11Window -#define Cursor X11Cursor -#define Font X11Font -#define Display X11Display -#define Time X11Time -#define KeyCode X11KeyCode -#define Picture X11Picture -#define Bool X11Bool - - #include - -#undef Bool -#undef Picture -#undef Window -#undef Cursor -#undef Font -#undef Display -#undef Time -#undef KeyCode -#undef uint -#undef new -#undef property -#undef class -#elif defined(__EMSCRIPTEN__) - - #define property _property - #define uint _uint - - #include - - //#include - //#include - - //#include - //#include - - //#include - #include - #include - - #undef property - #undef uint - -#else - #include -#endif - -#if defined(__ODROID__) && !defined(ES1_1) -#define ES1_1 + #include "wglDefs.h" #endif -#if defined(__EMSCRIPTEN__) -#define EM_MODE -// #define ES1_1 +#if defined(__WIN32__) +#elif !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__) +default: +private: #endif -#undef pointer - -import "Display" - -#if defined(__unix__) || defined(__APPLE__) - - #if !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__) - import "XInterface" - #endif +/* OpenGL Versions Features Quick Reference + + | OpenGL 1.1 | OpenGL 1.5 | GL ES 1.1 | OpenGL 2 | GL 3 (Compat) | GL 3 (Core) | GL ES 2 | WebGL 1 | GL ES 3 | WebGL 2 + ======================================================================================================================================================================= + glBegin() | X | X | - | X | X | - | - | - | - | - + glLoadMatrix() | X | X | - | X | X | - | - | - | - | - + glLineWidth() | X | X | - | X | X | - | - | - | - | - + glPointSize() | X | X | - | X | X | - | - | - | - | - + glLineStipple() | X | X | - | X | X | - | - | - | - | - + glPolygonStipple() | X | X | - | X | X | - | - | - | - | - + glColorMaterial() | X | X | - | X | X | - | - | - | - | - + GL_QUADS | X | X | - | X | X | - | - | - | - | - + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + GL_INT / GL_DOUBLE | X | X | - | X | X | X | - | - | - | - + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + GL_SELECT | X | X | - | (Slow) | (Slow) | (Slow) | - | - | - | - + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Non ² Textures | - | - | - | X | X | X | - | - | - | - + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + glVertexPointer() (PTR) | X | X | X | X | X | - | - | - | - | - + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + glVertexPointer() (VBO) | - | X | X | X | X | - | - | - | - | - + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + glBufferData() | - | X | X | X | X | X | X | X | X | X + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + glMapBuffer() | - | X | OES x | X | X | X | OES x | - | OES x | - + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + glBindFramebuffer() | - | - | OES x | - | X | X | X | X | X | X + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + glVertexAttribPointer() (PTR) | - | - | - | X | X | X | X | - | X | - + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + glVertexAttribPointer() (VBO) | - | - | - | X | X | X | X | X | X | X + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + GLSL Version | - | - | - | 1.10 | 1.30 | 1.30 | 1.00 | 1.00 | 3.00 | 3.00 + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + bool legacy :1; // | X | X | - | X | X | - | - | - | - | - + bool shaders :1; // | - | - | - | X | X | X | X | X | X | X + bool nonPow2Textures :1; // | - | - | - | X | X | X | - | - | - | - + bool vertexBuffer :1; // | - | X | X | X | X | X | X | X | X | X + bool frameBuffer :1; // | - | - | ~ | - | X | X | X | X | X | X +// bool mapBuffer :1; // | - | X | ~ | X | X | X | ~ | - | ~ | - +*/ -#endif +default: +// Capabilities Global set to capabilities of Display being rendered to +GLCapabilities glCaps; +// Requiring Graphics Reload: +bool glCaps_nonPow2Textures, glCaps_vertexBuffer, glCaps_quads, glCaps_intAndDouble, glCaps_legacyFormats, glCaps_compatible, glCaps_vertexPointer; +// Might toggle without Reload: +bool glCaps_core, glCaps_shaders, glCaps_fixedFunction, glCaps_immediate, glCaps_legacy, glCaps_pointSize, glCaps_frameBuffer, glCaps_vao, glCaps_select; +// bool mapBuffer; +private: -#define glLoadMatrix glLoadMatrixd -#define glMultMatrix glMultMatrixd -#define glGetMatrix glGetDoublev -#define glTranslate glTranslated -#define glScale glScaled +// ********** Errors and Debugging ********** /* -#define glVertex3v glVertex3dv -#define glNormal3v glNormal3dv +void CheckGLErrors() +{ + int e, nCount = 0; + while((e = glGetError()) && nCount++ < 10) + printf("GL error %d!\n", e); +} */ - -/* -//#ifdef VERTEX_FORMAT_DOUBLE - -#define glLoadMatrix glLoadMatrixd -#define glMultMatrix glMultMatrixd -#define glGetMatrix glGetDoublev -#define glVertex3v glVertex3dv -#define glNormal3v glNormal3dv -#define glTranslate glTranslated -#define glScale glScaled -//#define GL_VERTEX_FORMAT GL_DOUBLE - -#else - -#define glLoadMatrix glLoadMatrixf -#define glMultMatrix glMultMatrixf -#define glGetMatrix glGetFloatv -#define glVertex3v glVertex3fv -#define glNormal3v glNormal3fv -#define glTranslate glTranslatef -#define glScale glScalef -//#define GL_VERTEX_FORMAT GL_FLOAT - +#ifdef GL_DEBUGGING +#ifndef APIENTRY + #define APIENTRY #endif -*/ - -#define GL_ARRAY_BUFFER_ARB 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 -#define GL_STATIC_DRAW_ARB 0x88E4 -#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 -#define GL_SEPARATE_SPECULAR_COLOR 0x81FA - -#define GL_MULTISAMPLE_ARB 0x809D - -#if defined(__WIN32__) - #include "wglDefs.h" - - typedef void (APIENTRY * PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count); - typedef void (APIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void); +static void APIENTRY openglCallbackFunction(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam) +{ + if(severity == GL_DEBUG_SEVERITY_NOTIFICATION) + return; + PrintLn("---------------------opengl-callback-start------------"); + PrintLn("message: ", message); + PrintLn("type: "); + switch (type) + { + case GL_DEBUG_TYPE_ERROR: PrintLn("ERROR"); break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: PrintLn("DEPRECATED_BEHAVIOR"); break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: PrintLn("UNDEFINED_BEHAVIOR"); break; + case GL_DEBUG_TYPE_PORTABILITY: PrintLn("PORTABILITY"); break; + case GL_DEBUG_TYPE_PERFORMANCE: PrintLn("PERFORMANCE"); break; + case GL_DEBUG_TYPE_OTHER: PrintLn("OTHER"); break; + } - static PFNGLLOCKARRAYSEXTPROC glLockArraysEXT = null; - static PFNGLUNLOCKARRAYSEXTPROC glUnlockArraysEXT = null; + PrintLn("id: ", id); + Print("severity: "); + switch (severity) + { + case GL_DEBUG_SEVERITY_LOW: PrintLn("LOW"); break; + case GL_DEBUG_SEVERITY_MEDIUM: PrintLn("MEDIUM"); break; + case GL_DEBUG_SEVERITY_HIGH: PrintLn("HIGH"); break; + default: PrintLn("(other)"); + } + PrintLn("---------------------opengl-callback-end--------------"); +} - static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = null; - static PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = null; - static PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB = null; - static PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB = null; - static PFNWGLQUERYPBUFFERARBPROC wglQueryPbufferARB = null; - static PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB = null; - static PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB = null; - static PFNWGLBINDTEXIMAGEARBPROC wglBindTexImageARB = null; - static PFNWGLRELEASETEXIMAGEARBPROC wglReleaseTexImageARB = null; - static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = null; - static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = null; +static void setupDebugging() +{ + if(glDebugMessageCallback) + { + GLuint unusedIds = 0; -#elif defined(__ANDROID__) || defined(__ODROID__) + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); - #define GL_FRAMEBUFFER GL_FRAMEBUFFER_OES - #define GL_RENDERBUFFER GL_RENDERBUFFER_OES - #define GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_OES - - #define GL_POLYGON_STIPPLE 0xFFFF - #define GL_LINE_STIPPLE 0xFFFF - #define GL_LINE 0xFFFF - #define GL_FILL 0xFFFF - #define GL_ALL_ATTRIB_BITS 0xFFFF - #define GL_LIGHT_MODEL_LOCAL_VIEWER 0xFFFF - - #define GL_POLYGON 9 - #define GL_QUADS 7 - - //#define GL_QUADS 0 - #define GL_QUAD_STRIP 0 - //#define GL_DOUBLE 0 - //#define GL_UNSIGNED_INT 0 - //#define GL_FILL 0 - //#define GL_LINE 0 - //#define GL_LINE_STIPPLE 0 - #define GL_BGRA_EXT 0 - #define GL_UNPACK_ROW_LENGTH 0 - #define GL_UNPACK_SKIP_PIXELS 0 - #define GL_UNPACK_SKIP_ROWS 0 - #define GL_RGBA8 0 - #define GL_PACK_ROW_LENGTH 0 - #define GL_PACK_SKIP_ROWS 0 - #define GL_PACK_SKIP_PIXELS 0 - -#endif - - -#if defined(__ANDROID__) || defined(__ODROID__) - #define glBindFramebuffer glBindFramebufferOES - #define glBindRenderbuffer glBindRenderbufferOES - #define glFramebufferTexture2D glFramebufferTexture2DOES - #define glGenFramebuffers glGenFramebuffersOES - #define glGenRenderbuffers glGenRenderbuffersOES - #define glDeleteFramebuffers glDeleteFramebuffersOES - #define glDeleteRenderbuffers glDeleteRenderbuffersOES - - #define GL_INT 0x1404 - #define GL_UNSIGNED_INT 0x1405 - #define GL_DOUBLE 0x140A - #define APIENTRY + glDebugMessageCallback(openglCallbackFunction, null); + glDebugMessageControl(GL_DONT_CARE, + GL_DONT_CARE, + GL_DONT_CARE, + 0, + &unusedIds, + GL_TRUE); + } +} #endif -#if defined(ES1_1) || defined(SHADERS) - - #undef glRecti - #undef glBegin - #undef glTexCoord2i - #undef glVertex2i - #undef glTexCoord2d - #undef glVertex2d - #undef glTexCoord2f - #undef glVertex2f - #undef glEnd - #undef glColor3f - #undef glColor4ub - #undef glColor4fv - #undef glNormal3fv - #undef glNormal3f - #undef glTexCoord2fv - #undef glVertex3d - #undef glVertex3dv - #undef glVertex3f - #undef glVertex3fv - - #undef glLoadMatrixd - #undef glMultMatrixd - #undef glFrustum - #undef glOrtho - #undef glScaled - #undef glScalef - #undef glTranslated - #undef glRotated - #undef glMatrixMode - #undef glLoadIdentity - #undef glPushMatrix - #undef glPopMatrix - - #undef glLineStipple - #undef glColorMaterial - #undef glLightModeli - - #define glRecti glimtkRecti - #define glBegin glimtkBegin - #define glTexCoord2i glimtkTexCoord2i - #define glVertex2i glimtkVertex2i - #define glTexCoord2d glimtkTexCoord2d - #define glVertex2d glimtkVertex2d - #define glTexCoord2f glimtkTexCoord2f - #define glVertex2f glimtkVertex2f - #define glEnd glimtkEnd - #define glColor3f glimtkColor3f - #define glColor4ub glimtkColor4ub - #define glColor4fv glimtkColor4fv - #define glNormal3fv glimtkNormal3fv - #define glNormal3f glimtkNormal3f - #define glTexCoord2fv glimtkTexCoord2fv - #define glVertex3d glimtkVertex3d - #define glVertex3dv glimtkVertex3dv - #define glVertex3f glimtkVertex3f - #define glVertex3fv glimtkVertex3fv - - #define glLoadMatrixd glmsLoadMatrixd - #define glMultMatrixd glmsMultMatrixd - #define glFrustum glmsFrustum - #define glOrtho glmsOrtho - #define glScaled glmsScaled - #define glScalef glmsScaled - #define glTranslated glmsTranslated - #define glRotated glmsRotated - #define glMatrixMode glmsMatrixMode - #define glLoadIdentity glmsLoadIdentity - #define glPushMatrix glmsPushMatrix - #define glPopMatrix glmsPopMatrix - - #define glLineStipple glesLineStipple - #define glColorMaterial glesColorMaterial - #define glLightModeli glesLightModeli - -#endif - -public void glesColorMaterial(int a, int b) -{ - PrintLn("glColorMaterial stub"); -} static GLuint stippleTexture; -#if defined(ES1_1) || defined(SHADERS) || defined(EM_MODE) static bool stippleEnabled; -#endif -public void glesLineStipple( int i, unsigned short j ) +public void glsupLineStipple( int i, uint16 j ) { uint texture[1*16]; int x; @@ -406,91 +262,125 @@ public void glesLineStipple( int i, unsigned short j ) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); + GLMatrixMode(GL_TEXTURE); + GLLoadIdentity(); //glTranslated(1.0/backAttrib->texW/2.0f, 1.0/backAttrib->texH/2.0f, 0.0f); - glScaled(i/16.0, 1, 1.0f); - glTranslated(0.5, 0.5, 0); - glMatrixMode(MatrixMode::projection); + GLScaled(i/16.0, 1, 1.0f); + GLTranslated(0.5, 0.5, 0); + GLMatrixMode(MatrixMode::projection); } -public void glesLightModeli( unsigned int pname, int param ) -{ -#if !defined(EM_MODE) && !defined(SHADERS) - if(pname == GL_LIGHT_MODEL_TWO_SIDE) - glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, param); + // Exported to build _GLES version... + public void glsupLightModeli( unsigned int pname, int param ) + { +#if ENABLE_GL_FFP + if(pname == GL_LIGHT_MODEL_TWO_SIDE) + glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, param); +#endif + } + +#ifdef _GLES + void glFogi( unsigned int pname, int param ) { } + void glPolygonMode( unsigned int i, unsigned int j ) { } + void glBlendFuncSeparate(int a, int b, int c, int d) + { + glBlendFunc(a, b); + } + #endif -} -#if defined(__ANDROID__) || defined(__ODROID__) +#if defined(_GLES) || defined(_GLES2) void glClearDepth( double depth ) { glClearDepthf((float)depth); } -void glFogi( unsigned int pname, int param ) { } -void glPolygonMode( unsigned int i, unsigned int j ) { } +#endif +#if !ENABLE_GL_SELECT // *** Picking won't be supported for now *** void glPushName( unsigned int i ) { } void glLoadName( unsigned int i ) { } void glPopName() { } -// Probably replace by regular glBlendFunc ... -void glBlendFuncSeparate(int a, int b, int c, int d) +#endif + +#if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA) +static inline uint getPrimitiveType(RenderPrimitiveType type) { - glBlendFunc(a, b); + static int primitiveTypes[RenderPrimitiveType] = + { + GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, + GLIMTKMode::quads, + GLIMTKMode::quadStrip, + GL_LINE_STRIP + }; + // NOTE: This will only work for single quads + return (type == quads && !glCaps_quads) ? GL_TRIANGLE_FAN : primitiveTypes[type]; } -// For direct pixel blitting... -void glRasterPos2d(double a, double b) { } -void glPixelZoom(float a, float b) { } -void glDrawPixels(int a, int b, int c, int d, void * e) { } +public void GLSetupTexturing(bool enable) +{ +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + defaultShader.texturing(enable); +#endif +#if ENABLE_GL_FFP + if(!glCaps_shaders) + (enable ? glEnable : glDisable)(GL_TEXTURE_2D); #endif +} -#if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA) -static int primitiveTypes[RenderPrimitiveType] = +public void GLSetupFog(bool enable) { - GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GLIMTKMode::quads, GLIMTKMode::quadStrip, GL_LINE_STRIP -}; +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + defaultShader.fog(enable); #endif -public void GLSetupTexturing(bool enable) -{ -#ifdef SHADERS - shader_texturing(enable); -#else - (enable ? glEnable : glDisable)(GL_TEXTURE_2D); +#if ENABLE_GL_FFP + if(!glCaps_shaders) + (enable ? glEnable : glDisable)(GL_FOG); #endif } +bool lightingEnabled; -// Non OpenGL ES friendly stuff +public void GLSetupLighting(bool enable) +{ + lightingEnabled = enable; +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + defaultShader.lighting(enable); +#endif -#if defined(ES1_1) +#if ENABLE_GL_FFP + if(!glCaps_shaders) + (enable ? glEnable : glDisable)(GL_LIGHTING); +#endif +} +#endif -//#undef GL_UNSIGNED_INT -//#undef GL_DOUBLE -#undef GL_INT -//#undef GL_POLYGON -//#undef GL_QUADS -#undef GL_QUAD_STRIP -#undef GL_POLYGON_STIPPLE -#undef GL_LINE_STIPPLE -#undef GL_LINE -#undef GL_FILL -#undef GL_ALL_ATTRIB_BITS -#undef GL_LIGHT_MODEL_LOCAL_VIEWER +/*static */GLuint lastBlitTex; -#endif +Shader activeShader; static int displayWidth, displayHeight; #define GL_CLAMP_TO_EDGE 0x812F -static bool vboAvailable; - static bool useSingleGLContext = false; class OGLDisplay : struct { + GLCapabilities capabilities, originalCapabilities; + bool compat; + int version; + + ColorAlpha * flippingBuffer; + int flipBufH, flipBufW; + bool depthWrite; + int x, y; + uint vao; + int maxTMU; + #if defined(__WIN32__) HDC hdc; HGLRC glrc; @@ -520,63 +410,32 @@ class OGLDisplay : struct Pixmap shapePixmap; X11Picture shapePicture; #endif - - ColorAlpha * flippingBuffer; - int flipBufH, flipBufW; - bool depthWrite; - int x, y; }; -#ifdef _DEBUG -static void APIENTRY openglCallbackFunction(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar* message, - const void* userParam) -{ - PrintLn("---------------------opengl-callback-start------------"); - PrintLn("message: ", message); - PrintLn("type: "); - switch (type) - { - case GL_DEBUG_TYPE_ERROR: PrintLn("ERROR"); break; - case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: PrintLn("DEPRECATED_BEHAVIOR"); break; - case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: PrintLn("UNDEFINED_BEHAVIOR"); break; - case GL_DEBUG_TYPE_PORTABILITY: PrintLn("PORTABILITY"); break; - case GL_DEBUG_TYPE_PERFORMANCE: PrintLn("PERFORMANCE"); break; - case GL_DEBUG_TYPE_OTHER: PrintLn("OTHER"); break; - } - - PrintLn("id: ", id); - Print("severity: "); - switch (severity) - { - case GL_DEBUG_SEVERITY_LOW: PrintLn("LOW"); break; - case GL_DEBUG_SEVERITY_MEDIUM: PrintLn("MEDIUM"); break; - case GL_DEBUG_SEVERITY_HIGH: PrintLn("HIGH"); break; - } - PrintLn("---------------------opengl-callback-end--------------"); -} -#endif - class OGLSystem : struct { int maxTextureSize; bool loadingFont; - bool pow2textures; #if defined(__WIN32__) PIXELFORMATDESCRIPTOR pfd; int format; HDC hdc; HGLRC glrc; HWND hwnd; -#elif !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__) +#elif defined(__EMSCRIPTEN__) + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE glc; +#elif !defined(__ANDROID__) && !defined(__ODROID__) XVisualInfo * visualInfo; GLXContext glContext; GLXDrawable glxDrawable; #endif + GLCapabilities capabilities; + bool compat; + int version; + + // Buffer Data + uint16 *shortBDBuffer; + uint shortBDSize; }; class OGLSurface : struct @@ -594,6 +453,8 @@ class OGLMesh : struct { GLAB vertices; GLAB normals; + GLAB tangents; + GLAB lightVectors; GLAB texCoords; GLAB texCoords2; GLAB colors; @@ -609,42 +470,59 @@ class OGLIndices : struct int current; void * previous; -static void setupDebugging() -{ -#ifdef _DEBUG - if(glDebugMessageCallback) - { - GLuint unusedIds = 0; - - glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); - glDebugMessageCallback(openglCallbackFunction, null); - glDebugMessageControl(GL_DONT_CARE, - GL_DONT_CARE, - GL_DONT_CARE, - 0, - &unusedIds, - GL_TRUE); - } -#endif -} - #if defined(__WIN32__) -static HGLRC winCreateContext(HDC hdc) +static HGLRC winCreateContext(HDC hdc, int * contextVersion, bool * isCompatible, bool compatible) { + HGLRC result = 0; if(wglCreateContextAttribsARB) { - int attribs[] = + int versions[12][2] = { - WGL_CONTEXT_MAJOR_VERSION_ARB, 4, - WGL_CONTEXT_MINOR_VERSION_ARB, 4, - WGL_CONTEXT_FLAGS_ARB, /*WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB | */WGL_CONTEXT_DEBUG_BIT_ARB, - WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB /*WGL_CONTEXT_CORE_PROFILE_BIT_ARB*/, - 0,0 + { 4, 5 }, { 4, 4 }, { 4, 3 }, { 4, 2 }, { 4, 1 }, { 4, 0 }, + { 3, 3 }, { 3, 2 }, { 3, 1 }, { 3, 0 }, + { 2, 1 }, { 2, 0 } }; - return wglCreateContextAttribsARB(hdc, null, attribs); + + bool tryingCompat = compatible; + int v = 0; + while(!result) + { + for(v = 0; !result && v < sizeof(versions) / sizeof(versions[0]); v++) + { + int v0 = versions[v][0], v1 = versions[v][1]; + if(!tryingCompat || v0 >= 3) + { + bool coreNotion = v0 > 3 || (v0 == 3 && v1 >= 3); + int attribs[] = + { + WGL_CONTEXT_MAJOR_VERSION_ARB, v0, WGL_CONTEXT_MINOR_VERSION_ARB, v1, + #ifdef _DEBUG + WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB, + #endif + coreNotion ? WGL_CONTEXT_PROFILE_MASK_ARB : 0, coreNotion ? (tryingCompat ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : WGL_CONTEXT_CORE_PROFILE_BIT_ARB) : 0, + 0,0 + }; + result = wglCreateContextAttribsARB(hdc, null, attribs); + if(result) + { + if(contextVersion) *contextVersion = v0; + if(isCompatible) *isCompatible = tryingCompat || !coreNotion; + } + } + } + if(tryingCompat) + tryingCompat = false; + else + break; + } + } + if(!result) + { + if(contextVersion) *contextVersion = 1; + if(isCompatible) *isCompatible = true; + result = wglCreateContext(hdc); } - else - return wglCreateContext(hdc); + return result; } #endif @@ -654,7 +532,10 @@ class OpenGLDisplayDriver : DisplayDriver bool LockSystem(DisplaySystem displaySystem) { -#if !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__) +#if defined(__EMSCRIPTEN__) + OGLSystem oglSystem = displaySystem.driverData; + emscripten_webgl_make_context_current(oglSystem.glc); +#elif !defined(__ANDROID__) && !defined(__ODROID__) OGLSystem oglSystem = displaySystem.driverData; if(useSingleGLContext) return true; #if defined(__WIN32__) @@ -779,19 +660,83 @@ class OpenGLDisplayDriver : DisplayDriver } } - void ::CheckExtensions(OGLSystem oglSystem) +#if !defined(__EMSCRIPTEN__) + void ::CheckCapabilities(OGLSystem oglSystem, OGLDisplay oglDisplay, bool canCheckExtensions) { - const char * extensions = (const char *)glGetString(GL_EXTENSIONS); - if(extensions) - oglSystem.pow2textures = strstr(extensions, "GL_ARB_texture_non_power_of_two") ? false : true; + GLCapabilities capabilities; +#if !defined(_GLES2) + const char * extensions = (canCheckExtensions && (!oglDisplay || oglDisplay.compat)) ? (const char *)glGetString(GL_EXTENSIONS) : null; +#endif +#ifdef DIAGNOSTICS + printf("extensions: %s\n", extensions); +#endif + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &oglSystem.maxTextureSize); + +#if defined(_GLES) + capabilities = { fixedFunction = true, vertexPointer = true, vertexBuffer = true, pointSize = true, legacyFormats = true, frameBuffer = extensions && strstr(extensions, "GL_OES_framebuffer_object") }; +#elif defined(_GLES2) + capabilities = { glCaps_shaders = true, vertexBuffer = true, pointSize = true, frameBuffer = true, legacyFormats = true }; +#else + capabilities = + { + nonPow2Textures = glGetStringi || (extensions && (strstr(extensions, "GL_ARB_texture_non_power_of_two"))); + intAndDouble = true; +#ifdef GL_DEBUGGING + debug = true; +#endif + compatible = oglDisplay.compat; + pointSize = oglDisplay.compat; +#if ENABLE_GL_LEGACY + legacy = glBegin != null && oglDisplay.compat; + legacyFormats = glBegin != null && oglDisplay.compat; + immediate = glBegin != null && oglDisplay.compat; + fixedFunction = glBegin != null && oglDisplay.compat; + quads = glBegin != null && oglDisplay.compat; + select = glSelectBuffer != null && oglDisplay.compat; +#endif +#if ENABLE_GL_SHADERS + shaders = glCreateProgram != null; +#endif +#if ENABLE_GL_POINTER + vertexPointer = oglDisplay.compat; +#endif +#if ENABLE_GL_VAO + vao = glBindVertexArray != null && !oglDisplay.compat; +#endif +#if ENABLE_GL_FBO + frameBuffer = glBindFramebuffer != null; +#endif + vertexBuffer = glBindBuffer != null; + // mapBuffer = glMapBuffer != null; + }; +#endif + +#ifdef DIAGNOSTICS + PrintLn("max texture size: ", oglSystem.maxTextureSize); +#endif + if(oglDisplay) oglDisplay.capabilities = capabilities; + if(oglSystem) oglSystem.capabilities = capabilities; } +#endif bool CreateDisplaySystem(DisplaySystem displaySystem) { bool result = false; OGLSystem oglSystem = displaySystem.driverData = OGLSystem { }; +#ifdef _GLES + oglSystem.capabilities = { fixedFunction = true, vertexBuffer = true, frameBuffer = true, pointSize = true }; +#elif defined(_GLES2) + oglSystem.capabilities = { shaders = true, vertexBuffer = true, frameBuffer = true, pointSize = true }; +#else + oglSystem.capabilities = { compatible = glCaps_compatible, shaders = true, fixedFunction = true, immediate = true, legacy = true, pointSize = true, quads = true, intAndDouble = true, vertexBuffer = true, frameBuffer = true, vao = true, nonPow2Textures = true }; +#endif + +#ifdef DIAGNOSTICS + PrintLn("OpenGL driver's CreateDisplaySystem()"); +#endif + #ifdef __WIN32__ oglSystem.hwnd = CreateWindow("static", null, 0,0,0,0,0,null,null,null,null); @@ -884,8 +829,15 @@ class OpenGLDisplayDriver : DisplayDriver SetPixelFormat(oglSystem.hdc, oglSystem.format, &oglSystem.pfd); //Log("Successfully set pixel format\n"); - oglSystem.glrc = winCreateContext(oglSystem.hdc); - wglMakeCurrent(oglSystem.hdc, oglSystem.glrc); +#ifdef DIAGNOSTICS + PrintLn("winCreateContext()"); +#endif + oglSystem.glrc = winCreateContext(oglSystem.hdc, &oglSystem.version, &oglSystem.compat, displaySystem.glCapabilities.compatible); +#ifdef DIAGNOSTICS + PrintLn("wglMakeCurrent()"); +#endif + if(oglSystem.glrc) + wglMakeCurrent(oglSystem.hdc, oglSystem.glrc); } } /*else @@ -900,27 +852,86 @@ class OpenGLDisplayDriver : DisplayDriver } } #elif defined(__unix__) || defined(__APPLE__) - vboAvailable = true; - #if defined(__ANDROID__) + #if defined(__ANDROID__) || defined(__ODROID__) + #if defined(__ANDROID__) egl_init_display(guiApp.desktop.windowHandle); - #elif defined(__ODROID__) + #elif defined(__ODROID__) egl_init_display((uint)displaySystem.window); - CheckExtensions(oglSystem); + #endif + CheckCapabilities(oglSystem, null, true); + + // TODO: Clean this up? Needed here? + GLEnableClientState(VERTICES); + /* + // Initialize GL state. + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + glEnable(GL_CULL_FACE); + glShadeModel(GL_SMOOTH); + glDisable(GL_DEPTH_TEST); + */ + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + matrixStack[0][0].Identity(); + matrixStack[1][0].Identity(); + matrixStack[2][0].Identity(); + + GLMatrixMode(GL_MODELVIEW); + GLScaled(1.0, 1.0, -1.0); + GLMatrixMode(GL_PROJECTION); + glShadeModel(GL_FLAT); + +#if !defined(_GLES) + if(!glCaps_shaders) + ;//GLLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); +#endif + glFogi(GL_FOG_MODE, GL_EXP); + glFogf(GL_FOG_DENSITY, 0); + glEnable(GL_NORMALIZE); + glDepthFunc(GL_LESS); + glClearDepth(1.0); + glDisable(GL_MULTISAMPLE); + + glViewport(0,0,eglWidth,eglHeight); + GLLoadIdentity(); + GLOrtho(0,eglWidth,eglHeight,0,0.0,1.0); + + glabCurArrayBuffer = 0; + glabCurElementBuffer = 0; + result = true; #elif defined(__EMSCRIPTEN__) - if(glfwInit() == GL_TRUE) { - const int width = 640, height = 480; - if(glfwOpenWindow(width, height, 8, 8, 8, 8, 16, 0, GLFW_WINDOW) == GL_TRUE) - { - //glfwSwapBuffers(); + EmscriptenWebGLContextAttributes attribs = { 0 }; + attribs.depth = 1; + attribs.antialias = 1; + + /* + EM_BOOL alpha; + EM_BOOL depth; + EM_BOOL stencil; + EM_BOOL antialias; + EM_BOOL premultipliedAlpha; + EM_BOOL preserveDrawingBuffer; + EM_BOOL preferLowPowerToHighPerformance; + EM_BOOL failIfMajorPerformanceCaveat; + int majorVersion; + int minorVersion; + EM_BOOL enableExtensionsByDefault; + */ + + emscripten_webgl_init_context_attributes(&attribs); + oglSystem.maxTextureSize = 16384; + oglSystem.glc = emscripten_webgl_create_context("canvas", &attribs); + if(emscripten_webgl_make_context_current(oglSystem.glc) == EMSCRIPTEN_RESULT_SUCCESS) result = true; - } - else - printf("glfwOpenWindow() failed\n"); //glfwTerminate(); + + /*glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND);*/ } - else - printf("glfwInit() failed\n"); //glfwTerminate(); #else { X11Window root = RootWindow( xGlobalDisplay, DefaultScreen( xGlobalDisplay ) ); @@ -953,8 +964,6 @@ class OpenGLDisplayDriver : DisplayDriver if(oglSystem.glContext) { glXMakeCurrent(xGlobalDisplay, oglSystem.glxDrawable, oglSystem.glContext); - // Setup Extensions - CheckExtensions(oglSystem); glXMakeCurrent(xGlobalDisplay, None, null); result = true; } @@ -971,6 +980,19 @@ class OpenGLDisplayDriver : DisplayDriver void DestroyDisplaySystem(DisplaySystem displaySystem) { OGLSystem oglSystem = displaySystem.driverData; + if(stippleTexture) + { + glDeleteTextures(1, &stippleTexture); + stippleTexture = 0; + } + +#if ENABLE_GL_SHADERS + defaultShader.free(); + activeShader = null; +#endif + + delete oglSystem.shortBDBuffer; + glimtkTerminate(); #if defined(__WIN32__) wglMakeCurrent( null, null ); @@ -986,7 +1008,7 @@ class OpenGLDisplayDriver : DisplayDriver #if defined(__ANDROID__) || defined(__ODROID__) egl_term_display(); #elif defined(__EMSCRIPTEN__) - glfwTerminate(); + emscripten_webgl_destroy_context(oglSystem.glc); #else if(oglSystem.visualInfo) { @@ -996,6 +1018,8 @@ class OpenGLDisplayDriver : DisplayDriver XFree(oglSystem.visualInfo); #endif } + if(oglSystem.glContext) + glXDestroyContext(xGlobalDisplay, oglSystem.glContext); if(oglSystem.glxDrawable) { @@ -1007,13 +1031,116 @@ class OpenGLDisplayDriver : DisplayDriver delete oglSystem; } - static bool ::initialDisplaySetup(Display display) + /*static */bool ::initialDisplaySetup(Display display, bool canCheckExtensions, bool loadExtensions) { + OGLDisplay oglDisplay = display.driverData; + OGLSystem oglSystem = display.displaySystem.driverData; bool result = true; - #ifdef SHADERS - loadShaders("<:ecere>shaders/fixed.vertex", "<:ecere>shaders/fixed.frag"); - #endif - glEnableClientState(GL_VERTEX_ARRAY); + +#if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__) + if(loadExtensions && ogl_LoadFunctions() == ogl_LOAD_FAILED) + PrintLn("ogl_LoadFunctions() failed!"); + CheckCapabilities(oglSystem, oglDisplay, canCheckExtensions); +#endif + + { + GLCapabilities capabilities = *&display.glCapabilities; + // PrintLn("Available OpenGL Capabilities: ", oglDisplay.capabilities); + // PrintLn("Desired OpenGL Capabilities: ", capabilities); + + oglDisplay.originalCapabilities = oglDisplay.capabilities; + + // Re-enable glCaps_shaders if no fixed function support + if(!oglDisplay.capabilities.fixedFunction) + capabilities.shaders = true; + // Re-enable fixed function if no glCaps_shaders support + if(!oglDisplay.capabilities.shaders) + { + capabilities.fixedFunction = true; + capabilities.shaders = false; + } + + if(!capabilities.shaders && !capabilities.fixedFunction) + { + capabilities.fixedFunction = oglDisplay.capabilities.fixedFunction; + capabilities.shaders = oglDisplay.capabilities.shaders; + } + + // Disable things that don't work with glCaps_shaders + if(capabilities.shaders) + { + capabilities.fixedFunction = false; + capabilities.legacy = false; + capabilities.immediate = false; + } + + #if !ENABLE_GL_POINTER + // Re-enable vertex buffer if no pointer support + capabilities.vertexBuffer = true; + #endif + + oglDisplay.capabilities &= capabilities; + + // PrintLn("Selected OpenGL Capabilities: ", oglDisplay.capabilities); + oglSystem.capabilities = oglDisplay.capabilities; + } + + #ifdef GL_DEBUGGING + if(oglDisplay.capabilities.debug) + setupDebugging(); + #else + oglDisplay.capabilities.debug = false; + #endif + +#if ENABLE_GL_VAO + if(oglDisplay.capabilities.vao) + { + glGenVertexArrays(1, &oglDisplay.vao); + glBindVertexArray(oglDisplay.vao); + } +#endif + + oglSystem.capabilities = oglDisplay.capabilities; + SETCAPS(oglDisplay.capabilities); + +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + { +#if ENABLE_GL_LEGACY + if(oglDisplay.compat) + { + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + } +#endif + defaultShader.select(); + } +#if ENABLE_GL_LEGACY + else + { + glDisableVertexAttribArray(GLBufferContents::color); + glDisableVertexAttribArray(GLBufferContents::normal); + glDisableVertexAttribArray(GLBufferContents::texCoord); + glDisableVertexAttribArray(GLBufferContents::vertex); + glDisableVertexAttribArray(GLBufferContents::tangent1); + glDisableVertexAttribArray(GLBufferContents::tangent2); +#if ENABLE_GL_VAO + glBindVertexArray(0); +#endif + glUseProgram(0); + } +#endif + +#endif + +#if ENABLE_GL_VAO + if(glCaps_vao) + glBindVertexArray(oglDisplay.vao); +#endif + + GLEnableClientState(VERTICES); GLABBindBuffer(GL_ARRAY_BUFFER, 0); GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -1028,27 +1155,41 @@ class OpenGLDisplayDriver : DisplayDriver #endif glEnable(GL_BLEND); - glMatrixMode(MatrixMode::modelView); - glLoadIdentity(); // For setting up GLES stack - glScaled(1.0, 1.0, -1.0); + GLMatrixMode(MatrixMode::texture); + GLLoadIdentity(); + + GLMatrixMode(MatrixMode::modelView); + GLLoadIdentity(); // For setting up GLES stack + GLScaled(1.0, 1.0, -1.0); // glTranslatef(0.375f, 0.375f, 0.0f); // glTranslatef(-0.625f, -0.625f, 0.0f); - glMatrixMode(MatrixMode::projection); -#if !defined(EM_MODE) && !defined(SHADERS) - glShadeModel(GL_FLAT); + GLMatrixMode(MatrixMode::projection); + GLLoadIdentity(); + if(display.width && display.height) + GLOrtho(0,display.width,display.height,0,0.0,1.0); - // #define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 +#if ENABLE_GL_FFP + if(!glCaps_shaders) + { + glShadeModel(GL_FLAT); - // glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); + #define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 + GLLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); - glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); - glFogi(GL_FOG_MODE, GL_EXP); - glFogf(GL_FOG_DENSITY, 0); - glEnable(GL_NORMALIZE); +#if !defined(_GLES) + ;//GLLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); +#endif + glFogi(GL_FOG_MODE, GL_EXP); + glFogf(GL_FOG_DENSITY, 0); + glEnable(GL_NORMALIZE); + } #endif glDepthFunc(GL_LESS); glClearDepth(1.0); - glDisable(GL_MULTISAMPLE_ARB); +#if !defined(__EMSCRIPTEN__) + glDisable(GL_MULTISAMPLE); +#endif + #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA) display.ambient = Color { 50,50,50 }; #endif @@ -1059,22 +1200,20 @@ class OpenGLDisplayDriver : DisplayDriver { bool result = false; OGLDisplay oglDisplay = display.driverData; -#if !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__) OGLSystem oglSystem = display.displaySystem.driverData; -#endif if(!oglDisplay) oglDisplay = display.driverData = OGLDisplay { }; - //printf("Inside CreateDisplay\n"); + oglDisplay.capabilities = oglSystem.capabilities; #if defined(__WIN32__) || defined(USEPBUFFER) if(!display.alphaBlend) #endif { - #if defined(__WIN32__) +#if defined(__WIN32__) oglDisplay.hdc = GetDC(display.window); SetPixelFormat(oglDisplay.hdc, oglSystem.format, &oglSystem.pfd); - if((oglDisplay.glrc = winCreateContext(oglDisplay.hdc))) + if((oglDisplay.glrc = winCreateContext(oglDisplay.hdc, &oglDisplay.version, &oglDisplay.compat, (*&display.glCapabilities).compatible))) { wglShareLists(oglSystem.glrc, oglDisplay.glrc); wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc); @@ -1082,9 +1221,10 @@ class OpenGLDisplayDriver : DisplayDriver } else ReleaseDC(display.window, oglDisplay.hdc); - #elif defined(__unix__) || defined(__APPLE__) - #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__) - #else +#elif defined(__unix__) || defined(__APPLE__) +# if defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__ODROID__) + result = true; +# else XVisualInfo * visualInfo = ((XWindowData)display.windowDriverData).visual; /* #if defined(__APPLE__) @@ -1103,6 +1243,11 @@ class OpenGLDisplayDriver : DisplayDriver // visualInfo = oglSystem.visualInfo; //#endif */ +#if !defined(__APPLE__) + oglDisplay.compat = true; + oglDisplay.version = 4; +#endif + if(visualInfo) { //printf("visualInfo is not null\n"); @@ -1118,23 +1263,28 @@ class OpenGLDisplayDriver : DisplayDriver glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext); result = true; } - #endif - #endif +# endif +#endif } #if defined(__WIN32__) || defined(USEPBUFFER) else { + oglDisplay.compat = (*&display.glCapabilities).compatible; result = true; wglMakeCurrent(oglSystem.hdc, oglSystem.glrc); } #endif if(result) { - ogl_LoadFunctions(); - CheckExtensions(oglSystem); - vboAvailable = glBindBuffer != null; - setupDebugging(); - initialDisplaySetup(display); +#if defined(__EMSCRIPTEN__) + emscripten_webgl_make_context_current(oglSystem.glc); +#endif + +#if defined(__WIN32__) || defined(USEPBUFFER) + initialDisplaySetup(display, !display.alphaBlend, true); +#else + initialDisplaySetup(display, true, true); +#endif } if(!useSingleGLContext) @@ -1155,17 +1305,14 @@ class OpenGLDisplayDriver : DisplayDriver result = true; #endif } - return result; } bool DisplaySize(Display display, int width, int height) { OGLDisplay oglDisplay = display.driverData; - bool result = false; - //printf("Inside DisplaySize\n"); #if defined(__WIN32__) || defined(USEPBUFFER) OGLSystem oglSystem = display.displaySystem.driverData; if(display.alphaBlend) @@ -1249,7 +1396,7 @@ class OpenGLDisplayDriver : DisplayDriver oglDisplay.pBuffer = wglCreatePbufferARB(oglSystem.hdc, pixelFormat, width, height, attributes); oglDisplay.hdc = wglGetPbufferDCARB(oglDisplay.pBuffer); - if((oglDisplay.glrc = winCreateContext(oglDisplay.hdc))) + if((oglDisplay.glrc = winCreateContext(oglDisplay.hdc, null, null, oglDisplay.capabilities.compatible))) { BITMAPINFO * info; HDC hdc = GetDC(display.window); @@ -1489,9 +1636,11 @@ class OpenGLDisplayDriver : DisplayDriver #if defined(__WIN32__) wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc); #elif defined(__unix__) || defined(__APPLE__) - #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__) + #if defined(__ANDROID__) || defined(__ODROID__) width = eglWidth; height = eglHeight; + #elif defined(__EMSCRIPTEN__) + emscripten_webgl_make_context_current(oglSystem.glc); #else glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext); #endif @@ -1501,8 +1650,10 @@ class OpenGLDisplayDriver : DisplayDriver #endif result = true; + SETCAPS(oglDisplay.capabilities); + if(display.alphaBlend && result) - initialDisplaySetup(display); + initialDisplaySetup(display, true, false); if(!result && display.alphaBlend) { @@ -1514,9 +1665,9 @@ class OpenGLDisplayDriver : DisplayDriver result = false; glViewport(0,0,width,height); - glMatrixMode(MatrixMode::projection); - glLoadIdentity(); - glOrtho(0,width,height,0,0.0,1.0); + GLMatrixMode(MatrixMode::projection); + GLLoadIdentity(); + GLOrtho(0,width,height,0,0.0,1.0); displayWidth = display.width = width; displayHeight = display.height = height; @@ -1524,7 +1675,7 @@ class OpenGLDisplayDriver : DisplayDriver { oglDisplay.flipBufW = width; oglDisplay.flipBufH = height; -#ifdef ES1_1 +#if defined(_GLES) || defined(_GLES2) result = true; #else oglDisplay.flippingBuffer = renew oglDisplay.flippingBuffer ColorAlpha [width * height]; @@ -1554,6 +1705,18 @@ class OpenGLDisplayDriver : DisplayDriver void StartUpdate(Display display) { +#if ENABLE_GL_VAO + if(glCaps_vao) + { + OGLDisplay oglDisplay = display.driverData; + glBindVertexArray(oglDisplay.vao); + } +#endif + GLABBindBuffer(GL_ARRAY_BUFFER, 0); + GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +#if ENABLE_GL_SHADERS + activeProgram = 0; +#endif } void EndUpdate(Display display) @@ -1569,7 +1732,6 @@ class OpenGLDisplayDriver : DisplayDriver #if defined(__WIN32__) || defined(USEPBUFFER) OGLDisplay oglDisplay = display.driverData; #endif - //Logf("DisplayScreen\n"); #if !defined(__ANDROID__) /*glFlush(); @@ -1664,17 +1826,16 @@ class OpenGLDisplayDriver : DisplayDriver #if defined(__WIN32__) //wglSwapLayerBuffers(oglDisplay.hdc,WGL_SWAP_MAIN_PLANE); SwapBuffers(oglDisplay.hdc); + //ecere::sys::Sleep(0.1); #elif defined(__unix__) || defined(__APPLE__) #if defined(__ANDROID__) || defined(__ODROID__) - eglSwapBuffers(eglDisplay, eglSurface); + egl_swap_buffers(); #elif defined(__EMSCRIPTEN__) - glfwSwapBuffers(); #else glXSwapBuffers(xGlobalDisplay, (GLXDrawable)display.window); #endif #endif } - //Logf("Out of DisplayScreen\n"); } void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap) @@ -1691,12 +1852,13 @@ class OpenGLDisplayDriver : DisplayDriver bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette) { OGLSystem oglSystem = displaySystem.driverData; + GLCapabilities capabilities = oglSystem.capabilities; bool result = false; Bitmap mipMap { }; GLuint glBitmap = 0; uint w = width, h = height; - if(oglSystem.pow2textures) + if(!capabilities.nonPow2Textures) { w = pow2i(w); h = pow2i(h); @@ -1715,8 +1877,9 @@ class OpenGLDisplayDriver : DisplayDriver glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -#if !defined(SHADERS) - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); +#if ENABLE_GL_FFP + if(!capabilities.shaders) + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); #endif mipMap.Allocate(null, w, h, w, pixelFormatRGBA, false); @@ -1735,11 +1898,14 @@ class OpenGLDisplayDriver : DisplayDriver return result; } - bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps) + bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps, uint cubeMapFace) { bool result = false; OGLSystem oglSystem = displaySystem.driverData; + GLCapabilities capabilities = oglSystem.capabilities; Bitmap convBitmap = bitmap; + bool oldStyleCubeMap = (cubeMapFace >> 3) != 0; + int face = (cubeMapFace & 7) - 1; if(bitmap.keepData) { convBitmap = { }; @@ -1751,8 +1917,9 @@ class OpenGLDisplayDriver : DisplayDriver { int c, level; uint w = bitmap.width, h = bitmap.height; - GLuint glBitmap = 0; - if(oglSystem.pow2textures) + GLuint glBitmap = cubeMapFace && face > 0 ? (GLuint)(uintptr)bitmap.driverData : 0; + int target = cubeMapFace ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; + if(!capabilities.nonPow2Textures) { w = pow2i(w); h = pow2i(h); @@ -1769,7 +1936,8 @@ class OpenGLDisplayDriver : DisplayDriver // Switch ARGB to RGBA //if(bitmap.format != pixelFormatRGBA) { - for(c=0; cm[3][0], mat->m[3][1], mat->m[3][2] }; + if(display.display3D && display.display3D.camera) + l.Subtract(l, display.display3D.camera.cPosition); + + position[0] = (float)l.x, position[1] = (float)l.y, position[2] = (float)l.z, position[3] = 1; + + if(light.flags.attenuation) { - positionVector = lightObject.transform.position; - positionVector.Subtract(positionVector, display.display3D.camera.cPosition); + glLightf(GL_LIGHT0 + id, GL_CONSTANT_ATTENUATION, light.Kc); + glLightf(GL_LIGHT0 + id, GL_LINEAR_ATTENUATION, light.Kl); + glLightf(GL_LIGHT0 + id, GL_QUADRATIC_ATTENUATION, light.Kq); } else { - positionVector.MultMatrix(lightObject.transform.position, lightObject.parent.matrix); - if(display.display3D.camera) - positionVector.Subtract(positionVector, display.display3D.camera.cPosition); + glLightf(GL_LIGHT0 + id, GL_CONSTANT_ATTENUATION, 1); + glLightf(GL_LIGHT0 + id, GL_LINEAR_ATTENUATION, 0); + glLightf(GL_LIGHT0 + id, GL_QUADRATIC_ATTENUATION, 0); } - position[3] = 1; - } - else - { - if(!light.direction.x && !light.direction.y && !light.direction.z) + + if((light.flags.spot && light.fallOff < 360) || (lightObject && (light.direction.x || light.direction.y || light.direction.z))) { - Vector3Df vector { 0,0,-1 }; - Matrix mat; - mat.RotationQuaternion(light.orientation); - positionVector.MultMatrixf(vector, mat); + // Figure out exponent out of the hot spot + #define MAXLIGHT 0.9 + float exponent = light.flags.spot ? (float)(log(MAXLIGHT) / log(cos(light.hotSpot / 2))) : 1; + Degrees cutOff = light.flags.spot ? light.fallOff/2 : 90; + float direction[4] = { (float)light.direction.x, (float)light.direction.y, (float)light.direction.z, 1 }; + + glLightfv(GL_LIGHT0 + id, GL_SPOT_DIRECTION, direction); + glLightf(GL_LIGHT0 + id, GL_SPOT_CUTOFF, (float)cutOff); + glLightf(GL_LIGHT0 + id, GL_SPOT_EXPONENT, exponent); } else { - positionVector = light.direction; - position[3] = 1; + float d[4] = { 0, 0, 1, 0 }; + glLightfv(GL_LIGHT0 + id, GL_SPOT_DIRECTION, d); + glLightf(GL_LIGHT0 + id, GL_SPOT_CUTOFF, 180); + glLightf(GL_LIGHT0 + id, GL_SPOT_EXPONENT, 1); } - } - - position[0] = (float)positionVector.x; - position[1] = (float)positionVector.y; - position[2] = (float)positionVector.z; - glLightfv(GL_LIGHT0 + id, GL_POSITION, position); + /* + if(lightObject) + { + // Display Light Position + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glColor3f(1,1,1); + glPointSize(10); + glBegin(GL_POINTS); + glVertex3fv(position); + glEnd(); + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); + + + // Display Target + if(lightObject.flags.root || !lightObject.parent) + { + positionVector = light.target.transform.position; + positionVector.Subtract(positionVector, display.camera.cPosition); + } + else + { + positionVector.MultMatrix(light.target.transform.position, + lightObject.light.target.parent.matrix); + positionVector.Subtract(positionVector, display.camera.cPosition); + } - /* - // Display Light Position - glDisable(GL_LIGHTING); - glDisable(GL_DEPTH_TEST); - glColor3f(1,1,1); - glPointSize(10); - glBegin(GL_POINTS); - glVertex3fv(position); - glEnd(); - glEnable(GL_DEPTH_TEST); - glEnable(GL_LIGHTING); - - - // Display Target - if(lightObject.flags.root || !lightObject.parent) - { - positionVector = light.target.transform.position; - positionVector.Subtract(positionVector, display.camera.cPosition); + position[0] = positionVector.x; + position[1] = positionVector.y; + position[2] = positionVector.z; + + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glColor3f(1,1,0); + glPointSize(10); + glBegin(GL_POINTS); + glVertex3fv(position); + glEnd(); + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); + } + */ } else { - positionVector.MultMatrix(light.target.transform.position, - lightObject.light.target.parent.matrix); - positionVector.Subtract(positionVector, display.camera.cPosition); - } - - position[0] = positionVector.x; - position[1] = positionVector.y; - position[2] = positionVector.z; - - glDisable(GL_LIGHTING); - glDisable(GL_DEPTH_TEST); - glColor3f(1,1,0); - glPointSize(10); - glBegin(GL_POINTS); - glVertex3fv(position); - glEnd(); - glEnable(GL_DEPTH_TEST); - glEnable(GL_LIGHTING); - */ - - if(light.flags.attenuation) - { - glLightf(GL_LIGHT0 + id, GL_CONSTANT_ATTENUATION, light.Kc); - glLightf(GL_LIGHT0 + id, GL_LINEAR_ATTENUATION, light.Kl); - glLightf(GL_LIGHT0 + id, GL_QUADRATIC_ATTENUATION, light.Kq); + // Directional Light + Vector3D vector { 0,0,-1 }; + Vector3D direction; + Matrix mat; + mat.RotationQuaternion(light.orientation); + direction.MultMatrix(vector, mat); + l.Normalize(direction); + position[0] = (float)l.x, position[1] = (float)l.y, position[2] = (float)l.z, position[3] = 0; } - - if(light.flags.spot) + glLightfv(GL_LIGHT0 + id, GL_POSITION, position); + if(display.display3D) { - float exponent = 0; - #define MAXLIGHT 0.9 - float direction[4] = { (float)light.direction.x, (float)light.direction.y, (float)light.direction.z, 1 }; - // Figure out exponent out of the hot spot - exponent = (float)(log(MAXLIGHT) / log(cos((light.hotSpot / 2)))); - - glLightfv(GL_LIGHT0 + id, GL_SPOT_DIRECTION, direction); - glLightf(GL_LIGHT0 + id, GL_SPOT_CUTOFF, (float)(light.fallOff / 2)); - glLightf(GL_LIGHT0 + id, GL_SPOT_EXPONENT, exponent); + Matrix m; + Vector3Df v { position[0], position[1], position[2] }; + Vector3Df l; + float * lp = display.display3D.light0Pos; + if(display.display3D.camera) + m = display.display3D.camera.viewMatrix; + else + m.Identity(); + l.MultMatrix(v, m); + lp[0] = l.x; + lp[1] =-l.y; + lp[2] =-l.z; + lp[3] = position[3]; } } else - { - Vector3Df vector { 0,0,-1 }; - Vector3Df direction; - Matrix mat; - - mat.RotationQuaternion(light.orientation); - direction.MultMatrix(vector, mat); - - position[0] = direction.x; - position[1] = direction.y; - position[2] = direction.z; - - glLightfv(GL_LIGHT0 + id, GL_POSITION, position); - } + glDisable(GL_LIGHT0 + id); } - else - glDisable(GL_LIGHT0 + id); #endif } void SetCamera(Display display, Surface surface, Camera camera) { OGLDisplay oglDisplay = display.driverData; - //Logf("SetCamera\n"); if(surface && camera) { @@ -2838,10 +3084,15 @@ class OpenGLDisplayDriver : DisplayDriver // *** ViewPort *** glViewport(x, y, w, h); + GLMatrixMode(MatrixMode::texture); + if(!display.display3D.camera) + GLPushMatrix(); + GLLoadIdentity(); + // *** Projection Matrix *** - glMatrixMode(MatrixMode::projection); + GLMatrixMode(MatrixMode::projection); if(!display.display3D.camera) - glPushMatrix(); + GLPushMatrix(); if(display.display3D.collectingHits) { @@ -2857,11 +3108,11 @@ class OpenGLDisplayDriver : DisplayDriver (h + 2.0f * (y - pickY)) / display.display3D.pickHeight, 0, 1 } }; - glLoadMatrixd(pickMatrix.array); + GLLoadMatrixd(pickMatrix.array); } else - glLoadIdentity(); - glFrustum( + GLLoadIdentity(); + GLFrustum( (left - origX) * camera.zMin / camera.focalX, (right - origX) * camera.zMin / camera.focalX, (bottom - origY) * camera.zMin / camera.focalY, @@ -2871,148 +3122,599 @@ class OpenGLDisplayDriver : DisplayDriver glDisable(GL_BLEND); // *** Z Inverted Identity Matrix *** - glMatrixMode(MatrixMode::modelView); + GLMatrixMode(MatrixMode::modelView); if(!display.display3D.camera) - glPushMatrix(); + GLPushMatrix(); - glLoadIdentity(); + GLLoadIdentity(); - glScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane); + GLScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane); // *** View Matrix *** - glMultMatrixd(camera.viewMatrix.array); + GLMultMatrixd(camera.viewMatrix.array); + +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + { + defaultShader.select(); + defaultShader.setCamera(camera); + } +#endif // *** Lights *** // ... glEnable(GL_DEPTH_TEST); -#if defined(SHADERS) - shader_lighting(true); -#elif !defined(EM_MODE) - glEnable(GL_LIGHTING); - glShadeModel(GL_SMOOTH); + GLSetupLighting(true); +#if ENABLE_GL_FFP + if(!glCaps_shaders) + glShadeModel(GL_SMOOTH); #endif glDepthMask((byte)bool::true); oglDisplay.depthWrite = true; - glEnable(GL_MULTISAMPLE_ARB); +#ifndef __EMSCRIPTEN__ + glEnable(GL_MULTISAMPLE); +#endif } else if(surface && display.display3D.camera) { + nearPlane = 1; oglDisplay.depthWrite = false; glViewport(0,0,display.width,display.height); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); - GLSetupTexturing(false); -#if defined(SHADERS) - shader_lighting(false); -#elif !defined(EM_MODE) - glDisable(GL_LIGHTING); - glDisable(GL_FOG); - glShadeModel(GL_FLAT); + + GLDisableClientState(COLORS); +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + { + GLDisableClientState(TANGENTS1); + GLDisableClientState(TANGENTS2); + } +#endif + GLDisableClientState(NORMALS); +#if ENABLE_GL_FFP + if(!glCaps_shaders) + GLDisableClientState(LIGHTVECTORS); #endif - glEnable(GL_BLEND); - glDisable(GL_MULTISAMPLE_ARB); // *** Restore 2D MODELVIEW Matrix *** - glPopMatrix(); + GLMatrixMode(MatrixMode::modelView); + GLPopMatrix(); + + // *** Restore 2D TEXTURE Matrix *** + GLMatrixMode(MatrixMode::texture); + GLPopMatrix(); // *** Restore 2D PROJECTION Matrix *** - glMatrixMode(MatrixMode::projection); - glPopMatrix(); - } + GLMatrixMode(MatrixMode::projection); + GLPopMatrix(); + + // NOTE: We expect the 2D projection matrix to be the active one for GetSurface to call glOrtho() + +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + defaultShader.select(); +#endif + +#if ENABLE_GL_FFP + if(!glCaps_shaders) + { + disableRemainingTMUs(display, 0); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glDisable(GL_TEXTURE_CUBE_MAP); + #if _GLES + glDisable(GL_TEXTURE_GEN_STR); + #else + glDisable(GL_TEXTURE_GEN_R); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + #endif + } +#endif + + GLSetupTexturing(false); + GLSetupLighting(false); + GLSetupFog(false); + +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + { + defaultShader.setPerVertexColor(false); + defaultShader.setMaterial(null, 0); + } +#endif +#if ENABLE_GL_FFP + if(!glCaps_shaders) + glShadeModel(GL_FLAT); +#endif + glEnable(GL_BLEND); +#if !defined(__EMSCRIPTEN__) + glDisable(GL_MULTISAMPLE); +#endif + } } void ApplyMaterial(Display display, Material material, Mesh mesh) { - //Logf("ApplyMaterial\n"); + Shader shader = material.shader ? material.shader : defaultShader; + MaterialFlags flags = material.flags; +#if ENABLE_GL_FFP + static int lastSeparate = 0; + int tmu = 0; + bool normalMapped = false; + OGLMesh oglMesh = mesh ? mesh.data : null; +#endif + +#if ENABLE_GL_SHADERS + if(glCaps_shaders && shader) + shader.select(); +#endif // Basic Properties - if(material.flags.doubleSided) + if(flags.doubleSided) { -#if !defined(EM_MODE) && !defined(SHADERS) - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, !material.flags.singleSideLight); +#if ENABLE_GL_FFP + if(!glCaps_shaders) + GLLightModeli(GL_LIGHT_MODEL_TWO_SIDE, !flags.singleSideLight); #endif glDisable(GL_CULL_FACE); } else { -#if !defined(EM_MODE) && !defined(SHADERS) - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, bool::false); +#if ENABLE_GL_FFP + if(!glCaps_shaders) + GLLightModeli(GL_LIGHT_MODEL_TWO_SIDE, bool::false); #endif glEnable(GL_CULL_FACE); } -#if !defined(SHADERS) // Fog - if(material.flags.noFog) - glDisable(GL_FOG); - else - glEnable(GL_FOG); + GLSetupFog(!flags.noFog); + +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + activeShader.setMaterial(material, mesh.flags); #endif +#if ENABLE_GL_FFP + if(!glCaps_shaders) + { + if(material.bumpMap && mesh.lightVectors) + { + float color[4] = { 1,1,1,1 }; + glActiveTexture(GL_TEXTURE0 + tmu); + glClientActiveTexture(GL_TEXTURE0 + tmu++); + glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)material.bumpMap.driverData); + glDisable(GL_TEXTURE_CUBE_MAP); + glEnable(GL_TEXTURE_2D); + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PRIMARY_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + + if(0) //((DefaultShaderBits)defaultShader.state).debugging) + { + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PRIMARY_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color ); + } + + #if _GLES + glDisable(GL_TEXTURE_GEN_STR); + #else + glDisable(GL_TEXTURE_GEN_R); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + #endif + glDisable(GL_LIGHTING); + lightingEnabled = false; + + GLMatrixMode(GL_TEXTURE); + GLLoadIdentity(); + if(material.uScale && material.vScale) + GLScalef(material.uScale, material.vScale, 1); + GLMatrixMode(MatrixMode::modelView); + + if(flags.tile) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } + else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + + glActiveTexture(GL_TEXTURE0 + tmu); + glClientActiveTexture(GL_TEXTURE0 + tmu); + + normalMapped = true; + + // Modulate base color + if(material.diffuse.r < 1 || material.diffuse.g < 1 || material.diffuse.b < 1) + { + tmu++; + glDisable(GL_TEXTURE_CUBE_MAP); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)material.bumpMap.driverData); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); + + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); + + color[0] = material.diffuse.r, color[1] = material.diffuse.g, color[2] = material.diffuse.b, color[3] = 1.0; + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color ); + glActiveTexture(GL_TEXTURE0 + tmu); + glClientActiveTexture(GL_TEXTURE0 + tmu); + } + + // Add ambient light + { + ColorRGB ambient { material.ambient.r * 0.2f, material.ambient.g * 0.2f, material.ambient.g * 0.2f }; + if(ambient.r > 0 || ambient.g > 0 || ambient.b > 0) + { + tmu++; + glDisable(GL_TEXTURE_CUBE_MAP); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)material.bumpMap.driverData); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); + + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); + + color[0] = ambient.r, color[1] = ambient.g, color[2] = ambient.b, color[3] = 1.0; + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color ); + glActiveTexture(GL_TEXTURE0 + tmu); + glClientActiveTexture(GL_TEXTURE0 + tmu); + } + } + } + else + { + GLDisableClientState(LIGHTVECTORS); + if(!lightingEnabled) + { + glEnable(GL_LIGHTING); + lightingEnabled = true; + } + } + } +#endif // Maps - if(material.baseMap && (mesh.texCoords || mesh.flags.texCoords1)) + if(flags.cubeMap || (material.baseMap && (mesh.texCoords || mesh.flags.texCoords1))) { Bitmap map = material.baseMap; - GLSetupTexturing(true); - glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)map.driverData); + int diffuseTarget = flags.cubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - if(material.uScale && material.vScale) - glScalef(material.uScale, material.vScale, 1); - glMatrixMode(MatrixMode::modelView); +#if ENABLE_GL_FFP + if(!glCaps_shaders) + { + glActiveTexture(GL_TEXTURE0 + tmu); + glClientActiveTexture(GL_TEXTURE0 + tmu++); + glEnable(diffuseTarget); + glDisable(flags.cubeMap ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP); + } +#endif + +#if ENABLE_GL_SHADERS + if(glCaps_shaders && !flags.cubeMap) + GLSetupTexturing(true); +#endif + + glBindTexture(diffuseTarget, (GLuint)(uintptr)map.driverData); + +#if ENABLE_GL_FFP + if(!glCaps_shaders) + { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + /* // This did not have the desired effect with a GL_ALPHA texture + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); + */ + + if(flags.cubeMap) + { + #if _GLES + glEnable(GL_TEXTURE_GEN_STR); + // GL_OBJECT_LINEAR: No extension support? + // glTexGeni(GL_TEXTURE_GEN_STR_OES, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + #else + GLfloat xPlane[] = { 1.0f, 0.0f, 0.0f, 0 }; + GLfloat yPlane[] = { 0.0f,-1.0f, 0.0f, 0 }; + GLfloat zPlane[] = { 0.0f, 0.0f,-1.0f, 0 }; + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGenfv(GL_R, GL_OBJECT_PLANE, zPlane); + glTexGenfv(GL_S, GL_OBJECT_PLANE, xPlane); + glTexGenfv(GL_T, GL_OBJECT_PLANE, yPlane); + + glEnable(GL_TEXTURE_GEN_R); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + #endif + + GLDisableClientState(TEXCOORDS); + } + else + { + #if _GLES + glDisable(GL_TEXTURE_GEN_STR); + #else + glDisable(GL_TEXTURE_GEN_R); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + #endif - if(material.flags.tile) + if(tmu > 1) + oglMesh.texCoords.use(texCoord, 2, GL_FLOAT, 0, oglMesh.texCoords.buffer ? null : mesh.texCoords); + GLEnableClientState(TEXCOORDS); + } + glClientActiveTexture(GL_TEXTURE0); + } +#endif + if(flags.tile) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(diffuseTarget, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(diffuseTarget, GL_TEXTURE_WRAP_T, GL_REPEAT); } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(diffuseTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(diffuseTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } } else + { GLSetupTexturing(false); + } -#if defined(SHADERS) - shader_setMaterial(material, mesh.flags.colors); -#elif defined(EM_MODE) - glimtkColor4f(material.diffuse.r, material.diffuse.g, material.diffuse.b, material.opacity); -#else - if(mesh.flags.colors) +#if ENABLE_GL_FFP && !defined(_GLES) + if(!glCaps_shaders) { - glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - glEnable(GL_COLOR_MATERIAL); + int separate = material.flags.separateSpecular ? GL_SEPARATE_SPECULAR_COLOR : GL_SINGLE_COLOR; + if(separate != lastSeparate) + { + GLLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, separate); + lastSeparate = separate; + } } - else +#endif + + if((flags.cubeMap && material.baseMap) || + (mesh.texCoords && (material.baseMap || material.bumpMap || material.specularMap || material.reflectMap))) { - glDisable(GL_COLOR_MATERIAL); +#if ENABLE_GL_FFP + if(!glCaps_shaders) { - float color[4] = { material.diffuse.r, material.diffuse.g, material.diffuse.b, material.opacity }; - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color); + glActiveTexture(GL_TEXTURE0 + tmu - 1); + glClientActiveTexture(GL_TEXTURE0 + tmu - 1); } +#endif + GLMatrixMode(GL_TEXTURE); + GLLoadIdentity(); + if(material.uScale && material.vScale) + GLScalef(material.uScale, material.vScale, 1); + GLMatrixMode(MatrixMode::modelView); +#if ENABLE_GL_FFP + if(!glCaps_shaders) { - float color[4] = { material.ambient.r, material.ambient.g, material.ambient.b, 0 }; - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color); + glActiveTexture(GL_TEXTURE0); + glClientActiveTexture(GL_TEXTURE0); } +#endif } + +#if ENABLE_GL_FFP + if(!glCaps_shaders) { - float color[4] = { material.specular.r, material.specular.g, material.specular.b, 0 }; - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color); + if(material.envMap && material.refractiveIndex) + { + float color[4] = { material.opacity, material.opacity, material.opacity, 1.0 }; + glActiveTexture(GL_TEXTURE0 + tmu); + glClientActiveTexture(GL_TEXTURE0 + tmu++); + glBindTexture(GL_TEXTURE_CUBE_MAP, (GLuint)(uintptr)material.envMap.driverData); + glEnable(GL_TEXTURE_CUBE_MAP); + #if _GLES + glEnable(GL_TEXTURE_GEN_STR); + glTexGeni(GL_TEXTURE_GEN_STR_OES, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + #else + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glEnable(GL_TEXTURE_GEN_R); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + #endif + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + + if(normalMapped) + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); + else + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); + + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); + + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE); + + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); + + if(!normalMapped) + { + glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_ALPHA, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA); + } + + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color ); + + GLMatrixMode(MatrixMode::texture); + { + double * s = display.display3D.camera.viewMatrix.array; + double k = 2.0; + Matrix m + { { + k*s[0],-k*s[4],-k*s[8], 0, + k*s[1],-k*s[5],-k*s[9], 0, + k*s[2],-k*s[6],-k*s[10],0, + 0,0,0,1 + } }; + GLLoadMatrixd(m.array); + } + GLMatrixMode(MatrixMode::modelView); + } + + if(material.envMap && material.reflectivity) + { + float color[4] = { 1.0f - material.reflectivity, 1.0f - material.reflectivity, 1.0f - material.reflectivity, 1.0 }; + glActiveTexture(GL_TEXTURE0 + tmu); + glClientActiveTexture(GL_TEXTURE0 + tmu++); + glBindTexture(GL_TEXTURE_CUBE_MAP, (GLuint)(uintptr)material.envMap.driverData); + glEnable(GL_TEXTURE_CUBE_MAP); + #if _GLES + glEnable(GL_TEXTURE_GEN_STR); + glTexGeni(GL_TEXTURE_GEN_STR_OES, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + #else + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glEnable(GL_TEXTURE_GEN_R); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + #endif + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + + if(normalMapped) + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); + else + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); + + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); + + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); + + if(!normalMapped) + { + glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_ALPHA, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA); + } + + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color ); + + GLMatrixMode(MatrixMode::texture); + { + double * s = display.display3D.camera.inverseTranspose.array; + Matrix m + { { + s[0],s[1],-s[2],0, + s[4],-s[5],-s[6],0, + -s[8],s[9],s[10],0, + 0,0,0,1 + } }; + GLLoadMatrixd(m.array); + } + GLMatrixMode(MatrixMode::modelView); + } } +#endif + +#if ENABLE_GL_FFP + if(!glCaps_shaders) { - float color[4] = { material.emissive.r, material.emissive.g, material.emissive.b, 0 }; - glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color); - } + disableRemainingTMUs(display, tmu); - glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &material.power); + if(mesh.flags.colors) + { + GLColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); + } + else + { + glDisable(GL_COLOR_MATERIAL); + { + float color[4] = { material.diffuse.r, material.diffuse.g, material.diffuse.b, material.opacity }; + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color); + } + { + float color[4] = { material.ambient.r, material.ambient.g, material.ambient.b, 0 }; + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color); + } + } + if(material.power > 0.1) + { + float color[4] = { material.specular.r, material.specular.g, material.specular.b, 0 }; + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color); + } + else + { + float color[4] = { 0,0,0,0 }; + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color); + } + { + float color[4] = { material.emissive.r, material.emissive.g, material.emissive.b, 0 }; + glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color); + } + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &material.power); + } #endif } @@ -3021,6 +3723,10 @@ class OpenGLDisplayDriver : DisplayDriver OGLMesh oglMesh = mesh.data; if(oglMesh) { + OGLSystem oglSystem = displaySystem.driverData; + GLCapabilities caps = glCaps; + SETCAPS(oglSystem.capabilities); + if(!mesh.flags.vertices) { oglMesh.vertices.free(); @@ -3031,6 +3737,16 @@ class OpenGLDisplayDriver : DisplayDriver oglMesh.normals.free(); delete mesh.normals; } + if(!mesh.flags.tangents) + { + oglMesh.tangents.free(); + delete mesh.tangents; + } + if(!mesh.flags.lightVectors) + { + oglMesh.lightVectors.free(); + delete mesh.lightVectors; + } if(!mesh.flags.texCoords1) { oglMesh.texCoords.free(); @@ -3051,6 +3767,7 @@ class OpenGLDisplayDriver : DisplayDriver delete oglMesh; mesh.data = null; } + SETCAPS(caps); } } @@ -3085,6 +3802,14 @@ class OpenGLDisplayDriver : DisplayDriver else mesh.normals = new Vector3Df[nVertices]; } + if(!mesh.flags.tangents && flags.tangents) + { + mesh.tangents = new Vector3Df[2*nVertices]; + } + if(!mesh.flags.lightVectors && flags.lightVectors) + { + mesh.lightVectors = new ColorRGB[nVertices]; + } if(!mesh.flags.texCoords1 && flags.texCoords1) { mesh.texCoords = new Pointf[nVertices]; @@ -3125,6 +3850,14 @@ class OpenGLDisplayDriver : DisplayDriver { mesh.colors = renew mesh.colors ColorRGBAf[nVertices]; } + if(flags.tangents) + { + mesh.tangents = renew mesh.tangents Vector3Df[2 * nVertices]; + } + if(flags.lightVectors) + { + mesh.lightVectors = renew mesh.lightVectors ColorRGB[nVertices]; + } } result = true; } @@ -3133,27 +3866,37 @@ class OpenGLDisplayDriver : DisplayDriver void UnlockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags) { - OGLMesh oglMesh = mesh.data; - if(!flags) flags = mesh.flags; + OGLSystem oglSystem = displaySystem.driverData; + GLCapabilities caps = glCaps; + SETCAPS(oglSystem.capabilities); - if(vboAvailable) + if(glCaps_vertexBuffer) { + OGLMesh oglMesh = mesh.data; + if(!flags) flags = mesh.flags; if(flags.vertices) - oglMesh.vertices.upload( - mesh.nVertices * (mesh.flags.doubleVertices ? sizeof(Vector3D) : sizeof(Vector3Df)), mesh.vertices); //, GL_STATIC_DRAW_ARB ); + oglMesh.vertices.allocate( + mesh.nVertices * (mesh.flags.doubleVertices ? sizeof(Vector3D) : sizeof(Vector3Df)), mesh.vertices, staticDraw); if(flags.normals) - oglMesh.normals.upload( - mesh.nVertices * (mesh.flags.doubleNormals ? sizeof(Vector3D) : sizeof(Vector3Df)), mesh.normals); //, GL_STATIC_DRAW_ARB ); + oglMesh.normals.allocate( + mesh.nVertices * (mesh.flags.doubleNormals ? sizeof(Vector3D) : sizeof(Vector3Df)), mesh.normals, staticDraw); if(flags.texCoords1) - oglMesh.texCoords.upload( - mesh.nVertices * sizeof(Pointf), mesh.texCoords); //, GL_STATIC_DRAW_ARB ); + oglMesh.texCoords.allocate( + mesh.nVertices * sizeof(Pointf), mesh.texCoords, staticDraw); if(flags.colors) - oglMesh.colors.upload( - mesh.nVertices * sizeof(ColorRGBAf), mesh.colors); //, GL_STATIC_DRAW_ARB ); + oglMesh.colors.allocate( + mesh.nVertices * sizeof(ColorRGBAf), mesh.colors, staticDraw); + + if(flags.tangents) + oglMesh.tangents.allocate(mesh.nVertices * 2*sizeof(Vector3Df), mesh.tangents, staticDraw); + + if(flags.lightVectors) + oglMesh.lightVectors.allocate(mesh.nVertices * sizeof(ColorRGB), mesh.lightVectors, staticDraw); } + SETCAPS(caps); } bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags) @@ -3165,12 +3908,17 @@ class OpenGLDisplayDriver : DisplayDriver void FreeIndices(DisplaySystem displaySystem, OGLIndices oglIndices) { + OGLSystem oglSystem = displaySystem.driverData; + GLCapabilities caps = glCaps; + SETCAPS(oglSystem.capabilities); + if(oglIndices) { oglIndices.buffer.free(); delete oglIndices.indices; delete oglIndices; } + SETCAPS(caps); } void * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit) @@ -3186,23 +3934,41 @@ class OpenGLDisplayDriver : DisplayDriver void UnlockIndices(DisplaySystem displaySystem, OGLIndices oglIndices, bool indices32bit, int nIndices) { - if(vboAvailable) + OGLSystem oglSystem = displaySystem.driverData; + GLCapabilities caps = glCaps; + SETCAPS(oglSystem.capabilities); + + if(glCaps_vertexBuffer) { -#ifdef ES1_1 - if(indices32bit) + if(!glCaps_intAndDouble && indices32bit) { if(!oglIndices.buffer.buffer) glGenBuffers(1, &oglIndices.buffer.buffer); if(glabCurElementBuffer != oglIndices.buffer.buffer) GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, oglIndices.buffer.buffer); - glimtkBufferDatai(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32) * nIndices, oglIndices.indices, GL_STATIC_DRAW_ARB); + + { + uint * pointer = (uint *)oglIndices.indices; + int i; + uint16 * b; + if(nIndices > oglSystem.shortBDSize) + { + oglSystem.shortBDSize = nIndices; + oglSystem.shortBDBuffer = renew oglSystem.shortBDBuffer uint16[oglSystem.shortBDSize]; + } + b = oglSystem.shortBDBuffer; + for(i = 0; i < nIndices; i++) + b[i] = (uint16)pointer[i]; + + glBufferData(GL_ELEMENT_ARRAY_BUFFER, nIndices * sizeof(uint16), b, GL_STATIC_DRAW); + } } else -#endif - oglIndices.buffer.upload( - nIndices * (indices32bit ? sizeof(uint32) : sizeof(uint16)), - oglIndices.indices); //GL_STATIC_DRAW_ARB); + oglIndices.buffer.allocate( + nIndices * (indices32bit ? sizeof(uint32) : sizeof(uint16)), + oglIndices.indices, staticDraw); } + SETCAPS(caps); } uint16 * LockIndices(DisplaySystem displaySystem, OGLIndices oglIndices) @@ -3213,23 +3979,19 @@ class OpenGLDisplayDriver : DisplayDriver void SelectMesh(Display display, Mesh mesh) { - //Logf("SelectMesh\n"); - #if !defined( __ANDROID__) && !defined(__APPLE__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__) - #if defined(__WIN32__) if(glUnlockArraysEXT) #endif - if(!vboAvailable && display.display3D.mesh) + if(!glCaps_vertexBuffer && display.display3D.mesh) glUnlockArraysEXT(); - #endif if(mesh) { OGLMesh oglMesh = mesh.data; // *** Vertex Stream *** - glEnableClientState(GL_VERTEX_ARRAY); + GLEnableClientState(VERTICES); if(!display.display3D.collectingHits && oglMesh) { oglMesh.vertices.use(vertex, 3, (mesh.flags.doubleVertices ? GL_DOUBLE : GL_FLOAT), 0, oglMesh.vertices.buffer ? null : (double *)mesh.vertices); @@ -3237,54 +3999,119 @@ class OpenGLDisplayDriver : DisplayDriver // *** Normals Stream *** if(mesh.normals || mesh.flags.normals) { - glEnableClientState(GL_NORMAL_ARRAY); + GLEnableClientState(NORMALS); oglMesh.normals.use(normal, 3, GL_FLOAT, 0, oglMesh.normals.buffer ? null : mesh.normals); } else - glDisableClientState(GL_NORMAL_ARRAY); + GLDisableClientState(NORMALS); + +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + { + // *** Tangents Stream *** + if(mesh.tangents || mesh.flags.tangents) + { + GLEnableClientState(TANGENTS1); + GLEnableClientState(TANGENTS2); + oglMesh.tangents.use(tangent1, 3, GL_FLOAT, sizeof(Vector3Df)*2, oglMesh.tangents.buffer ? null : mesh.tangents); + oglMesh.tangents.use(tangent2, 3, GL_FLOAT, sizeof(Vector3Df)*2, oglMesh.tangents.buffer ? (void *)sizeof(Vector3Df) : mesh.tangents+1); + } + else + { + GLDisableClientState(TANGENTS1); + GLDisableClientState(TANGENTS2); + } + } +#endif // *** Texture Coordinates Stream *** if(mesh.texCoords || mesh.flags.texCoords1) { - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + GLEnableClientState(TEXCOORDS); oglMesh.texCoords.use(texCoord, 2, GL_FLOAT, 0, oglMesh.texCoords.buffer ? null : mesh.texCoords); } else - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + GLDisableClientState(TEXCOORDS); +#if ENABLE_GL_FFP + if(!glCaps_shaders) + { + // *** Normal Map Aligned Light Vector *** + if(mesh.lightVectors || mesh.flags.lightVectors) + { + GLEnableClientState(LIGHTVECTORS); + oglMesh.lightVectors.use(lightVector, 3, GL_FLOAT, 0, oglMesh.lightVectors.buffer ? null : mesh.lightVectors); + } + else + GLDisableClientState(LIGHTVECTORS); + } + else +#endif // *** Color Stream *** if(mesh.colors || mesh.flags.colors) { - glEnableClientState(GL_COLOR_ARRAY); + GLEnableClientState(COLORS); oglMesh.colors.use(color, 4, GL_FLOAT, 0, oglMesh.colors.buffer ? null : mesh.colors); } else - glDisableClientState(GL_COLOR_ARRAY); + GLDisableClientState(COLORS); } else { noAB.use(vertex, 3, (mesh.flags.doubleVertices ? GL_DOUBLE : GL_FLOAT), 0, (double *)mesh.vertices); if((mesh.normals || mesh.flags.normals) && !display.display3D.collectingHits) { - glEnableClientState(GL_NORMAL_ARRAY); + GLEnableClientState(NORMALS); noAB.use(normal, 3, GL_FLOAT, 0, mesh.normals); } else - glDisableClientState(GL_NORMAL_ARRAY); + GLDisableClientState(NORMALS); +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + { + if((mesh.tangents || mesh.flags.tangents) && !display.display3D.collectingHits) + { + GLEnableClientState(TANGENTS1); + GLEnableClientState(TANGENTS2); + noAB.use(tangent1, 3, GL_FLOAT, sizeof(Vector3Df)*2, mesh.tangents); + noAB.use(tangent2, 3, GL_FLOAT, sizeof(Vector3Df)*2, mesh.tangents+1); + } + else + { + GLDisableClientState(TANGENTS1); + GLDisableClientState(TANGENTS2); + } + } +#endif + if((mesh.texCoords || mesh.flags.texCoords1) && !display.display3D.collectingHits) { - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + GLEnableClientState(TEXCOORDS); noAB.use(texCoord, 2, GL_FLOAT, 0, mesh.texCoords); } else - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + GLDisableClientState(TEXCOORDS); + +#if ENABLE_GL_FFP + if(!glCaps_shaders) + { + if((mesh.lightVectors || mesh.flags.lightVectors) && !display.display3D.collectingHits) + { + GLEnableClientState(LIGHTVECTORS); + noAB.use(lightVector, 3, GL_FLOAT, sizeof(ColorRGB), mesh.lightVectors); + } + else + GLDisableClientState(LIGHTVECTORS); + } + else +#endif if((mesh.colors || mesh.flags.colors) && !display.display3D.collectingHits) { - glEnableClientState(GL_COLOR_ARRAY); + GLEnableClientState(COLORS); noAB.use(color, 4, GL_FLOAT, 0, mesh.colors); } else - glDisableClientState(GL_COLOR_ARRAY); + GLDisableClientState(COLORS); } #if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__) @@ -3292,67 +4119,49 @@ class OpenGLDisplayDriver : DisplayDriver #if defined(__WIN32__) if(glLockArraysEXT) #endif - if(!vboAvailable) + if(!glCaps_vertexBuffer) glLockArraysEXT(0, mesh.nVertices); - #endif } } void DrawPrimitives(Display display, PrimitiveSingle * primitive, Mesh mesh) { - //Logf("DrawPrimitives\n"); - if(primitive->type.vertexRange) - glDrawArrays(primitiveTypes[primitive->type.primitiveType], primitive->first, primitive->nVertices); + { + GLFlushMatrices(); + glDrawArrays(getPrimitiveType(primitive->type.primitiveType), primitive->first, primitive->nVertices); + } else { - // *** Hoping the data won't be uploaded at all (Won't really work if another group of the mesh is using the mesh ) *** - // HACK TO SPEED THINGS UP... -#ifndef __ANDROID__ - /*GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); - if(primitive->nIndices < (mesh.nVertices >> 2) && !primitive->type.indices32bit) + OGLIndices oglIndices = primitive->data; + GLEAB eab = ((!display.display3D.collectingHits && oglIndices && glCaps_vertexBuffer) ? oglIndices.buffer : noEAB); + if(!glCaps_intAndDouble && !glCaps_vertexBuffer && primitive->type.indices32bit) { - int c; - glBegin((GLIMTKMode)primitiveTypes[primitive->type.primitiveType]); - if(primitive->data) - { - OGLIndices oglIndices = primitive->data; - MeshFeatures flags = mesh.flags; - for(c = 0; cnIndices; c++) - { - uint16 index = ((uint16 *) oglIndices.indices)[c]; - if(flags.normals) glNormal3fv((float *)&mesh.normals[index]); - if(flags.texCoords1) glTexCoord2fv((float *)&mesh.texCoords[index]); - if(flags.colors) glColor4fv((float *)&mesh.colors[index]); - glVertex3fv((float *)&mesh.vertices[index]); - } - } - glEnd(); + uint16 * temp = new uint16[primitive->nIndices]; + uint32 * src = (uint32 *)(oglIndices ? oglIndices.indices : primitive->indices); + int i; + for(i = 0; i < primitive->nIndices; i++) + temp[i] = (uint16)src[i]; + eab.draw(getPrimitiveType(primitive->type.primitiveType), primitive->nIndices, GL_UNSIGNED_SHORT, temp); + delete temp; } - else*/ -#endif - - { - OGLIndices oglIndices = primitive->data; - GLEAB eab = ((!display.display3D.collectingHits && oglIndices) ? oglIndices.buffer : noEAB); - - eab.draw(primitiveTypes[primitive->type.primitiveType], primitive->nIndices, + else + eab.draw(getPrimitiveType(primitive->type.primitiveType), primitive->nIndices, primitive->type.indices32bit ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, eab.buffer ? 0 : (oglIndices ? oglIndices.indices : primitive->indices)); - GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } + GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } } void PushMatrix(Display display) { - glPushMatrix(); + GLPushMatrix(); } void PopMatrix(Display display, bool setMatrix) { - glPopMatrix(); + GLPopMatrix(); } void SetTransform(Display display, Matrix transMatrix, bool viewSpace, bool useCamera) @@ -3362,18 +4171,18 @@ class OpenGLDisplayDriver : DisplayDriver if(viewSpace) { - glLoadIdentity(); - glScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane); + GLLoadIdentity(); + GLScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane); } else if(camera) { - glTranslated( + GLTranslated( matrix.m[3][0] - camera.cPosition.x, matrix.m[3][1] - camera.cPosition.y, matrix.m[3][2] - camera.cPosition.z); } else - glTranslated( + GLTranslated( matrix.m[3][0], matrix.m[3][1], matrix.m[3][2]); @@ -3382,7 +4191,7 @@ class OpenGLDisplayDriver : DisplayDriver matrix.m[3][1] = 0; matrix.m[3][2] = 0; - glMultMatrixd(matrix.array); + GLMultMatrixd(matrix.array); } #endif } @@ -3406,6 +4215,8 @@ IS_GLGetContext(DisplaySystem displaySystem) #elif defined(__ANDROID__) || defined(__ODROID__) return eglContext; #elif defined(__EMSCRIPTEN__) + OGLSystem system = displaySystem.driverData; + return (void *)system.glc; #else OGLSystem system = displaySystem.driverData; return system.glContext;