1 #ifndef H_GAPI_GL 2 #define H_GAPI_GL 3 4 #include "core.h" 5 6 #if defined(_DEBUG) || defined(PROFILE) 7 //#define _DEBUG_SHADERS "../../OpenLara/src/shaders/" 8 #endif 9 10 #ifdef _OS_WIN 11 #include <gl/GL.h> 12 #include <gl/glext.h> 13 #include <gl/wglext.h> 14 #elif _OS_ANDROID 15 #include <dlfcn.h> 16 17 // #define _GAPI_GLES2 // for old devices 18 19 #ifdef _GAPI_GLES2 20 #include <GLES2/gl2.h> 21 #include <GLES2/gl2ext.h> 22 23 #define GL_CLAMP_TO_BORDER 0x812D 24 #define GL_TEXTURE_BORDER_COLOR 0x1004 25 26 #define GL_TEXTURE_COMPARE_MODE 0x884C 27 #define GL_TEXTURE_COMPARE_FUNC 0x884D 28 #define GL_COMPARE_REF_TO_TEXTURE 0x884E 29 30 #undef GL_RG 31 #undef GL_RG32F 32 #undef GL_RG16F 33 #undef GL_RGBA32F 34 #undef GL_RGBA16F 35 #undef GL_HALF_FLOAT 36 37 #define GL_RG GL_RGBA 38 #define GL_RGBA32F GL_RGBA 39 #define GL_RGBA16F GL_RGBA 40 #define GL_RG32F GL_RGBA 41 #define GL_RG16F GL_RGBA 42 #define GL_HALF_FLOAT GL_HALF_FLOAT_OES 43 44 #define GL_TEXTURE_3D 0 45 #define GL_TEXTURE_WRAP_R 0 46 #define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES 47 #define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES 48 49 #define glTexImage3D(...) 0 50 51 #define glGenVertexArrays(...) 52 #define glDeleteVertexArrays(...) 53 #define glBindVertexArray(...) 54 55 #define GL_PROGRAM_BINARY_LENGTH GL_PROGRAM_BINARY_LENGTH_OES 56 #define glGetProgramBinary(...) 57 #define glProgramBinary(...) 58 59 #define glInvalidateFramebuffer(...) 60 #else 61 #include <GLES3/gl3.h> 62 #include <GLES3/gl3ext.h> 63 #include <GLES2/gl2ext.h> 64 #endif 65 66 #elif defined(__SDL2__) 67 #include <SDL2/SDL.h> 68 69 #if defined(_GAPI_GLES) // Default in SDL2 is GLES3. If we want GLES2, pass -D_GAPI_GLES2. 70 #if defined (_GAPI_GLES2) // We want GLES2 on SDL2 71 #include <SDL2/SDL_opengles2.h> 72 #include <SDL2/SDL_opengles2_gl2ext.h> 73 74 #define GL_CLAMP_TO_BORDER 0x812D 75 #define GL_TEXTURE_BORDER_COLOR 0x1004 76 77 #define GL_TEXTURE_COMPARE_MODE 0x884C 78 #define GL_TEXTURE_COMPARE_FUNC 0x884D 79 #define GL_COMPARE_REF_TO_TEXTURE 0x884E 80 81 #undef GL_RG 82 #undef GL_RG32F 83 #undef GL_RG16F 84 #undef GL_RGBA32F 85 #undef GL_RGBA16F 86 #undef GL_HALF_FLOAT 87 88 #define GL_RG GL_RGBA 89 #define GL_RGBA32F GL_RGBA 90 #define GL_RGBA16F GL_RGBA 91 #define GL_RG32F GL_RGBA 92 #define GL_RG16F GL_RGBA 93 #define GL_HALF_FLOAT GL_HALF_FLOAT_OES 94 95 #define GL_TEXTURE_WRAP_R 0 96 #define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES 97 #define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES 98 //We need this on GLES2, too. 99 #define GL_TEXTURE_MAX_LEVEL GL_TEXTURE_MAX_LEVEL_APPLE 100 101 #define glTexImage3D(...) 0 102 #ifndef GL_TEXTURE_3D // WUUUUUT!? 103 #define GL_TEXTURE_3D GL_TEXTURE_3D_OES 104 #endif 105 106 #define GL_PROGRAM_BINARY_LENGTH GL_PROGRAM_BINARY_LENGTH_OES 107 #else // We want GLES3 on SDL2 108 #include <GLES3/gl3.h> 109 #include <GLES3/gl3ext.h> 110 #include <GLES2/gl2ext.h> 111 #endif //GAPI_GLES2 112 113 // These are needed for both GLES2 and GLES3 on SDL2 114 #define glGenVertexArrays(...) 115 #define glDeleteVertexArrays(...) 116 #define glBindVertexArray(...) 117 #define glGetProgramBinary(...) 118 #define glProgramBinary(...) 119 120 #define PFNGLGENVERTEXARRAYSPROC PFNGLGENVERTEXARRAYSOESPROC 121 #define PFNGLDELETEVERTEXARRAYSPROC PFNGLDELETEVERTEXARRAYSOESPROC 122 #define PFNGLBINDVERTEXARRAYPROC PFNGLBINDVERTEXARRAYOESPROC 123 #define PFNGLGETPROGRAMBINARYPROC PFNGLGETPROGRAMBINARYOESPROC 124 #define PFNGLPROGRAMBINARYPROC PFNGLPROGRAMBINARYOESPROC 125 126 #else // We want OpenGL on SDL2, not GLES 127 #include <SDL2/SDL_opengl.h> 128 #include <SDL2/SDL_opengl_glext.h> 129 #endif 130 131 #elif defined(_OS_PSC) 132 #include <GLES3/gl3.h> 133 #include <GLES2/gl2ext.h> 134 extern EGLDisplay display; 135 #elif defined(_OS_GCW0) 136 #include <GLES2/gl2.h> 137 #include <GLES2/gl2ext.h> 138 #include <EGL/egl.h> 139 #include <EGL/eglext.h> 140 141 #define GL_TEXTURE_MAX_LEVEL GL_TEXTURE_MAX_LEVEL_APPLE 142 #define GL_TEXTURE_3D 0 143 #define GL_TEXTURE_WRAP_R 0 144 #define GL_TEXTURE_COMPARE_MODE 0x884C 145 #define GL_TEXTURE_COMPARE_FUNC 0x884D 146 #define GL_COMPARE_REF_TO_TEXTURE 0x884E 147 148 #undef GL_RG 149 #undef GL_RG32F 150 #undef GL_RG16F 151 #undef GL_RGBA32F 152 #undef GL_RGBA16F 153 #undef GL_HALF_FLOAT 154 155 #define GL_RG GL_RGBA 156 #define GL_RGBA32F GL_RGBA 157 #define GL_RGBA16F GL_RGBA 158 #define GL_RG32F GL_RGBA 159 #define GL_RG16F GL_RGBA 160 #define GL_HALF_FLOAT GL_HALF_FLOAT_OES 161 162 #define glTexImage3D(...) 0 163 164 #define GL_PROGRAM_BINARY_LENGTH GL_PROGRAM_BINARY_LENGTH_OES 165 166 #define PFNGLGENVERTEXARRAYSPROC PFNGLGENVERTEXARRAYSOESPROC 167 #define PFNGLDELETEVERTEXARRAYSPROC PFNGLDELETEVERTEXARRAYSOESPROC 168 #define PFNGLBINDVERTEXARRAYPROC PFNGLBINDVERTEXARRAYOESPROC 169 #define PFNGLGETPROGRAMBINARYPROC PFNGLGETPROGRAMBINARYOESPROC 170 #define PFNGLPROGRAMBINARYPROC PFNGLPROGRAMBINARYOESPROC 171 172 #define glGenVertexArrays glGenVertexArraysOES 173 #define glDeleteVertexArrays glDeleteVertexArraysOES 174 #define glBindVertexArray glBindVertexArrayOES 175 #define glGetProgramBinary glGetProgramBinaryOES 176 #define glProgramBinary glProgramBinaryOES 177 178 extern EGLDisplay display; 179 #elif defined(_OS_RPI) || defined(_OS_CLOVER) 180 #include <GLES2/gl2.h> 181 #include <GLES2/gl2ext.h> 182 #include <EGL/egl.h> 183 #include <EGL/eglext.h> 184 185 #define GL_CLAMP_TO_BORDER 0x812D 186 #define GL_TEXTURE_BORDER_COLOR 0x1004 187 #define GL_TEXTURE_MAX_LEVEL GL_TEXTURE_MAX_LEVEL_APPLE 188 #define GL_TEXTURE_COMPARE_MODE 0x884C 189 #define GL_TEXTURE_COMPARE_FUNC 0x884D 190 #define GL_COMPARE_REF_TO_TEXTURE 0x884E 191 192 #undef GL_RG 193 #undef GL_RG32F 194 #undef GL_RG16F 195 #undef GL_RGBA32F 196 #undef GL_RGBA16F 197 #undef GL_HALF_FLOAT 198 199 #define GL_RG GL_RGBA 200 #define GL_RGBA32F GL_RGBA 201 #define GL_RGBA16F GL_RGBA 202 #define GL_RG32F GL_RGBA 203 #define GL_RG16F GL_RGBA 204 #define GL_HALF_FLOAT GL_HALF_FLOAT_OES 205 206 #define GL_TEXTURE_3D 0 207 #define GL_TEXTURE_WRAP_R 0 208 #define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES 209 #define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES 210 211 #define glTexImage3D(...) 0 212 213 #define glGenVertexArrays(...) 214 #define glDeleteVertexArrays(...) 215 #define glBindVertexArray(...) 216 217 #define GL_PROGRAM_BINARY_LENGTH GL_PROGRAM_BINARY_LENGTH_OES 218 #define glGetProgramBinary(...) 219 #define glProgramBinary(...) 220 221 extern EGLDisplay display; 222 #elif _OS_SWITCH 223 #define GL_GLEXT_PROTOTYPES 224 #include <EGL/egl.h> 225 #include <EGL/eglext.h> 226 #include <GL/gl.h> 227 #include <GL/glext.h> 228 229 extern EGLDisplay display; 230 #elif _OS_LINUX 231 #include <GL/gl.h> 232 #include <GL/glext.h> 233 #include <GL/glx.h> 234 #elif __APPLE__ 235 #ifdef _OS_IOS 236 #include <OpenGLES/ES2/gl.h> 237 #include <OpenGLES/ES2/glext.h> 238 #include <OpenGLES/ES3/glext.h> 239 240 #define PFNGLGENVERTEXARRAYSPROC PFNGLGENVERTEXARRAYSOESPROC 241 #define PFNGLDELETEVERTEXARRAYSPROC PFNGLDELETEVERTEXARRAYSOESPROC 242 #define PFNGLBINDVERTEXARRAYPROC PFNGLBINDVERTEXARRAYOESPROC 243 #define glGenVertexArrays glGenVertexArraysOES 244 #define glDeleteVertexArrays glDeleteVertexArraysOES 245 #define glBindVertexArray glBindVertexArrayOES 246 247 #define GL_CLAMP_TO_BORDER 0x812D 248 #define GL_TEXTURE_BORDER_COLOR 0x1004 249 250 // TODO: WTF? 251 #undef GL_RG 252 #undef GL_RGBA32F 253 #undef GL_RGBA16F 254 #undef GL_RG32F 255 #undef GL_RG16F 256 #undef GL_HALF_FLOAT 257 258 #define GL_RG GL_RGBA 259 #define GL_RG16F GL_RGBA 260 #define GL_RG32F GL_RGBA 261 #define GL_RGBA32F GL_RGBA 262 #define GL_RGBA16F GL_RGBA 263 #define GL_HALF_FLOAT GL_HALF_FLOAT_OES 264 265 //#define GL_TEXTURE_COMPARE_MODE GL_TEXTURE_COMPARE_MODE_EXT 266 //#define GL_TEXTURE_COMPARE_FUNC GL_TEXTURE_COMPARE_FUNC_EXT 267 //#define GL_COMPARE_REF_TO_TEXTURE GL_COMPARE_REF_TO_TEXTURE_EXT 268 #else 269 #include <Carbon/Carbon.h> 270 #include <AudioToolbox/AudioQueue.h> 271 #include <OpenGL/OpenGL.h> 272 #include <OpenGL/gl.h> 273 #include <OpenGL/glext.h> 274 #include <AGL/agl.h> 275 276 #define GL_RG 0x8227 277 #define GL_RG16F 0x822F 278 #define GL_RG32F 0x8230 279 #define GL_RGBA16F 0x881A 280 #define GL_RGBA32F 0x8814 281 #define GL_HALF_FLOAT 0x140B 282 283 #define GL_RGB565 GL_RGBA 284 #define GL_TEXTURE_COMPARE_MODE 0x884C 285 #define GL_TEXTURE_COMPARE_FUNC 0x884D 286 #define GL_COMPARE_REF_TO_TEXTURE 0x884E 287 288 #define glGenVertexArrays glGenVertexArraysAPPLE 289 #define glDeleteVertexArrays glDeleteVertexArraysAPPLE 290 #define glBindVertexArray glBindVertexArrayAPPLE 291 292 #define GL_PROGRAM_BINARY_LENGTH 0 293 #define glGetProgramBinary(...) 0 294 #define glProgramBinary(...) 0 295 #endif 296 #elif _OS_WEB 297 #include <emscripten/emscripten.h> 298 #include <emscripten/html5.h> 299 #include <GLES/gl.h> 300 #include <GLES3/gl3.h> 301 #include <GLES3/gl2ext.h> 302 303 #define GL_CLAMP_TO_BORDER GL_CLAMP_TO_BORDER_EXT 304 #define GL_TEXTURE_BORDER_COLOR GL_TEXTURE_BORDER_COLOR_EXT 305 306 #define glGetProgramBinary(...) 307 #define glProgramBinary(...) 308 #endif 309 310 #if defined(_OS_WIN) || defined(_OS_LINUX) || defined(_OS_GCW0) || (defined(__SDL2__) && (defined(_GAPI_GLES2) || defined(_SDL2_OPENGL))) 311 GetProc(const char * name)312 void* GetProc(const char *name) { 313 #ifdef _OS_WIN 314 return (void*)wglGetProcAddress(name); 315 #elif _OS_LINUX 316 return (void*)glXGetProcAddress((GLubyte*)name); 317 #elif __SDL2__ 318 return (void*)SDL_GL_GetProcAddress(name); 319 #else // EGL 320 return (void*)eglGetProcAddress(name); 321 #endif 322 } 323 324 #define GetProcOGL(x) x=(decltype(x))GetProc(#x) 325 326 // TODO: different systems, different headers, different extension suffixes... fuck this shit and make your own OGL header! 327 328 // Texture 329 #ifdef _OS_WIN 330 PFNGLACTIVETEXTUREPROC glActiveTexture; 331 #endif 332 333 // VSync 334 #ifdef _OS_WIN 335 typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); 336 PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; 337 #elif _OS_LINUX 338 typedef int (*PFNGLXSWAPINTERVALSGIPROC) (int interval); 339 PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI; 340 #endif 341 342 #if defined(_OS_WIN) || defined(_OS_LINUX) || (defined(__SDL2__) && !defined(_GAPI_GLES2)) 343 PFNGLGENERATEMIPMAPPROC glGenerateMipmap; 344 #ifdef _OS_WIN 345 PFNGLTEXIMAGE3DPROC glTexImage3D; 346 #endif 347 PFNGLGETSTRINGIPROC glGetStringi; 348 // Profiling 349 #ifdef PROFILE 350 PFNGLOBJECTLABELPROC glObjectLabel; 351 PFNGLPUSHDEBUGGROUPPROC glPushDebugGroup; 352 PFNGLPOPDEBUGGROUPPROC glPopDebugGroup; 353 PFNGLGENQUERIESPROC glGenQueries; 354 PFNGLDELETEQUERIESPROC glDeleteQueries; 355 PFNGLGETQUERYOBJECTIVPROC glGetQueryObjectiv; 356 PFNGLBEGINQUERYPROC glBeginQuery; 357 PFNGLENDQUERYPROC glEndQuery; 358 #endif 359 // Shader 360 PFNGLCREATEPROGRAMPROC glCreateProgram; 361 PFNGLDELETEPROGRAMPROC glDeleteProgram; 362 PFNGLLINKPROGRAMPROC glLinkProgram; 363 PFNGLUSEPROGRAMPROC glUseProgram; 364 PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog; 365 PFNGLCREATESHADERPROC glCreateShader; 366 PFNGLDELETESHADERPROC glDeleteShader; 367 PFNGLSHADERSOURCEPROC glShaderSource; 368 PFNGLATTACHSHADERPROC glAttachShader; 369 PFNGLCOMPILESHADERPROC glCompileShader; 370 PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; 371 PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation; 372 PFNGLUNIFORM1IVPROC glUniform1iv; 373 PFNGLUNIFORM1FVPROC glUniform1fv; 374 PFNGLUNIFORM2FVPROC glUniform2fv; 375 PFNGLUNIFORM3FVPROC glUniform3fv; 376 PFNGLUNIFORM4FVPROC glUniform4fv; 377 PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv; 378 PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation; 379 PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray; 380 PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray; 381 PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer; 382 PFNGLGETPROGRAMIVPROC glGetProgramiv; 383 // Render to texture 384 PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; 385 PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer; 386 PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers; 387 PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer; 388 PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; 389 PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer; 390 PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage; 391 PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus; 392 PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; 393 PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers; 394 PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv; 395 // Mesh 396 PFNGLGENBUFFERSARBPROC glGenBuffers; 397 PFNGLDELETEBUFFERSARBPROC glDeleteBuffers; 398 PFNGLBINDBUFFERARBPROC glBindBuffer; 399 PFNGLBUFFERDATAARBPROC glBufferData; 400 PFNGLBUFFERSUBDATAARBPROC glBufferSubData; 401 #endif 402 403 // Vertex Arrays 404 PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; 405 PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; 406 PFNGLBINDVERTEXARRAYPROC glBindVertexArray; 407 // Binary shaders 408 PFNGLGETPROGRAMBINARYPROC glGetProgramBinary; 409 PFNGLPROGRAMBINARYPROC glProgramBinary; 410 411 #if defined(_GAPI_GLES) 412 PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; 413 #endif 414 #endif 415 416 #ifdef PROFILE 417 //#define USE_CV_MARKERS 418 419 #ifdef USE_CV_MARKERS 420 #include <libs/cvmarkers/cvmarkersobj.h> 421 using namespace Concurrency::diagnostic; 422 423 marker_series *series[256]; 424 int seriesIndex; 425 #endif 426 427 struct Marker { 428 #ifdef USE_CV_MARKERS 429 span *cvSpan; 430 #endif 431 MarkerMarker432 Marker(const char *title) { 433 if (Core::support.profMarker) glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, title); 434 #ifdef USE_CV_MARKERS 435 marker_series *&s = series[seriesIndex]; 436 if (s == NULL) { 437 char seriesTitle[64]; 438 sprintf(seriesTitle, "events - %d", seriesIndex); 439 s = new marker_series(seriesTitle); 440 } 441 cvSpan = new span(*s, normal_importance, _T(title)); 442 seriesIndex++; 443 #endif 444 } 445 ~MarkerMarker446 ~Marker() { 447 if (Core::support.profMarker) glPopDebugGroup(); 448 #ifdef USE_CV_MARKERS 449 delete cvSpan; 450 seriesIndex--; 451 #endif 452 } 453 setLabelMarker454 static void setLabel(GLenum id, GLuint name, const char *label) { 455 if (Core::support.profMarker) glObjectLabel(id, name, -1, label); 456 } 457 }; 458 459 struct Timing { 460 GLuint ID; 461 int &result; 462 TimingTiming463 Timing(int &result) : result(result) { 464 if (!Core::support.profTiming) return; 465 glGenQueries(1, &ID); 466 glBeginQuery(GL_TIME_ELAPSED, ID); 467 } 468 ~TimingTiming469 ~Timing() { 470 if (!Core::support.profTiming) return; 471 glEndQuery(GL_TIME_ELAPSED); 472 glGetQueryObjectiv(ID, GL_QUERY_RESULT, (GLint*)&result); 473 glDeleteQueries(1, &ID); 474 } 475 }; 476 477 #define PROFILE_MARKER(title) Marker marker(title) 478 #define PROFILE_LABEL(id, name, label) Marker::setLabel(GL_##id, name, label) 479 #define PROFILE_TIMING(result) Timing timing(result) 480 #else 481 #define PROFILE_MARKER(title) 482 #define PROFILE_LABEL(id, name, label) 483 #define PROFILE_TIMING(time) 484 #endif 485 486 487 namespace GAPI { 488 489 using namespace Core; 490 491 typedef ::Vertex Vertex; 492 493 int cullMode, blendMode; 494 bool depthWrite; 495 496 char GLSL_HEADER_VERT[512]; 497 char GLSL_HEADER_FRAG[512]; 498 499 bool GL_VER_3 = false; 500 501 // Shader 502 #ifndef FFP 503 const char SHADER_COMPOSE[] = 504 #include "../shaders/compose.glsl" 505 ; 506 507 const char SHADER_SHADOW[] = 508 #include "../shaders/shadow.glsl" 509 ; 510 511 const char SHADER_AMBIENT[] = 512 #include "../shaders/ambient.glsl" 513 ; 514 515 const char SHADER_SKY[] = 516 #include "../shaders/sky.glsl" 517 ; 518 519 const char SHADER_WATER[] = 520 #include "../shaders/water.glsl" 521 ; 522 523 const char SHADER_FILTER[] = 524 #include "../shaders/filter.glsl" 525 ; 526 527 const char SHADER_GUI[] = 528 #include "../shaders/gui.glsl" 529 ; 530 531 const char *DefineName[SD_MAX] = { SHADER_DEFINES(DECL_STR) }; 532 #endif 533 534 static const struct Binding { 535 bool vec; // true - vec4, false - mat4 536 int reg; 537 } bindings[uMAX] = { 538 { true, 0 }, // uParam 539 { true, 1 }, // uTexParam 540 { false, 2 }, // uViewProj 541 { true, 6 }, // uBasis 542 { false, 70 }, // uLightProj 543 { true, 74 }, // uMaterial 544 { true, 75 }, // uAmbient 545 { true, 81 }, // uFogParams 546 { true, 82 }, // uViewPos 547 { true, 83 }, // uLightPos 548 { true, 87 }, // uLightColor 549 { true, 91 }, // uRoomSize 550 { true, 92 }, // uPosScale 551 { true, 98 }, // uContacts 552 }; 553 554 struct Shader { 555 #ifdef FFP initShader556 void init(Core::Pass pass, int type, int *def, int defCount) {} deinitShader557 void deinit() {} bindShader558 void bind() {} validateShader559 void validate() {} 560 void setParam(UniformType uType, const vec4 &value, int count = 1) {} 561 void setParam(UniformType uType, const mat4 &value, int count = 1) {} 562 #else 563 GLuint ID; 564 int32 uID[uMAX]; 565 566 vec4 cbMem[98 + MAX_CONTACTS]; 567 int cbCount[uMAX]; 568 569 bool rebind; 570 571 void init(Pass pass, int type, int *def, int defCount) { 572 const char *source; 573 switch (pass) { 574 case Core::passCompose : source = SHADER_COMPOSE; break; 575 case Core::passShadow : source = SHADER_SHADOW; break; 576 case Core::passAmbient : source = SHADER_AMBIENT; break; 577 case Core::passSky : source = SHADER_SKY; break; 578 case Core::passWater : source = SHADER_WATER; break; 579 case Core::passFilter : source = SHADER_FILTER; break; 580 case Core::passGUI : source = SHADER_GUI; break; 581 default : ASSERT(false); LOG("! wrong pass id\n"); return; 582 } 583 584 #ifdef _DEBUG_SHADERS 585 Stream *stream = NULL; 586 switch (pass) { 587 case Core::passCompose : stream = new Stream(_DEBUG_SHADERS "compose.glsl"); break; 588 case Core::passShadow : stream = new Stream(_DEBUG_SHADERS "shadow.glsl"); break; 589 case Core::passAmbient : stream = new Stream(_DEBUG_SHADERS "ambient.glsl"); break; 590 case Core::passSky : stream = new Stream(_DEBUG_SHADERS "sky.glsl"); break; 591 case Core::passWater : stream = new Stream(_DEBUG_SHADERS "water.glsl"); break; 592 case Core::passFilter : stream = new Stream(_DEBUG_SHADERS "filter.glsl"); break; 593 case Core::passGUI : stream = new Stream(_DEBUG_SHADERS "gui.glsl"); break; 594 default : ASSERT(false); return; 595 } 596 597 char *sourceData = new char[stream->size + 1]; 598 stream->raw(sourceData, stream->size); 599 sourceData[stream->size] = 0; 600 601 source = sourceData; 602 for (int i = 0; i < stream->size; i++) // trim string resource begin tag 603 if (sourceData[i] == '(') { 604 source = sourceData + i + 1; 605 break; 606 } 607 608 for (int i = stream->size - 1; i >= 0; i--) // trim string resource end tag 609 if (sourceData[i] == ')') { 610 sourceData[i] = 0; 611 break; 612 } 613 614 delete stream; 615 #endif 616 617 char defines[1024]; 618 defines[0] = 0; 619 strcat(defines, "#define VER3\n"); 620 621 for (int i = 0; i < defCount; i++) { 622 sprintf(defines + strlen(defines), "#define %s\n", DefineName[def[i]]); 623 } 624 625 sprintf(defines + strlen(defines), "#define SHADOW_SIZE %d.0\n", SHADOW_TEX_SIZE); 626 627 #ifdef MERGE_MODELS 628 strcat(defines, "#define MESH_SKINNING\n"); 629 #endif 630 631 // etnaviv driver has no sin/cos/abs implementation 632 #if !defined(_OS_GCW0) 633 strcat(defines, "#define VERT_CAUSTICS\n"); 634 #endif 635 636 #if defined(_OS_RPI) || defined(_OS_CLOVER) || defined(_OS_GCW0) || (defined (__SDL2__) && defined(_GAPI_GLES)) 637 strcat(defines, "#define OPT_VLIGHTPROJ\n"); 638 strcat(defines, "#define OPT_VLIGHTVEC\n"); 639 strcat(defines, "#define OPT_SHADOW_ONETAP\n"); 640 #endif 641 642 if (support.tex3D) { 643 strcat(defines, "#define OPT_TEXTURE_3D\n"); 644 } 645 646 #ifndef _OS_CLOVER 647 // TODO: only for non Mali-400? 648 strcat(defines, "#define OPT_TRAPEZOID\n"); 649 if (Core::settings.detail.water > Core::Settings::LOW) 650 strcat(defines, "#define OPT_UNDERWATER_FOG\n"); 651 #endif 652 653 char fileName[255]; 654 // generate shader file path 655 if (Core::support.shaderBinary) { 656 uint32 hash = fnv32(defines, (int32)strlen(defines), fnv32(source, (int32)strlen(source))); 657 sprintf(fileName, "%08X.xsh", hash); 658 } 659 660 ID = glCreateProgram(); 661 662 if (!(Core::support.shaderBinary && linkBinary(fileName))) { // try to load cached shader 663 if (linkSource(source, defines) && Core::support.shaderBinary) { // compile shader from source and dump it into cache 664 #ifndef _OS_WEB 665 GLenum format = 0, size; 666 glGetProgramiv(ID, GL_PROGRAM_BINARY_LENGTH, (GLsizei*)&size); 667 char *data = new char[8 + size]; 668 glGetProgramBinary(ID, size, NULL, &format, &data[8]); 669 *(int*)(&data[0]) = format; 670 *(int*)(&data[4]) = size; 671 Stream::cacheWrite(fileName, data, 8 + size); 672 delete[] data; 673 #endif 674 } 675 } 676 677 #ifdef _DEBUG_SHADERS 678 delete[] sourceData; 679 #endif 680 681 Core::active.shader = this; 682 glUseProgram(ID); 683 684 for (int st = 0; st < sMAX; st++) { 685 GLint idx = glGetUniformLocation(ID, (GLchar*)SamplerName[st]); 686 if (idx != -1) 687 glUniform1iv(idx, 1, &st); 688 } 689 690 for (int ut = 0; ut < uMAX; ut++) 691 uID[ut] = glGetUniformLocation(ID, (GLchar*)UniformName[ut]); 692 693 rebind = true; 694 } 695 696 void deinit() { 697 glDeleteProgram(ID); 698 } 699 700 bool linkSource(const char *text, const char *defines = "") { 701 const int type[2] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER }; 702 const char *code[2][4] = { 703 { GLSL_HEADER_VERT, defines, "#line 0\n", text }, 704 { GLSL_HEADER_FRAG, defines, "#line 0\n", text } 705 }; 706 707 GLchar info[1024]; 708 709 for (int i = 0; i < 2; i++) { 710 GLuint obj = glCreateShader(type[i]); 711 glShaderSource(obj, 4, code[i], NULL); 712 glCompileShader(obj); 713 714 glGetShaderInfoLog(obj, sizeof(info), NULL, info); 715 if (info[0] && strlen(info) > 8) LOG("! shader: %s\n", info); 716 717 glAttachShader(ID, obj); 718 glDeleteShader(obj); 719 } 720 721 for (int at = 0; at < aMAX; at++) 722 glBindAttribLocation(ID, at, AttribName[at]); 723 724 glLinkProgram(ID); 725 726 glGetProgramInfoLog(ID, sizeof(info), NULL, info); 727 if (info[0] && strlen(info) > 8) LOG("! program: %s\n", info); 728 729 return checkLink(); 730 } 731 732 bool linkBinary(const char *name) { 733 // non-async code! 734 char path[255]; 735 strcpy(path, cacheDir); 736 strcat(path, name); 737 738 if (!Stream::exists(path)) 739 return false; 740 741 Stream *stream = new Stream(path); 742 if (!stream) 743 return false; 744 745 GLenum size, format; 746 stream->read(format); 747 stream->read(size); 748 char *data = new char[size]; 749 stream->raw(data, size); 750 glProgramBinary(ID, format, data, size); 751 delete[] data; 752 delete stream; 753 754 return checkLink(); 755 } 756 757 bool checkLink() { 758 GLint success; 759 glGetProgramiv(ID, GL_LINK_STATUS, &success); 760 return success != 0; 761 } 762 763 void bind() { 764 if (Core::active.shader != this) { 765 Core::active.shader = this; 766 memset(cbCount, 0, sizeof(cbCount)); 767 rebind = true; 768 } 769 } 770 771 void validate() { 772 if (rebind) { 773 glUseProgram(ID); 774 rebind = false; 775 } 776 777 for (int uType = 0; uType < uMAX; uType++) { 778 if (!cbCount[uType]) continue; 779 780 const Binding &b = bindings[uType]; 781 782 if (b.vec) 783 glUniform4fv(uID[uType], cbCount[uType], (GLfloat*)(cbMem + b.reg)); 784 else 785 glUniformMatrix4fv(uID[uType], cbCount[uType] / 4, false, (GLfloat*)(cbMem + b.reg)); 786 787 cbCount[uType] = 0; 788 Core::stats.cb++; 789 } 790 } 791 792 void setParam(UniformType uType, float *value, int count) { 793 cbCount[uType] = count; 794 memcpy(cbMem + bindings[uType].reg, value, count * 16); 795 } 796 797 void setParam(UniformType uType, const vec4 &value, int count = 1) { 798 if (uID[uType] != -1) setParam(uType, (float*)&value, count); 799 } 800 801 void setParam(UniformType uType, const mat4 &value, int count = 1) { 802 if (uID[uType] != -1) setParam(uType, (float*)&value, count * 4); 803 } 804 #endif 805 }; 806 807 808 // Texture 809 static const struct FormatDesc { 810 GLuint ifmt, fmt; 811 GLenum type; 812 } formats[FMT_MAX] = { 813 { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE }, // LUMINANCE 814 { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE }, // RGBA 815 { GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 }, // RGB16 816 { GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 }, // RGBA16 817 { GL_RG32F, GL_RG, GL_FLOAT }, // RG_FLOAT 818 { GL_RG16F, GL_RG, GL_HALF_FLOAT }, // RG_HALF 819 { GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT }, // DEPTH 820 { GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT }, // SHADOW 821 }; 822 823 struct Texture { 824 uint32 ID; 825 int width, height, depth, origWidth, origHeight, origDepth; 826 TexFormat fmt; 827 uint32 opt; 828 GLenum target; 829 TextureTexture830 Texture(int width, int height, int depth, uint32 opt) : ID(0), width(width), height(height), depth(depth), origWidth(width), origHeight(height), origDepth(depth), fmt(FMT_RGBA), opt(opt) {} 831 initTexture832 void init(void *data) { 833 ASSERT((opt & OPT_PROXY) == 0); 834 835 bool filter = (opt & OPT_NEAREST) == 0; 836 bool mipmaps = (opt & OPT_MIPMAPS) != 0; 837 bool isCube = (opt & OPT_CUBEMAP) != 0; 838 bool isVolume = (opt & OPT_VOLUME) != 0; 839 bool isShadow = fmt == FMT_SHADOW; 840 841 target = isVolume ? GL_TEXTURE_3D : (isCube ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D); 842 843 glGenTextures(1, &ID); 844 845 Core::active.textures[0] = NULL; 846 bind(0); 847 848 if (isShadow) { 849 glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); 850 glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); 851 } 852 853 glTexParameteri(target, GL_TEXTURE_WRAP_S, (opt & OPT_REPEAT) ? GL_REPEAT : GL_CLAMP_TO_EDGE); 854 glTexParameteri(target, GL_TEXTURE_WRAP_T, (opt & OPT_REPEAT) ? GL_REPEAT : GL_CLAMP_TO_EDGE); 855 if (isVolume) { 856 glTexParameteri(target, GL_TEXTURE_WRAP_R, (opt & OPT_REPEAT) ? GL_REPEAT : GL_CLAMP_TO_EDGE); 857 } 858 859 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter ? (mipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR) : (mipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST)); 860 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter ? GL_LINEAR : GL_NEAREST); 861 862 FormatDesc desc = getFormat(); 863 864 void *pix = (width == origWidth && height == origHeight && depth == origDepth) ? data : NULL; 865 866 if (isVolume) { 867 glTexImage3D(target, 0, desc.ifmt, width, height, depth, 0, desc.fmt, desc.type, pix); 868 } else if (isCube) { 869 for (int i = 0; i < 6; i++) { 870 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, desc.ifmt, width, height, 0, desc.fmt, desc.type, pix); 871 } 872 } else { 873 glTexImage2D(target, 0, desc.ifmt, width, height, 0, desc.fmt, desc.type, pix); 874 } 875 876 if (pix != data) { 877 update(data); 878 } 879 } 880 deinitTexture881 void deinit() { 882 if (ID) { 883 glDeleteTextures(1, &ID); 884 } 885 } 886 getFormatTexture887 FormatDesc getFormat() { 888 FormatDesc desc = formats[fmt]; 889 890 if ((fmt == FMT_RG_FLOAT || fmt == FMT_RG_HALF) && !Core::support.texRG) { 891 desc.ifmt = (fmt == FMT_RG_FLOAT) ? GL_RGBA32F : GL_RGBA16F; 892 desc.fmt = GL_RGBA; 893 } 894 895 if (fmt == FMT_LUMINANCE && Core::support.texRG) { 896 desc.ifmt = GL_R8; 897 desc.fmt = GL_RED; 898 } 899 900 #ifdef _OS_WEB // fucking firefox! 901 if (WEBGL_VERSION == 1) { 902 if (fmt == FMT_RG_FLOAT) { 903 if (Core::support.texFloat) { 904 desc.ifmt = GL_RGBA; 905 desc.type = GL_FLOAT; 906 } 907 } 908 909 if (fmt == FMT_RG_HALF) { 910 if (Core::support.texHalf) { 911 desc.ifmt = GL_RGBA; 912 desc.type = GL_HALF_FLOAT_OES; 913 } 914 } 915 } else { 916 if (fmt == FMT_DEPTH || fmt == FMT_SHADOW) { 917 desc.ifmt = GL_DEPTH_COMPONENT16; 918 } 919 } 920 #else 921 if ((fmt == FMT_RG_FLOAT && !Core::support.colorFloat) || (fmt == FMT_RG_HALF && !Core::support.colorHalf)) { 922 desc.ifmt = GL_RGBA; 923 #ifdef _GAPI_GLES 924 if (fmt == FMT_RG_HALF) { 925 desc.type = GL_HALF_FLOAT_OES; 926 } 927 #endif 928 } 929 #endif 930 return desc; 931 } 932 generateMipMapTexture933 void generateMipMap() { 934 bind(0); 935 if (glGenerateMipmap) { 936 glGenerateMipmap(target); 937 } 938 if ((opt & (OPT_VOLUME | OPT_CUBEMAP | OPT_NEAREST)) == 0 && (Core::support.maxAniso > 0)) { 939 glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, min(int(Core::support.maxAniso), 8)); 940 if (Core::support.texMaxLevel) { 941 glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 3); 942 } 943 } 944 } 945 updateTexture946 void update(void *data) { 947 ASSERT((opt & (OPT_VOLUME | OPT_CUBEMAP)) == 0); 948 bind(0); 949 FormatDesc desc = getFormat(); 950 glTexSubImage2D(target, 0, 0, 0, origWidth, origHeight, desc.fmt, desc.type, data); 951 } 952 bindTexture953 void bind(int sampler) { 954 if (opt & OPT_PROXY) return; 955 ASSERT(ID); 956 957 if (Core::active.textures[sampler] != this) { 958 Core::active.textures[sampler] = this; 959 #ifdef FFP 960 if (sampler != sDiffuse) { 961 return; 962 } 963 #else 964 glActiveTexture(GL_TEXTURE0 + sampler); 965 #endif 966 glBindTexture(target, ID); 967 } 968 } 969 unbindTexture970 void unbind(int sampler) { 971 if (Core::active.textures[sampler]) { 972 Core::active.textures[sampler] = NULL; 973 #ifdef FFP 974 if (sampler != sDiffuse) { 975 return; 976 } 977 #else 978 glActiveTexture(GL_TEXTURE0 + sampler); 979 #endif 980 glBindTexture(target, 0); 981 } 982 } 983 setFilterQualityTexture984 void setFilterQuality(int value) { 985 bool filter = (opt & OPT_NEAREST) == 0 && (value > Core::Settings::LOW); 986 bool mipmaps = (opt & OPT_MIPMAPS) != 0; 987 988 Core::active.textures[0] = NULL; 989 bind(0); 990 if (Core::support.maxAniso > 0) { 991 glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, value > Core::Settings::MEDIUM ? min(int(Core::support.maxAniso), 8) : 1); 992 } 993 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter ? (mipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR ) : ( mipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST )); 994 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter ? GL_LINEAR : GL_NEAREST); 995 } 996 }; 997 998 // Mesh 999 struct Mesh { 1000 Index *iBuffer; 1001 Vertex *vBuffer; 1002 GLuint *VAO; 1003 GLuint ID[2]; 1004 1005 int iCount; 1006 int vCount; 1007 int aCount; 1008 bool dynamic; 1009 MeshMesh1010 Mesh(bool dynamic) : iBuffer(NULL), vBuffer(NULL), VAO(NULL), dynamic(dynamic) { 1011 ID[0] = ID[1] = 0; 1012 } 1013 initMesh1014 void init(Index *indices, int iCount, ::Vertex *vertices, int vCount, int aCount) { 1015 this->iCount = iCount; 1016 this->vCount = vCount; 1017 this->aCount = aCount; 1018 1019 if (Core::support.VAO) 1020 glBindVertexArray(Core::active.VAO = 0); 1021 1022 bool useVBO = Core::support.VBO; 1023 1024 #ifdef DYNGEOM_NO_VBO 1025 if (!vertices && !indices) { 1026 useVBO = false; 1027 } 1028 #endif 1029 1030 ASSERT(sizeof(GAPI::Vertex) == sizeof(::Vertex)); 1031 1032 if (useVBO) { 1033 glGenBuffers(2, ID); 1034 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ID[0]); 1035 glBindBuffer(GL_ARRAY_BUFFER, ID[1]); 1036 glBufferData(GL_ELEMENT_ARRAY_BUFFER, iCount * sizeof(Index), indices, dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); 1037 glBufferData(GL_ARRAY_BUFFER, vCount * sizeof(Vertex), vertices, dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); 1038 } else { 1039 iBuffer = new Index[iCount]; 1040 vBuffer = new GAPI::Vertex[vCount]; 1041 update(indices, iCount, vertices, vCount); 1042 } 1043 1044 if (Core::support.VAO && aCount) { 1045 VAO = new GLuint[aCount]; 1046 glGenVertexArrays(aCount, VAO); 1047 } 1048 } 1049 deinitMesh1050 void deinit() { 1051 if (iBuffer || vBuffer) { 1052 delete[] iBuffer; 1053 delete[] vBuffer; 1054 } else { 1055 if (VAO) { 1056 glDeleteVertexArrays(aCount, VAO); 1057 delete[] VAO; 1058 } 1059 glDeleteBuffers(2, ID); 1060 } 1061 } 1062 updateMesh1063 void update(Index *indices, int iCount, ::Vertex *vertices, int vCount) { 1064 ASSERT(sizeof(GAPI::Vertex) == sizeof(::Vertex)); 1065 1066 if (Core::support.VAO && Core::active.VAO != 0) 1067 glBindVertexArray(Core::active.VAO = 0); 1068 1069 if (indices && iCount) { 1070 if (iBuffer) { 1071 memcpy(iBuffer, indices, iCount * sizeof(Index)); 1072 } else { 1073 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Core::active.iBuffer = ID[0]); 1074 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, iCount * sizeof(Index), indices); 1075 } 1076 } 1077 if (vertices && vCount) { 1078 if (vBuffer) { 1079 memcpy(vBuffer, vertices, vCount * sizeof(GAPI::Vertex)); 1080 } else { 1081 glBindBuffer(GL_ARRAY_BUFFER, Core::active.vBuffer = ID[1]); 1082 glBufferSubData(GL_ARRAY_BUFFER, 0, vCount * sizeof(GAPI::Vertex), vertices); 1083 } 1084 } 1085 } 1086 setupFVFMesh1087 void setupFVF(GAPI::Vertex *v) const { 1088 #ifdef FFP 1089 glTexCoordPointer (2, GL_SHORT, sizeof(*v), &v->texCoord); 1090 glColorPointer (4, GL_UNSIGNED_BYTE, sizeof(*v), &v->light); 1091 glNormalPointer ( GL_SHORT, sizeof(*v), &v->normal); 1092 glVertexPointer (3, GL_SHORT, sizeof(*v), &v->coord); 1093 #else 1094 glEnableVertexAttribArray(aCoord); 1095 glEnableVertexAttribArray(aNormal); 1096 glEnableVertexAttribArray(aTexCoord); 1097 glEnableVertexAttribArray(aColor); 1098 glEnableVertexAttribArray(aLight); 1099 1100 glVertexAttribPointer(aCoord, 4, GL_SHORT, false, sizeof(*v), &v->coord); 1101 glVertexAttribPointer(aNormal, 4, GL_SHORT, true, sizeof(*v), &v->normal); 1102 glVertexAttribPointer(aTexCoord, 4, GL_SHORT, true, sizeof(*v), &v->texCoord); 1103 glVertexAttribPointer(aColor, 4, GL_UNSIGNED_BYTE, true, sizeof(*v), &v->color); 1104 glVertexAttribPointer(aLight, 4, GL_UNSIGNED_BYTE, true, sizeof(*v), &v->light); 1105 #endif 1106 } 1107 bindMesh1108 void bind(const MeshRange &range) const { 1109 if (range.aIndex == -1) { 1110 if (Core::support.VBO && Core::active.iBuffer != ID[0]) 1111 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Core::active.iBuffer = ID[0]); 1112 if (Core::support.VBO && Core::active.vBuffer != ID[1]) 1113 glBindBuffer(GL_ARRAY_BUFFER, Core::active.vBuffer = ID[1]); 1114 setupFVF(vBuffer + range.vStart); 1115 } else { 1116 ASSERT(Core::support.VAO); 1117 GLuint vao = VAO[range.aIndex]; 1118 if (Core::active.VAO != vao) 1119 glBindVertexArray(Core::active.VAO = vao); 1120 } 1121 } 1122 initNextRangeMesh1123 void initNextRange(MeshRange &range, int &aIndex) const { 1124 if (Core::support.VAO && VAO) { 1125 ASSERT(aIndex < aCount); 1126 1127 Core::active.iBuffer = 0; 1128 Core::active.vBuffer = 0; 1129 Core::active.VAO = 0; 1130 1131 range.aIndex = aIndex++; // get new VAO index 1132 bind(range); // bind VAO 1133 range.aIndex = -1; // reset VAO to -1 1134 bind(range); // bind buffers and setup vertex format 1135 range.aIndex = aIndex - 1; // set VAO index back to the new 1136 1137 glBindVertexArray(Core::active.VAO = 0); 1138 } else 1139 range.aIndex = -1; 1140 } 1141 }; 1142 1143 1144 GLuint FBO, defaultFBO; 1145 struct RenderTargetCacheItem { 1146 GLuint ID; 1147 int width; 1148 int height; 1149 }; 1150 Array<RenderTargetCacheItem> rtCache[2]; 1151 1152 extSupport(const char * str)1153 bool extSupport(const char *str) { 1154 if (glGetStringi != NULL) { 1155 GLint count = 0; 1156 glGetIntegerv(GL_NUM_EXTENSIONS, &count); 1157 for (int i = 0; i < count; i++) { 1158 const char *ext = (const char*)glGetStringi(GL_EXTENSIONS, i); 1159 if (strstr(ext, str) != NULL) { 1160 return true; 1161 } 1162 } 1163 } else { 1164 const char *ext = (const char*)glGetString(GL_EXTENSIONS); 1165 if (!ext) { 1166 return false; 1167 } 1168 return strstr(ext, str) != NULL; 1169 } 1170 1171 return false; 1172 } 1173 init()1174 void init() { 1175 #ifdef _OS_ANDROID 1176 //void *libGL = dlopen("libGLESv2.so", RTLD_LAZY); 1177 #endif 1178 1179 #if (defined(__SDL2__) && defined(_GAPI_GLES2)) 1180 GetProcOGL(glDiscardFramebufferEXT); 1181 #endif 1182 1183 #if defined(_OS_WIN) || defined(_OS_LINUX) || defined(_OS_GCW0) || (defined(__SDL2__) && !defined(_GAPI_GLES)) 1184 #ifdef _OS_WIN 1185 GetProcOGL(glActiveTexture); 1186 #endif 1187 1188 #ifdef _OS_WIN 1189 GetProcOGL(wglSwapIntervalEXT); 1190 #elif _OS_LINUX 1191 GetProcOGL(glXSwapIntervalSGI); 1192 #endif 1193 1194 #if defined(_OS_WIN) || defined(_OS_LINUX) || (defined(__SDL2__) && (defined(_GAPI_GLES2) || defined(_SDL2_OPENGL))) 1195 GetProcOGL(glGenerateMipmap); 1196 #ifdef _OS_WIN 1197 GetProcOGL(glTexImage3D); 1198 #endif 1199 1200 GetProcOGL(glGetStringi); 1201 1202 #ifdef PROFILE 1203 GetProcOGL(glObjectLabel); 1204 GetProcOGL(glPushDebugGroup); 1205 GetProcOGL(glPopDebugGroup); 1206 GetProcOGL(glGenQueries); 1207 GetProcOGL(glDeleteQueries); 1208 GetProcOGL(glGetQueryObjectiv); 1209 GetProcOGL(glBeginQuery); 1210 GetProcOGL(glEndQuery); 1211 #endif 1212 1213 GetProcOGL(glCreateProgram); 1214 GetProcOGL(glDeleteProgram); 1215 GetProcOGL(glLinkProgram); 1216 GetProcOGL(glUseProgram); 1217 GetProcOGL(glGetProgramInfoLog); 1218 GetProcOGL(glCreateShader); 1219 GetProcOGL(glDeleteShader); 1220 GetProcOGL(glShaderSource); 1221 GetProcOGL(glAttachShader); 1222 GetProcOGL(glCompileShader); 1223 GetProcOGL(glGetShaderInfoLog); 1224 GetProcOGL(glGetUniformLocation); 1225 GetProcOGL(glUniform1iv); 1226 GetProcOGL(glUniform1fv); 1227 GetProcOGL(glUniform2fv); 1228 GetProcOGL(glUniform3fv); 1229 GetProcOGL(glUniform4fv); 1230 GetProcOGL(glUniformMatrix4fv); 1231 GetProcOGL(glBindAttribLocation); 1232 GetProcOGL(glEnableVertexAttribArray); 1233 GetProcOGL(glDisableVertexAttribArray); 1234 GetProcOGL(glVertexAttribPointer); 1235 GetProcOGL(glGetProgramiv); 1236 1237 GetProcOGL(glGenFramebuffers); 1238 GetProcOGL(glBindFramebuffer); 1239 GetProcOGL(glGenRenderbuffers); 1240 GetProcOGL(glBindRenderbuffer); 1241 GetProcOGL(glFramebufferTexture2D); 1242 GetProcOGL(glFramebufferRenderbuffer); 1243 GetProcOGL(glRenderbufferStorage); 1244 GetProcOGL(glCheckFramebufferStatus); 1245 GetProcOGL(glDeleteFramebuffers); 1246 GetProcOGL(glDeleteRenderbuffers); 1247 GetProcOGL(glGetFramebufferAttachmentParameteriv); 1248 1249 GetProcOGL(glGenBuffers); 1250 GetProcOGL(glDeleteBuffers); 1251 GetProcOGL(glBindBuffer); 1252 GetProcOGL(glBufferData); 1253 GetProcOGL(glBufferSubData); 1254 #endif 1255 1256 GetProcOGL(glGenVertexArrays); 1257 GetProcOGL(glDeleteVertexArrays); 1258 GetProcOGL(glBindVertexArray); 1259 1260 GetProcOGL(glGetProgramBinary); 1261 GetProcOGL(glProgramBinary); 1262 1263 #if defined(_GAPI_GLES) 1264 GetProcOGL(glDiscardFramebufferEXT); 1265 #endif 1266 #endif 1267 1268 LOG("Vendor : %s\n", (char*)glGetString(GL_VENDOR)); 1269 LOG("Renderer : %s\n", (char*)glGetString(GL_RENDERER)); 1270 LOG("Version : %s\n", (char*)glGetString(GL_VERSION)); 1271 1272 #ifndef FFP 1273 bool GLES3 = false; 1274 #ifdef _OS_WEB 1275 GLES3 = WEBGL_VERSION != 1; 1276 #else 1277 #if defined(_GAPI_GLES) && !defined(_GAPI_GLES2) 1278 int GLES_VERSION = 1; 1279 #if defined(__SDL2__) 1280 SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &GLES_VERSION); 1281 #else 1282 #if defined(_OS_RPI) || defined(_OS_CLOVER) || defined(_OS_GCW0) 1283 GLES_VERSION = 2; 1284 #else 1285 glGetIntegerv(GL_MAJOR_VERSION, &GLES_VERSION); 1286 #endif 1287 #endif 1288 GLES3 = GLES_VERSION > 2; 1289 #endif 1290 #endif 1291 1292 bool _GL_EXT_shadow_samplers = extSupport("GL_EXT_shadow_samplers"); 1293 bool _GL_ARB_shadow = extSupport("GL_ARB_shadow"); 1294 bool _GL_OES_standard_derivatives = extSupport("GL_OES_standard_derivatives"); 1295 1296 support.shaderBinary = extSupport("_program_binary"); 1297 support.VAO = GLES3 || extSupport("_vertex_array_object"); 1298 support.VBO = glGenBuffers != NULL; 1299 support.depthTexture = GLES3 || extSupport("_depth_texture"); 1300 support.shadowSampler = _GL_EXT_shadow_samplers || _GL_ARB_shadow; 1301 support.discardFrame = extSupport("_discard_framebuffer"); 1302 support.texNPOT = GLES3 || extSupport("_texture_npot") || extSupport("_texture_non_power_of_two"); 1303 support.texRG = GLES3 || extSupport("_texture_rg"); 1304 support.texMaxLevel = GLES3 || extSupport("_texture_max_level"); 1305 1306 #ifdef _GAPI_GLES2 // TODO 1307 support.shaderBinary = false; 1308 support.VAO = false; 1309 support.texRG = false; 1310 support.discardFrame = false; 1311 #endif 1312 #ifdef _GAPI_GLES 1313 support.derivatives = GLES3 || _GL_OES_standard_derivatives; 1314 support.tex3D = GLES3; 1315 #else 1316 support.derivatives = true; 1317 support.tex3D = glTexImage3D != NULL; 1318 #endif 1319 support.texBorder = extSupport("_texture_border_clamp"); 1320 support.maxAniso = extSupport("_texture_filter_anisotropic"); 1321 support.colorFloat = extSupport("_color_buffer_float"); 1322 support.colorHalf = extSupport("_color_buffer_half_float") || extSupport("GL_ARB_half_float_pixel"); 1323 support.texFloatLinear = support.colorFloat || extSupport("GL_ARB_texture_float") || extSupport("_texture_float_linear"); 1324 support.texFloat = support.texFloatLinear || extSupport("_texture_float"); 1325 support.texHalfLinear = support.colorHalf || extSupport("GL_ARB_texture_float") || extSupport("_texture_half_float_linear") || extSupport("_color_buffer_half_float"); 1326 1327 support.texHalf = support.texHalfLinear || extSupport("_texture_half_float"); 1328 1329 #ifdef SDL2_GLES 1330 support.shaderBinary = false; // TODO 1331 support.VAO = false; // TODO 1332 support.shadowSampler = false; // TODO 1333 #endif 1334 1335 #ifdef PROFILE 1336 support.profMarker = extSupport("_KHR_debug"); 1337 support.profTiming = extSupport("_timer_query"); 1338 #endif 1339 1340 if (support.maxAniso) 1341 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &support.maxAniso); 1342 #ifdef _GAPI_GLES 1343 glGetIntegerv(GL_MAX_VARYING_VECTORS, &support.maxVectors); 1344 #else 1345 support.maxVectors = 16; 1346 #endif 1347 #endif 1348 1349 glEnable(GL_SCISSOR_TEST); 1350 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 1351 1352 glDepthFunc(GL_LEQUAL); 1353 1354 #ifdef FFP 1355 glEnable(GL_TEXTURE_2D); 1356 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 1357 glEnableClientState(GL_COLOR_ARRAY); 1358 glEnableClientState(GL_NORMAL_ARRAY); 1359 glEnableClientState(GL_VERTEX_ARRAY); 1360 1361 glAlphaFunc(GL_GREATER, 0.5f); 1362 1363 glMatrixMode(GL_TEXTURE); 1364 glLoadIdentity(); 1365 glScalef(1.0f / 32767.0f, 1.0f / 32767.0f, 1.0f / 32767.0f); 1366 1367 glClearColor(0, 0, 0, 0); 1368 #else 1369 glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&defaultFBO); 1370 glGenFramebuffers(1, &FBO); 1371 1372 char extHeader[256]; 1373 GLSL_HEADER_VERT[0] = GLSL_HEADER_FRAG[0] = extHeader[0] = 0; 1374 if (_GL_OES_standard_derivatives) { 1375 if (!GLES3) { 1376 strcat(extHeader, "#extension GL_OES_standard_derivatives : enable\n"); 1377 } 1378 } 1379 1380 if (_GL_EXT_shadow_samplers && !_GL_ARB_shadow) { 1381 if (!GLES3) { 1382 strcat(extHeader, "#extension GL_EXT_shadow_samplers : enable\n"); 1383 } 1384 } 1385 1386 #ifdef _GAPI_GLES 1387 if (GLES3) { 1388 // vertex 1389 strcat(GLSL_HEADER_VERT, "#version 300 es\n" 1390 "precision lowp int;\n" 1391 "precision highp float;\n" 1392 "#define VERTEX\n" 1393 "#define varying out\n" 1394 "#define attribute in\n" 1395 "#define texture2D texture\n"); 1396 // fragment 1397 strcat(GLSL_HEADER_FRAG, "#version 300 es\n"); 1398 strcat(GLSL_HEADER_FRAG, extHeader); 1399 strcat(GLSL_HEADER_FRAG, "precision lowp int;\n" 1400 "precision highp float;\n" 1401 "precision lowp sampler3D;\n" 1402 "#define FRAGMENT\n" 1403 "#define varying in\n" 1404 "#define texture2D texture\n" 1405 "#define texture3D texture\n" 1406 "#define textureCube texture\n" 1407 "#define FETCH_SHADOW2D(a,b) texture(a,b)\n" 1408 "out vec4 fragColor;\n"); 1409 } else { 1410 // vertex 1411 strcat(GLSL_HEADER_VERT, "#version 100\n" 1412 "precision lowp int;\n" 1413 "precision highp float;\n" 1414 "#define VERTEX\n"); 1415 // fragment 1416 strcat(GLSL_HEADER_FRAG, "#version 100\n"); 1417 strcat(GLSL_HEADER_FRAG, extHeader); 1418 strcat(GLSL_HEADER_FRAG, "precision lowp int;\n" 1419 "precision highp float;\n" 1420 "#define FRAGMENT\n" 1421 "#define FETCH_SHADOW2D(a,b) shadow2DEXT(a,b)\n" 1422 "#define fragColor gl_FragColor\n"); 1423 } 1424 1425 if (support.shadowSampler) { 1426 strcat(GLSL_HEADER_FRAG, "#define sampler2DShadow lowp sampler2DShadow\n"); 1427 } 1428 #else 1429 if (GL_VER_3) { 1430 strcat(GLSL_HEADER_VERT, "#version 150\n" 1431 "#define VERTEX\n" 1432 "#define varying out\n" 1433 "#define attribute in\n" 1434 "#define texture2D texture\n"); 1435 // fragment 1436 strcat(GLSL_HEADER_FRAG, "#version 150\n"); 1437 strcat(GLSL_HEADER_FRAG, extHeader); 1438 strcat(GLSL_HEADER_FRAG, "#define FRAGMENT\n" 1439 "#define varying in\n" 1440 "#define texture2D texture\n" 1441 "#define texture3D texture\n" 1442 "#define textureCube texture\n" 1443 "#define FETCH_SHADOW2D(a,b) texture(a,b)\n" 1444 "out vec4 fragColor;\n"); 1445 } else { 1446 // vertex 1447 strcat(GLSL_HEADER_VERT, "#version 110\n" 1448 "#define VERTEX\n"); 1449 // fragment 1450 strcat(GLSL_HEADER_FRAG, "#version 110\n"); 1451 strcat(GLSL_HEADER_FRAG, extHeader); 1452 strcat(GLSL_HEADER_FRAG, "#define FRAGMENT\n" 1453 "#define FETCH_SHADOW2D(a,b) shadow2D(a,b).x\n" 1454 "#define fragColor gl_FragColor\n"); 1455 } 1456 #endif 1457 ASSERT(strlen(GLSL_HEADER_VERT) < COUNT(GLSL_HEADER_VERT)); 1458 ASSERT(strlen(GLSL_HEADER_FRAG) < COUNT(GLSL_HEADER_FRAG)); 1459 #endif // FFP 1460 } 1461 deinit()1462 void deinit() { 1463 #ifdef FFP 1464 return; 1465 #endif 1466 glBindFramebuffer(GL_FRAMEBUFFER, 0); 1467 glDeleteFramebuffers(1, &FBO); 1468 1469 glBindRenderbuffer(GL_RENDERBUFFER, 0); 1470 for (int b = 0; b < 2; b++) { 1471 for (int i = 0; i < rtCache[b].length; i++) { 1472 glDeleteRenderbuffers(1, &rtCache[b][i].ID); 1473 } 1474 rtCache[b].clear(); 1475 } 1476 } 1477 getProjRange()1478 inline mat4::ProjRange getProjRange() { 1479 return mat4::PROJ_NEG_POS; 1480 } 1481 ortho(float l,float r,float b,float t,float znear,float zfar)1482 mat4 ortho(float l, float r, float b, float t, float znear, float zfar) { 1483 mat4 m; 1484 m.ortho(getProjRange(), l, r, b, t, znear, zfar); 1485 return m; 1486 } 1487 perspective(float fov,float aspect,float znear,float zfar,float eye)1488 mat4 perspective(float fov, float aspect, float znear, float zfar, float eye) { 1489 mat4 m; 1490 m.perspective(getProjRange(), fov, aspect, znear, zfar, eye); 1491 return m; 1492 } 1493 beginFrame()1494 bool beginFrame() { 1495 return true; 1496 } 1497 endFrame()1498 void endFrame() {} 1499 resetState()1500 void resetState() { 1501 if (Core::support.VAO) 1502 glBindVertexArray(0); 1503 1504 #ifndef FFP 1505 glActiveTexture(GL_TEXTURE0); 1506 glUseProgram(0); 1507 #endif 1508 1509 if (Core::support.VBO) { 1510 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 1511 glBindBuffer(GL_ARRAY_BUFFER, 0); 1512 } 1513 } 1514 cacheRenderTarget(bool depth,int width,int height)1515 int cacheRenderTarget(bool depth, int width, int height) { 1516 Array<RenderTargetCacheItem> &items = rtCache[depth]; 1517 1518 for (int i = 0; i < items.length; i++) 1519 if (items[i].width == width && items[i].height == height) { 1520 RenderTargetCacheItem item = items[i]; 1521 items.remove(i); 1522 return items.push(item); 1523 } 1524 1525 if (items.length >= MAX_RENDER_BUFFERS) { 1526 glDeleteRenderbuffers(1, &items[0].ID); 1527 items.remove(0); 1528 } 1529 1530 RenderTargetCacheItem item; 1531 item.width = width; 1532 item.height = height; 1533 1534 glGenRenderbuffers(1, &item.ID); 1535 glBindRenderbuffer(GL_RENDERBUFFER, item.ID); 1536 glRenderbufferStorage(GL_RENDERBUFFER, depth ? GL_DEPTH_COMPONENT16 : GL_RGB565, width, height); 1537 glBindRenderbuffer(GL_RENDERBUFFER, 0); 1538 return items.push(item); 1539 } 1540 bindTarget(Texture * target,int face)1541 void bindTarget(Texture *target, int face) { 1542 if (!target) { // may be a null 1543 glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); 1544 } else { 1545 GLenum texTarget = GL_TEXTURE_2D; 1546 if (target->opt & OPT_CUBEMAP) { 1547 texTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face; 1548 } 1549 1550 bool depth = target->fmt == FMT_DEPTH || target->fmt == FMT_SHADOW; 1551 1552 int rtIndex = cacheRenderTarget(!depth, target->width, target->height); 1553 1554 glBindFramebuffer(GL_FRAMEBUFFER, FBO); 1555 glFramebufferTexture2D (GL_FRAMEBUFFER, depth ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0, texTarget, target->ID, 0); 1556 glFramebufferRenderbuffer (GL_FRAMEBUFFER, depth ? GL_COLOR_ATTACHMENT0 : GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rtCache[!depth].items[rtIndex].ID); 1557 GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 1558 if (status != GL_FRAMEBUFFER_COMPLETE) { 1559 LOG("status: 0x%04X\n", (int)status); 1560 } 1561 } 1562 } 1563 discardTarget(bool color,bool depth)1564 void discardTarget(bool color, bool depth) { 1565 #ifdef _GAPI_GLES 1566 if (Core::support.discardFrame) { 1567 int count = 0; 1568 GLenum discard[2]; 1569 if (color) discard[count++] = Core::active.target ? GL_COLOR_ATTACHMENT0 : GL_COLOR_EXT; 1570 if (depth) discard[count++] = Core::active.target ? GL_DEPTH_ATTACHMENT : GL_DEPTH_EXT; 1571 if (count) { 1572 #if defined(_OS_ANDROID) || (defined(__SDL2__) && !defined(_GAPI_GLES2)) 1573 /* glInvalidateBuffer() is the GLES3 version of glDiscardFramebufferEXT(), also 1574 available on Android. Not available in any GLES2 implementation, this is GLES3 stuff.*/ 1575 glInvalidateFramebuffer(GL_FRAMEBUFFER, count, discard); 1576 #elif !defined(_OS_WEB) || (defined(__SDL2__) && defined(_GAPI_GLES2)) 1577 /* glDiscardFramebufferEXT() is available even in GLES2 MESA implementations, 1578 but we have to get the extension function pointer address to use it. 1579 Not available in GLES3, which is SDL2 default GLES version. */ 1580 glDiscardFramebufferEXT(GL_FRAMEBUFFER, count, discard); 1581 #endif 1582 } 1583 } 1584 #endif 1585 } 1586 copyTarget(Texture * dst,int xOffset,int yOffset,int x,int y,int width,int height)1587 void copyTarget(Texture *dst, int xOffset, int yOffset, int x, int y, int width, int height) { 1588 Core::active.textures[0] = NULL; 1589 glActiveTexture(GL_TEXTURE0); 1590 glBindTexture(GL_TEXTURE_2D, dst->ID); 1591 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, x, y, width, height); 1592 glBindTexture(GL_TEXTURE_2D, 0); 1593 } 1594 setVSync(bool enable)1595 void setVSync(bool enable) { 1596 #ifdef _OS_WIN 1597 if (wglSwapIntervalEXT) wglSwapIntervalEXT(enable ? 1 : 0); 1598 #elif _OS_LINUX 1599 if (glXSwapIntervalSGI) glXSwapIntervalSGI(enable ? 1 : 0); 1600 #elif defined(__SDL2__) 1601 SDL_GL_SetSwapInterval(enable ? 1 : 0); 1602 #elif defined(_OS_RPI) || defined(_OS_CLOVER) || defined(_OS_SWITCH) 1603 eglSwapInterval(display, enable ? 1 : 0); 1604 #endif 1605 } 1606 waitVBlank()1607 void waitVBlank() {} 1608 clear(bool color,bool depth)1609 void clear(bool color, bool depth) { 1610 uint32 mask = (color ? GL_COLOR_BUFFER_BIT : 0) | (depth ? GL_DEPTH_BUFFER_BIT : 0); 1611 if (mask) { 1612 if (depth && !depthWrite) { 1613 glDepthMask(GL_TRUE); 1614 glClear(mask); 1615 glDepthMask(GL_FALSE); 1616 } else { 1617 glClear(mask); 1618 } 1619 } 1620 } 1621 setClearColor(const vec4 & color)1622 void setClearColor(const vec4 &color) { 1623 glClearColor(color.x, color.y, color.z, color.w); 1624 } 1625 setViewport(const short4 & v)1626 void setViewport(const short4 &v) { 1627 glViewport(v.x, v.y, v.z, v.w); 1628 } 1629 setScissor(const short4 & s)1630 void setScissor(const short4 &s) { 1631 glScissor(s.x, s.y, s.z, s.w); 1632 } 1633 setDepthTest(bool enable)1634 void setDepthTest(bool enable) { 1635 if (enable) 1636 glEnable(GL_DEPTH_TEST); 1637 else 1638 glDisable(GL_DEPTH_TEST); 1639 } 1640 setDepthWrite(bool enable)1641 void setDepthWrite(bool enable) { 1642 depthWrite = enable; 1643 glDepthMask(enable ? GL_TRUE : GL_FALSE); 1644 } 1645 setColorWrite(bool r,bool g,bool b,bool a)1646 void setColorWrite(bool r, bool g, bool b, bool a) { 1647 glColorMask(r, g, b, a); 1648 } 1649 setAlphaTest(bool enable)1650 void setAlphaTest(bool enable) { 1651 #ifdef FFP 1652 if (enable) 1653 glEnable(GL_ALPHA_TEST); 1654 else 1655 glDisable(GL_ALPHA_TEST); 1656 #endif 1657 } 1658 setCullMode(int rsMask)1659 void setCullMode(int rsMask) { 1660 cullMode = rsMask; 1661 switch (rsMask) { 1662 case RS_CULL_BACK : glCullFace(GL_BACK); break; 1663 case RS_CULL_FRONT : glCullFace(GL_FRONT); break; 1664 default : glDisable(GL_CULL_FACE); return; 1665 } 1666 glEnable(GL_CULL_FACE); 1667 } 1668 setBlendMode(int rsMask)1669 void setBlendMode(int rsMask) { 1670 blendMode = rsMask; 1671 switch (rsMask) { 1672 case RS_BLEND_ALPHA : glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; 1673 case RS_BLEND_ADD : glBlendFunc(GL_ONE, GL_ONE); break; 1674 case RS_BLEND_MULT : glBlendFunc(GL_DST_COLOR, GL_ZERO); break; 1675 case RS_BLEND_PREMULT : glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); break; 1676 default : glDisable(GL_BLEND); return; 1677 } 1678 glEnable(GL_BLEND); 1679 } 1680 setViewProj(const mat4 & mView,const mat4 & mProj)1681 void setViewProj(const mat4 &mView, const mat4 &mProj) { 1682 #ifdef FFP 1683 glMatrixMode(GL_PROJECTION); 1684 glLoadMatrixf((float*)&mProj); 1685 #endif 1686 } 1687 updateLights(vec4 * lightPos,vec4 * lightColor,int count)1688 void updateLights(vec4 *lightPos, vec4 *lightColor, int count) { 1689 #ifdef FFP 1690 int lightsCount = 0; 1691 1692 glMatrixMode(GL_MODELVIEW); 1693 glPushMatrix(); 1694 glLoadIdentity(); 1695 1696 vec4 amb(vec3(Core::active.material.y), 1.0f); 1697 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (GLfloat*)&amb); 1698 1699 for (int i = 0; i < count; i++) { 1700 GLenum light = GL_LIGHT0 + i; 1701 1702 if (lightColor[i].w != 1.0f) { 1703 glEnable(light); 1704 lightsCount++; 1705 } else { 1706 glDisable(light); 1707 continue; 1708 } 1709 1710 vec4 pos(lightPos[i].xyz(), 1.0f); 1711 vec4 color(lightColor[i].xyz(), 1.0f); 1712 float att = lightColor[i].w * lightColor[i].w; 1713 1714 glLightfv(light, GL_POSITION, (GLfloat*)&pos); 1715 glLightfv(light, GL_DIFFUSE, (GLfloat*)&color); 1716 glLightfv(light, GL_QUADRATIC_ATTENUATION, (GLfloat*)&att); 1717 } 1718 1719 glPopMatrix(); 1720 1721 if (lightsCount) { 1722 glEnable(GL_COLOR_MATERIAL); 1723 glEnable(GL_LIGHTING); 1724 } else { 1725 glDisable(GL_COLOR_MATERIAL); 1726 glDisable(GL_LIGHTING); 1727 } 1728 #else 1729 if (Core::active.shader) { 1730 Core::active.shader->setParam(uLightColor, lightColor[0], count); 1731 Core::active.shader->setParam(uLightPos, lightPos[0], count); 1732 } 1733 #endif 1734 } 1735 setFog(const vec4 & params)1736 void setFog(const vec4 ¶ms) { 1737 // FFP TODO 1738 } 1739 DIP(Mesh * mesh,const MeshRange & range)1740 void DIP(Mesh *mesh, const MeshRange &range) { 1741 #ifdef FFP 1742 mat4 m = mView * mModel; 1743 glMatrixMode(GL_MODELVIEW); 1744 glLoadMatrixf((GLfloat*)&m); 1745 #endif 1746 if (Core::active.shader) { 1747 Core::active.shader->validate(); 1748 } 1749 1750 glDrawElements(GL_TRIANGLES, range.iCount, sizeof(Index) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, mesh->iBuffer + range.iStart); 1751 } 1752 copyPixel(int x,int y)1753 vec4 copyPixel(int x, int y) { 1754 ubyte4 c; 1755 glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &c); 1756 return vec4(float(c.x), float(c.y), float(c.z), float(c.w)) * (1.0f / 255.0f); 1757 } 1758 } 1759 1760 #endif 1761