diff options
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/COpenGLDriver.cpp')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/COpenGLDriver.cpp | 9652 |
1 files changed, 4826 insertions, 4826 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/COpenGLDriver.cpp b/libraries/irrlicht-1.8/source/Irrlicht/COpenGLDriver.cpp index 1caa9c6..67c6b72 100644 --- a/libraries/irrlicht-1.8/source/Irrlicht/COpenGLDriver.cpp +++ b/libraries/irrlicht-1.8/source/Irrlicht/COpenGLDriver.cpp | |||
@@ -1,4826 +1,4826 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | 1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt |
2 | // This file is part of the "Irrlicht Engine". | 2 | // This file is part of the "Irrlicht Engine". |
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | 3 | // For conditions of distribution and use, see copyright notice in irrlicht.h |
4 | 4 | ||
5 | #include "COpenGLDriver.h" | 5 | #include "COpenGLDriver.h" |
6 | // needed here also because of the create methods' parameters | 6 | // needed here also because of the create methods' parameters |
7 | #include "CNullDriver.h" | 7 | #include "CNullDriver.h" |
8 | 8 | ||
9 | #ifdef _IRR_COMPILE_WITH_OPENGL_ | 9 | #ifdef _IRR_COMPILE_WITH_OPENGL_ |
10 | 10 | ||
11 | #include "COpenGLTexture.h" | 11 | #include "COpenGLTexture.h" |
12 | #include "COpenGLMaterialRenderer.h" | 12 | #include "COpenGLMaterialRenderer.h" |
13 | #include "COpenGLShaderMaterialRenderer.h" | 13 | #include "COpenGLShaderMaterialRenderer.h" |
14 | #include "COpenGLSLMaterialRenderer.h" | 14 | #include "COpenGLSLMaterialRenderer.h" |
15 | #include "COpenGLCgMaterialRenderer.h" | 15 | #include "COpenGLCgMaterialRenderer.h" |
16 | #include "COpenGLNormalMapRenderer.h" | 16 | #include "COpenGLNormalMapRenderer.h" |
17 | #include "COpenGLParallaxMapRenderer.h" | 17 | #include "COpenGLParallaxMapRenderer.h" |
18 | #include "os.h" | 18 | #include "os.h" |
19 | 19 | ||
20 | #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ | 20 | #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ |
21 | #include <SDL/SDL.h> | 21 | #include <SDL/SDL.h> |
22 | #endif | 22 | #endif |
23 | 23 | ||
24 | namespace irr | 24 | namespace irr |
25 | { | 25 | { |
26 | namespace video | 26 | namespace video |
27 | { | 27 | { |
28 | 28 | ||
29 | // ----------------------------------------------------------------------- | 29 | // ----------------------------------------------------------------------- |
30 | // WINDOWS CONSTRUCTOR | 30 | // WINDOWS CONSTRUCTOR |
31 | // ----------------------------------------------------------------------- | 31 | // ----------------------------------------------------------------------- |
32 | #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ | 32 | #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ |
33 | //! Windows constructor and init code | 33 | //! Windows constructor and init code |
34 | COpenGLDriver::COpenGLDriver(const irr::SIrrlichtCreationParameters& params, | 34 | COpenGLDriver::COpenGLDriver(const irr::SIrrlichtCreationParameters& params, |
35 | io::IFileSystem* io, CIrrDeviceWin32* device) | 35 | io::IFileSystem* io, CIrrDeviceWin32* device) |
36 | : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), | 36 | : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), |
37 | CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), | 37 | CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), |
38 | AntiAlias(params.AntiAlias), RenderTargetTexture(0), | 38 | AntiAlias(params.AntiAlias), RenderTargetTexture(0), |
39 | CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), | 39 | CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), |
40 | CurrentTarget(ERT_FRAME_BUFFER), Params(params), | 40 | CurrentTarget(ERT_FRAME_BUFFER), Params(params), |
41 | HDc(0), Window(static_cast<HWND>(params.WindowId)), Win32Device(device), | 41 | HDc(0), Window(static_cast<HWND>(params.WindowId)), Win32Device(device), |
42 | DeviceType(EIDT_WIN32) | 42 | DeviceType(EIDT_WIN32) |
43 | { | 43 | { |
44 | #ifdef _DEBUG | 44 | #ifdef _DEBUG |
45 | setDebugName("COpenGLDriver"); | 45 | setDebugName("COpenGLDriver"); |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | #ifdef _IRR_COMPILE_WITH_CG_ | 48 | #ifdef _IRR_COMPILE_WITH_CG_ |
49 | CgContext = 0; | 49 | CgContext = 0; |
50 | #endif | 50 | #endif |
51 | } | 51 | } |
52 | 52 | ||
53 | 53 | ||
54 | bool COpenGLDriver::changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceWin32* device) | 54 | bool COpenGLDriver::changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceWin32* device) |
55 | { | 55 | { |
56 | if (videoData.OpenGLWin32.HWnd && videoData.OpenGLWin32.HDc && videoData.OpenGLWin32.HRc) | 56 | if (videoData.OpenGLWin32.HWnd && videoData.OpenGLWin32.HDc && videoData.OpenGLWin32.HRc) |
57 | { | 57 | { |
58 | if (!wglMakeCurrent((HDC)videoData.OpenGLWin32.HDc, (HGLRC)videoData.OpenGLWin32.HRc)) | 58 | if (!wglMakeCurrent((HDC)videoData.OpenGLWin32.HDc, (HGLRC)videoData.OpenGLWin32.HRc)) |
59 | { | 59 | { |
60 | os::Printer::log("Render Context switch failed."); | 60 | os::Printer::log("Render Context switch failed."); |
61 | return false; | 61 | return false; |
62 | } | 62 | } |
63 | else | 63 | else |
64 | { | 64 | { |
65 | HDc = (HDC)videoData.OpenGLWin32.HDc; | 65 | HDc = (HDC)videoData.OpenGLWin32.HDc; |
66 | } | 66 | } |
67 | } | 67 | } |
68 | // set back to main context | 68 | // set back to main context |
69 | else if (HDc != ExposedData.OpenGLWin32.HDc) | 69 | else if (HDc != ExposedData.OpenGLWin32.HDc) |
70 | { | 70 | { |
71 | if (!wglMakeCurrent((HDC)ExposedData.OpenGLWin32.HDc, (HGLRC)ExposedData.OpenGLWin32.HRc)) | 71 | if (!wglMakeCurrent((HDC)ExposedData.OpenGLWin32.HDc, (HGLRC)ExposedData.OpenGLWin32.HRc)) |
72 | { | 72 | { |
73 | os::Printer::log("Render Context switch failed."); | 73 | os::Printer::log("Render Context switch failed."); |
74 | return false; | 74 | return false; |
75 | } | 75 | } |
76 | else | 76 | else |
77 | { | 77 | { |
78 | HDc = (HDC)ExposedData.OpenGLWin32.HDc; | 78 | HDc = (HDC)ExposedData.OpenGLWin32.HDc; |
79 | } | 79 | } |
80 | } | 80 | } |
81 | return true; | 81 | return true; |
82 | } | 82 | } |
83 | 83 | ||
84 | //! inits the open gl driver | 84 | //! inits the open gl driver |
85 | bool COpenGLDriver::initDriver(CIrrDeviceWin32* device) | 85 | bool COpenGLDriver::initDriver(CIrrDeviceWin32* device) |
86 | { | 86 | { |
87 | // Create a window to test antialiasing support | 87 | // Create a window to test antialiasing support |
88 | const fschar_t* ClassName = __TEXT("GLCIrrDeviceWin32"); | 88 | const fschar_t* ClassName = __TEXT("GLCIrrDeviceWin32"); |
89 | HINSTANCE lhInstance = GetModuleHandle(0); | 89 | HINSTANCE lhInstance = GetModuleHandle(0); |
90 | 90 | ||
91 | // Register Class | 91 | // Register Class |
92 | WNDCLASSEX wcex; | 92 | WNDCLASSEX wcex; |
93 | wcex.cbSize = sizeof(WNDCLASSEX); | 93 | wcex.cbSize = sizeof(WNDCLASSEX); |
94 | wcex.style = CS_HREDRAW | CS_VREDRAW; | 94 | wcex.style = CS_HREDRAW | CS_VREDRAW; |
95 | wcex.lpfnWndProc = (WNDPROC)DefWindowProc; | 95 | wcex.lpfnWndProc = (WNDPROC)DefWindowProc; |
96 | wcex.cbClsExtra = 0; | 96 | wcex.cbClsExtra = 0; |
97 | wcex.cbWndExtra = 0; | 97 | wcex.cbWndExtra = 0; |
98 | wcex.hInstance = lhInstance; | 98 | wcex.hInstance = lhInstance; |
99 | wcex.hIcon = NULL; | 99 | wcex.hIcon = NULL; |
100 | wcex.hCursor = LoadCursor(NULL, IDC_ARROW); | 100 | wcex.hCursor = LoadCursor(NULL, IDC_ARROW); |
101 | wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); | 101 | wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); |
102 | wcex.lpszMenuName = 0; | 102 | wcex.lpszMenuName = 0; |
103 | wcex.lpszClassName = ClassName; | 103 | wcex.lpszClassName = ClassName; |
104 | wcex.hIconSm = 0; | 104 | wcex.hIconSm = 0; |
105 | wcex.hIcon = 0; | 105 | wcex.hIcon = 0; |
106 | RegisterClassEx(&wcex); | 106 | RegisterClassEx(&wcex); |
107 | 107 | ||
108 | RECT clientSize; | 108 | RECT clientSize; |
109 | clientSize.top = 0; | 109 | clientSize.top = 0; |
110 | clientSize.left = 0; | 110 | clientSize.left = 0; |
111 | clientSize.right = Params.WindowSize.Width; | 111 | clientSize.right = Params.WindowSize.Width; |
112 | clientSize.bottom = Params.WindowSize.Height; | 112 | clientSize.bottom = Params.WindowSize.Height; |
113 | 113 | ||
114 | DWORD style = WS_POPUP; | 114 | DWORD style = WS_POPUP; |
115 | if (!Params.Fullscreen) | 115 | if (!Params.Fullscreen) |
116 | style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; | 116 | style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; |
117 | 117 | ||
118 | AdjustWindowRect(&clientSize, style, FALSE); | 118 | AdjustWindowRect(&clientSize, style, FALSE); |
119 | 119 | ||
120 | const s32 realWidth = clientSize.right - clientSize.left; | 120 | const s32 realWidth = clientSize.right - clientSize.left; |
121 | const s32 realHeight = clientSize.bottom - clientSize.top; | 121 | const s32 realHeight = clientSize.bottom - clientSize.top; |
122 | 122 | ||
123 | const s32 windowLeft = (GetSystemMetrics(SM_CXSCREEN) - realWidth) / 2; | 123 | const s32 windowLeft = (GetSystemMetrics(SM_CXSCREEN) - realWidth) / 2; |
124 | const s32 windowTop = (GetSystemMetrics(SM_CYSCREEN) - realHeight) / 2; | 124 | const s32 windowTop = (GetSystemMetrics(SM_CYSCREEN) - realHeight) / 2; |
125 | 125 | ||
126 | HWND temporary_wnd=CreateWindow(ClassName, __TEXT(""), style, windowLeft, | 126 | HWND temporary_wnd=CreateWindow(ClassName, __TEXT(""), style, windowLeft, |
127 | windowTop, realWidth, realHeight, NULL, NULL, lhInstance, NULL); | 127 | windowTop, realWidth, realHeight, NULL, NULL, lhInstance, NULL); |
128 | 128 | ||
129 | if (!temporary_wnd) | 129 | if (!temporary_wnd) |
130 | { | 130 | { |
131 | os::Printer::log("Cannot create a temporary window.", ELL_ERROR); | 131 | os::Printer::log("Cannot create a temporary window.", ELL_ERROR); |
132 | UnregisterClass(ClassName, lhInstance); | 132 | UnregisterClass(ClassName, lhInstance); |
133 | return false; | 133 | return false; |
134 | } | 134 | } |
135 | 135 | ||
136 | HDc = GetDC(temporary_wnd); | 136 | HDc = GetDC(temporary_wnd); |
137 | 137 | ||
138 | // Set up pixel format descriptor with desired parameters | 138 | // Set up pixel format descriptor with desired parameters |
139 | PIXELFORMATDESCRIPTOR pfd = { | 139 | PIXELFORMATDESCRIPTOR pfd = { |
140 | sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor | 140 | sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor |
141 | 1, // Version Number | 141 | 1, // Version Number |
142 | PFD_DRAW_TO_WINDOW | // Format Must Support Window | 142 | PFD_DRAW_TO_WINDOW | // Format Must Support Window |
143 | PFD_SUPPORT_OPENGL | // Format Must Support OpenGL | 143 | PFD_SUPPORT_OPENGL | // Format Must Support OpenGL |
144 | (Params.Doublebuffer?PFD_DOUBLEBUFFER:0) | // Must Support Double Buffering | 144 | (Params.Doublebuffer?PFD_DOUBLEBUFFER:0) | // Must Support Double Buffering |
145 | (Params.Stereobuffer?PFD_STEREO:0), // Must Support Stereo Buffer | 145 | (Params.Stereobuffer?PFD_STEREO:0), // Must Support Stereo Buffer |
146 | PFD_TYPE_RGBA, // Request An RGBA Format | 146 | PFD_TYPE_RGBA, // Request An RGBA Format |
147 | Params.Bits, // Select Our Color Depth | 147 | Params.Bits, // Select Our Color Depth |
148 | 0, 0, 0, 0, 0, 0, // Color Bits Ignored | 148 | 0, 0, 0, 0, 0, 0, // Color Bits Ignored |
149 | 0, // No Alpha Buffer | 149 | 0, // No Alpha Buffer |
150 | 0, // Shift Bit Ignored | 150 | 0, // Shift Bit Ignored |
151 | 0, // No Accumulation Buffer | 151 | 0, // No Accumulation Buffer |
152 | 0, 0, 0, 0, // Accumulation Bits Ignored | 152 | 0, 0, 0, 0, // Accumulation Bits Ignored |
153 | Params.ZBufferBits, // Z-Buffer (Depth Buffer) | 153 | Params.ZBufferBits, // Z-Buffer (Depth Buffer) |
154 | BYTE(Params.Stencilbuffer ? 1 : 0), // Stencil Buffer Depth | 154 | BYTE(Params.Stencilbuffer ? 1 : 0), // Stencil Buffer Depth |
155 | 0, // No Auxiliary Buffer | 155 | 0, // No Auxiliary Buffer |
156 | PFD_MAIN_PLANE, // Main Drawing Layer | 156 | PFD_MAIN_PLANE, // Main Drawing Layer |
157 | 0, // Reserved | 157 | 0, // Reserved |
158 | 0, 0, 0 // Layer Masks Ignored | 158 | 0, 0, 0 // Layer Masks Ignored |
159 | }; | 159 | }; |
160 | 160 | ||
161 | GLuint PixelFormat; | 161 | GLuint PixelFormat; |
162 | 162 | ||
163 | for (u32 i=0; i<6; ++i) | 163 | for (u32 i=0; i<6; ++i) |
164 | { | 164 | { |
165 | if (i == 1) | 165 | if (i == 1) |
166 | { | 166 | { |
167 | if (Params.Stencilbuffer) | 167 | if (Params.Stencilbuffer) |
168 | { | 168 | { |
169 | os::Printer::log("Cannot create a GL device with stencil buffer, disabling stencil shadows.", ELL_WARNING); | 169 | os::Printer::log("Cannot create a GL device with stencil buffer, disabling stencil shadows.", ELL_WARNING); |
170 | Params.Stencilbuffer = false; | 170 | Params.Stencilbuffer = false; |
171 | pfd.cStencilBits = 0; | 171 | pfd.cStencilBits = 0; |
172 | } | 172 | } |
173 | else | 173 | else |
174 | continue; | 174 | continue; |
175 | } | 175 | } |
176 | else | 176 | else |
177 | if (i == 2) | 177 | if (i == 2) |
178 | { | 178 | { |
179 | pfd.cDepthBits = 24; | 179 | pfd.cDepthBits = 24; |
180 | } | 180 | } |
181 | else | 181 | else |
182 | if (i == 3) | 182 | if (i == 3) |
183 | { | 183 | { |
184 | if (Params.Bits!=16) | 184 | if (Params.Bits!=16) |
185 | pfd.cDepthBits = 16; | 185 | pfd.cDepthBits = 16; |
186 | else | 186 | else |
187 | continue; | 187 | continue; |
188 | } | 188 | } |
189 | else | 189 | else |
190 | if (i == 4) | 190 | if (i == 4) |
191 | { | 191 | { |
192 | // try single buffer | 192 | // try single buffer |
193 | if (Params.Doublebuffer) | 193 | if (Params.Doublebuffer) |
194 | pfd.dwFlags &= ~PFD_DOUBLEBUFFER; | 194 | pfd.dwFlags &= ~PFD_DOUBLEBUFFER; |
195 | else | 195 | else |
196 | continue; | 196 | continue; |
197 | } | 197 | } |
198 | else | 198 | else |
199 | if (i == 5) | 199 | if (i == 5) |
200 | { | 200 | { |
201 | os::Printer::log("Cannot create a GL device context", "No suitable format for temporary window.", ELL_ERROR); | 201 | os::Printer::log("Cannot create a GL device context", "No suitable format for temporary window.", ELL_ERROR); |
202 | ReleaseDC(temporary_wnd, HDc); | 202 | ReleaseDC(temporary_wnd, HDc); |
203 | DestroyWindow(temporary_wnd); | 203 | DestroyWindow(temporary_wnd); |
204 | UnregisterClass(ClassName, lhInstance); | 204 | UnregisterClass(ClassName, lhInstance); |
205 | return false; | 205 | return false; |
206 | } | 206 | } |
207 | 207 | ||
208 | // choose pixelformat | 208 | // choose pixelformat |
209 | PixelFormat = ChoosePixelFormat(HDc, &pfd); | 209 | PixelFormat = ChoosePixelFormat(HDc, &pfd); |
210 | if (PixelFormat) | 210 | if (PixelFormat) |
211 | break; | 211 | break; |
212 | } | 212 | } |
213 | 213 | ||
214 | SetPixelFormat(HDc, PixelFormat, &pfd); | 214 | SetPixelFormat(HDc, PixelFormat, &pfd); |
215 | HGLRC hrc=wglCreateContext(HDc); | 215 | HGLRC hrc=wglCreateContext(HDc); |
216 | if (!hrc) | 216 | if (!hrc) |
217 | { | 217 | { |
218 | os::Printer::log("Cannot create a temporary GL rendering context.", ELL_ERROR); | 218 | os::Printer::log("Cannot create a temporary GL rendering context.", ELL_ERROR); |
219 | ReleaseDC(temporary_wnd, HDc); | 219 | ReleaseDC(temporary_wnd, HDc); |
220 | DestroyWindow(temporary_wnd); | 220 | DestroyWindow(temporary_wnd); |
221 | UnregisterClass(ClassName, lhInstance); | 221 | UnregisterClass(ClassName, lhInstance); |
222 | return false; | 222 | return false; |
223 | } | 223 | } |
224 | 224 | ||
225 | SExposedVideoData data; | 225 | SExposedVideoData data; |
226 | data.OpenGLWin32.HDc = HDc; | 226 | data.OpenGLWin32.HDc = HDc; |
227 | data.OpenGLWin32.HRc = hrc; | 227 | data.OpenGLWin32.HRc = hrc; |
228 | data.OpenGLWin32.HWnd = temporary_wnd; | 228 | data.OpenGLWin32.HWnd = temporary_wnd; |
229 | 229 | ||
230 | 230 | ||
231 | if (!changeRenderContext(data, device)) | 231 | if (!changeRenderContext(data, device)) |
232 | { | 232 | { |
233 | os::Printer::log("Cannot activate a temporary GL rendering context.", ELL_ERROR); | 233 | os::Printer::log("Cannot activate a temporary GL rendering context.", ELL_ERROR); |
234 | wglDeleteContext(hrc); | 234 | wglDeleteContext(hrc); |
235 | ReleaseDC(temporary_wnd, HDc); | 235 | ReleaseDC(temporary_wnd, HDc); |
236 | DestroyWindow(temporary_wnd); | 236 | DestroyWindow(temporary_wnd); |
237 | UnregisterClass(ClassName, lhInstance); | 237 | UnregisterClass(ClassName, lhInstance); |
238 | return false; | 238 | return false; |
239 | } | 239 | } |
240 | 240 | ||
241 | core::stringc wglExtensions; | 241 | core::stringc wglExtensions; |
242 | #ifdef WGL_ARB_extensions_string | 242 | #ifdef WGL_ARB_extensions_string |
243 | PFNWGLGETEXTENSIONSSTRINGARBPROC irrGetExtensionsString = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); | 243 | PFNWGLGETEXTENSIONSSTRINGARBPROC irrGetExtensionsString = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); |
244 | if (irrGetExtensionsString) | 244 | if (irrGetExtensionsString) |
245 | wglExtensions = irrGetExtensionsString(HDc); | 245 | wglExtensions = irrGetExtensionsString(HDc); |
246 | #elif defined(WGL_EXT_extensions_string) | 246 | #elif defined(WGL_EXT_extensions_string) |
247 | PFNWGLGETEXTENSIONSSTRINGEXTPROC irrGetExtensionsString = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)wglGetProcAddress("wglGetExtensionsStringEXT"); | 247 | PFNWGLGETEXTENSIONSSTRINGEXTPROC irrGetExtensionsString = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)wglGetProcAddress("wglGetExtensionsStringEXT"); |
248 | if (irrGetExtensionsString) | 248 | if (irrGetExtensionsString) |
249 | wglExtensions = irrGetExtensionsString(HDc); | 249 | wglExtensions = irrGetExtensionsString(HDc); |
250 | #endif | 250 | #endif |
251 | const bool pixel_format_supported = (wglExtensions.find("WGL_ARB_pixel_format") != -1); | 251 | const bool pixel_format_supported = (wglExtensions.find("WGL_ARB_pixel_format") != -1); |
252 | const bool multi_sample_supported = ((wglExtensions.find("WGL_ARB_multisample") != -1) || | 252 | const bool multi_sample_supported = ((wglExtensions.find("WGL_ARB_multisample") != -1) || |
253 | (wglExtensions.find("WGL_EXT_multisample") != -1) || (wglExtensions.find("WGL_3DFX_multisample") != -1) ); | 253 | (wglExtensions.find("WGL_EXT_multisample") != -1) || (wglExtensions.find("WGL_3DFX_multisample") != -1) ); |
254 | #ifdef _DEBUG | 254 | #ifdef _DEBUG |
255 | os::Printer::log("WGL_extensions", wglExtensions); | 255 | os::Printer::log("WGL_extensions", wglExtensions); |
256 | #endif | 256 | #endif |
257 | 257 | ||
258 | #ifdef WGL_ARB_pixel_format | 258 | #ifdef WGL_ARB_pixel_format |
259 | PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormat_ARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); | 259 | PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormat_ARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); |
260 | if (pixel_format_supported && wglChoosePixelFormat_ARB) | 260 | if (pixel_format_supported && wglChoosePixelFormat_ARB) |
261 | { | 261 | { |
262 | // This value determines the number of samples used for antialiasing | 262 | // This value determines the number of samples used for antialiasing |
263 | // My experience is that 8 does not show a big | 263 | // My experience is that 8 does not show a big |
264 | // improvement over 4, but 4 shows a big improvement | 264 | // improvement over 4, but 4 shows a big improvement |
265 | // over 2. | 265 | // over 2. |
266 | 266 | ||
267 | if(AntiAlias > 32) | 267 | if(AntiAlias > 32) |
268 | AntiAlias = 32; | 268 | AntiAlias = 32; |
269 | 269 | ||
270 | f32 fAttributes[] = {0.0, 0.0}; | 270 | f32 fAttributes[] = {0.0, 0.0}; |
271 | s32 iAttributes[] = | 271 | s32 iAttributes[] = |
272 | { | 272 | { |
273 | WGL_DRAW_TO_WINDOW_ARB,1, | 273 | WGL_DRAW_TO_WINDOW_ARB,1, |
274 | WGL_SUPPORT_OPENGL_ARB,1, | 274 | WGL_SUPPORT_OPENGL_ARB,1, |
275 | WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB, | 275 | WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB, |
276 | WGL_COLOR_BITS_ARB,(Params.Bits==32) ? 24 : 15, | 276 | WGL_COLOR_BITS_ARB,(Params.Bits==32) ? 24 : 15, |
277 | WGL_ALPHA_BITS_ARB,(Params.Bits==32) ? 8 : 1, | 277 | WGL_ALPHA_BITS_ARB,(Params.Bits==32) ? 8 : 1, |
278 | WGL_DEPTH_BITS_ARB,Params.ZBufferBits, // 10,11 | 278 | WGL_DEPTH_BITS_ARB,Params.ZBufferBits, // 10,11 |
279 | WGL_STENCIL_BITS_ARB,Params.Stencilbuffer ? 1 : 0, | 279 | WGL_STENCIL_BITS_ARB,Params.Stencilbuffer ? 1 : 0, |
280 | WGL_DOUBLE_BUFFER_ARB,Params.Doublebuffer ? 1 : 0, | 280 | WGL_DOUBLE_BUFFER_ARB,Params.Doublebuffer ? 1 : 0, |
281 | WGL_STEREO_ARB,Params.Stereobuffer ? 1 : 0, | 281 | WGL_STEREO_ARB,Params.Stereobuffer ? 1 : 0, |
282 | WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, | 282 | WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, |
283 | #ifdef WGL_ARB_multisample | 283 | #ifdef WGL_ARB_multisample |
284 | WGL_SAMPLES_ARB,AntiAlias, // 20,21 | 284 | WGL_SAMPLES_ARB,AntiAlias, // 20,21 |
285 | WGL_SAMPLE_BUFFERS_ARB, 1, | 285 | WGL_SAMPLE_BUFFERS_ARB, 1, |
286 | #elif defined(WGL_EXT_multisample) | 286 | #elif defined(WGL_EXT_multisample) |
287 | WGL_SAMPLES_EXT,AntiAlias, // 20,21 | 287 | WGL_SAMPLES_EXT,AntiAlias, // 20,21 |
288 | WGL_SAMPLE_BUFFERS_EXT, 1, | 288 | WGL_SAMPLE_BUFFERS_EXT, 1, |
289 | #elif defined(WGL_3DFX_multisample) | 289 | #elif defined(WGL_3DFX_multisample) |
290 | WGL_SAMPLES_3DFX,AntiAlias, // 20,21 | 290 | WGL_SAMPLES_3DFX,AntiAlias, // 20,21 |
291 | WGL_SAMPLE_BUFFERS_3DFX, 1, | 291 | WGL_SAMPLE_BUFFERS_3DFX, 1, |
292 | #endif | 292 | #endif |
293 | #ifdef WGL_ARB_framebuffer_sRGB | 293 | #ifdef WGL_ARB_framebuffer_sRGB |
294 | WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, Params.HandleSRGB ? 1:0, | 294 | WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, Params.HandleSRGB ? 1:0, |
295 | #elif defined(WGL_EXT_framebuffer_sRGB) | 295 | #elif defined(WGL_EXT_framebuffer_sRGB) |
296 | WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT, Params.HandleSRGB ? 1:0, | 296 | WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT, Params.HandleSRGB ? 1:0, |
297 | #endif | 297 | #endif |
298 | // WGL_DEPTH_FLOAT_EXT, 1, | 298 | // WGL_DEPTH_FLOAT_EXT, 1, |
299 | 0,0,0,0 | 299 | 0,0,0,0 |
300 | }; | 300 | }; |
301 | int iAttrSize = sizeof(iAttributes)/sizeof(int); | 301 | int iAttrSize = sizeof(iAttributes)/sizeof(int); |
302 | const bool framebuffer_srgb_supported = ((wglExtensions.find("WGL_ARB_framebuffer_sRGB") != -1) || | 302 | const bool framebuffer_srgb_supported = ((wglExtensions.find("WGL_ARB_framebuffer_sRGB") != -1) || |
303 | (wglExtensions.find("WGL_EXT_framebuffer_sRGB") != -1)); | 303 | (wglExtensions.find("WGL_EXT_framebuffer_sRGB") != -1)); |
304 | if (!framebuffer_srgb_supported) | 304 | if (!framebuffer_srgb_supported) |
305 | { | 305 | { |
306 | memmove(&iAttributes[24],&iAttributes[26],sizeof(int)*(iAttrSize-26)); | 306 | memmove(&iAttributes[24],&iAttributes[26],sizeof(int)*(iAttrSize-26)); |
307 | iAttrSize -= 2; | 307 | iAttrSize -= 2; |
308 | } | 308 | } |
309 | if (!multi_sample_supported) | 309 | if (!multi_sample_supported) |
310 | { | 310 | { |
311 | memmove(&iAttributes[20],&iAttributes[24],sizeof(int)*(iAttrSize-24)); | 311 | memmove(&iAttributes[20],&iAttributes[24],sizeof(int)*(iAttrSize-24)); |
312 | iAttrSize -= 4; | 312 | iAttrSize -= 4; |
313 | } | 313 | } |
314 | 314 | ||
315 | s32 rv=0; | 315 | s32 rv=0; |
316 | // Try to get an acceptable pixel format | 316 | // Try to get an acceptable pixel format |
317 | do | 317 | do |
318 | { | 318 | { |
319 | int pixelFormat=0; | 319 | int pixelFormat=0; |
320 | UINT numFormats=0; | 320 | UINT numFormats=0; |
321 | const BOOL valid = wglChoosePixelFormat_ARB(HDc,iAttributes,fAttributes,1,&pixelFormat,&numFormats); | 321 | const BOOL valid = wglChoosePixelFormat_ARB(HDc,iAttributes,fAttributes,1,&pixelFormat,&numFormats); |
322 | 322 | ||
323 | if (valid && numFormats) | 323 | if (valid && numFormats) |
324 | rv = pixelFormat; | 324 | rv = pixelFormat; |
325 | else | 325 | else |
326 | iAttributes[21] -= 1; | 326 | iAttributes[21] -= 1; |
327 | } | 327 | } |
328 | while(rv==0 && iAttributes[21]>1); | 328 | while(rv==0 && iAttributes[21]>1); |
329 | if (rv) | 329 | if (rv) |
330 | { | 330 | { |
331 | PixelFormat=rv; | 331 | PixelFormat=rv; |
332 | AntiAlias=iAttributes[21]; | 332 | AntiAlias=iAttributes[21]; |
333 | } | 333 | } |
334 | } | 334 | } |
335 | else | 335 | else |
336 | #endif | 336 | #endif |
337 | AntiAlias=0; | 337 | AntiAlias=0; |
338 | 338 | ||
339 | wglMakeCurrent(HDc, NULL); | 339 | wglMakeCurrent(HDc, NULL); |
340 | wglDeleteContext(hrc); | 340 | wglDeleteContext(hrc); |
341 | ReleaseDC(temporary_wnd, HDc); | 341 | ReleaseDC(temporary_wnd, HDc); |
342 | DestroyWindow(temporary_wnd); | 342 | DestroyWindow(temporary_wnd); |
343 | UnregisterClass(ClassName, lhInstance); | 343 | UnregisterClass(ClassName, lhInstance); |
344 | 344 | ||
345 | // get hdc | 345 | // get hdc |
346 | HDc=GetDC(Window); | 346 | HDc=GetDC(Window); |
347 | if (!HDc) | 347 | if (!HDc) |
348 | { | 348 | { |
349 | os::Printer::log("Cannot create a GL device context.", ELL_ERROR); | 349 | os::Printer::log("Cannot create a GL device context.", ELL_ERROR); |
350 | return false; | 350 | return false; |
351 | } | 351 | } |
352 | 352 | ||
353 | // search for pixel format the simple way | 353 | // search for pixel format the simple way |
354 | if (PixelFormat==0 || (!SetPixelFormat(HDc, PixelFormat, &pfd))) | 354 | if (PixelFormat==0 || (!SetPixelFormat(HDc, PixelFormat, &pfd))) |
355 | { | 355 | { |
356 | for (u32 i=0; i<5; ++i) | 356 | for (u32 i=0; i<5; ++i) |
357 | { | 357 | { |
358 | if (i == 1) | 358 | if (i == 1) |
359 | { | 359 | { |
360 | if (Params.Stencilbuffer) | 360 | if (Params.Stencilbuffer) |
361 | { | 361 | { |
362 | os::Printer::log("Cannot create a GL device with stencil buffer, disabling stencil shadows.", ELL_WARNING); | 362 | os::Printer::log("Cannot create a GL device with stencil buffer, disabling stencil shadows.", ELL_WARNING); |
363 | Params.Stencilbuffer = false; | 363 | Params.Stencilbuffer = false; |
364 | pfd.cStencilBits = 0; | 364 | pfd.cStencilBits = 0; |
365 | } | 365 | } |
366 | else | 366 | else |
367 | continue; | 367 | continue; |
368 | } | 368 | } |
369 | else | 369 | else |
370 | if (i == 2) | 370 | if (i == 2) |
371 | { | 371 | { |
372 | pfd.cDepthBits = 24; | 372 | pfd.cDepthBits = 24; |
373 | } | 373 | } |
374 | if (i == 3) | 374 | if (i == 3) |
375 | { | 375 | { |
376 | if (Params.Bits!=16) | 376 | if (Params.Bits!=16) |
377 | pfd.cDepthBits = 16; | 377 | pfd.cDepthBits = 16; |
378 | else | 378 | else |
379 | continue; | 379 | continue; |
380 | } | 380 | } |
381 | else | 381 | else |
382 | if (i == 4) | 382 | if (i == 4) |
383 | { | 383 | { |
384 | os::Printer::log("Cannot create a GL device context", "No suitable format.", ELL_ERROR); | 384 | os::Printer::log("Cannot create a GL device context", "No suitable format.", ELL_ERROR); |
385 | return false; | 385 | return false; |
386 | } | 386 | } |
387 | 387 | ||
388 | // choose pixelformat | 388 | // choose pixelformat |
389 | PixelFormat = ChoosePixelFormat(HDc, &pfd); | 389 | PixelFormat = ChoosePixelFormat(HDc, &pfd); |
390 | if (PixelFormat) | 390 | if (PixelFormat) |
391 | break; | 391 | break; |
392 | } | 392 | } |
393 | } | 393 | } |
394 | 394 | ||
395 | // set pixel format | 395 | // set pixel format |
396 | if (!SetPixelFormat(HDc, PixelFormat, &pfd)) | 396 | if (!SetPixelFormat(HDc, PixelFormat, &pfd)) |
397 | { | 397 | { |
398 | os::Printer::log("Cannot set the pixel format.", ELL_ERROR); | 398 | os::Printer::log("Cannot set the pixel format.", ELL_ERROR); |
399 | return false; | 399 | return false; |
400 | } | 400 | } |
401 | os::Printer::log("Pixel Format", core::stringc(PixelFormat).c_str(), ELL_DEBUG); | 401 | os::Printer::log("Pixel Format", core::stringc(PixelFormat).c_str(), ELL_DEBUG); |
402 | 402 | ||
403 | // create rendering context | 403 | // create rendering context |
404 | #ifdef WGL_ARB_create_context | 404 | #ifdef WGL_ARB_create_context |
405 | PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs_ARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); | 405 | PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs_ARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); |
406 | if (wglCreateContextAttribs_ARB) | 406 | if (wglCreateContextAttribs_ARB) |
407 | { | 407 | { |
408 | int iAttribs[] = | 408 | int iAttribs[] = |
409 | { | 409 | { |
410 | WGL_CONTEXT_MAJOR_VERSION_ARB, 3, | 410 | WGL_CONTEXT_MAJOR_VERSION_ARB, 3, |
411 | WGL_CONTEXT_MINOR_VERSION_ARB, 1, | 411 | WGL_CONTEXT_MINOR_VERSION_ARB, 1, |
412 | 0 | 412 | 0 |
413 | }; | 413 | }; |
414 | hrc=wglCreateContextAttribs_ARB(HDc, 0, iAttribs); | 414 | hrc=wglCreateContextAttribs_ARB(HDc, 0, iAttribs); |
415 | } | 415 | } |
416 | else | 416 | else |
417 | #endif | 417 | #endif |
418 | hrc=wglCreateContext(HDc); | 418 | hrc=wglCreateContext(HDc); |
419 | 419 | ||
420 | if (!hrc) | 420 | if (!hrc) |
421 | { | 421 | { |
422 | os::Printer::log("Cannot create a GL rendering context.", ELL_ERROR); | 422 | os::Printer::log("Cannot create a GL rendering context.", ELL_ERROR); |
423 | return false; | 423 | return false; |
424 | } | 424 | } |
425 | 425 | ||
426 | // set exposed data | 426 | // set exposed data |
427 | ExposedData.OpenGLWin32.HDc = HDc; | 427 | ExposedData.OpenGLWin32.HDc = HDc; |
428 | ExposedData.OpenGLWin32.HRc = hrc; | 428 | ExposedData.OpenGLWin32.HRc = hrc; |
429 | ExposedData.OpenGLWin32.HWnd = Window; | 429 | ExposedData.OpenGLWin32.HWnd = Window; |
430 | 430 | ||
431 | // activate rendering context | 431 | // activate rendering context |
432 | 432 | ||
433 | if (!changeRenderContext(ExposedData, device)) | 433 | if (!changeRenderContext(ExposedData, device)) |
434 | { | 434 | { |
435 | os::Printer::log("Cannot activate GL rendering context", ELL_ERROR); | 435 | os::Printer::log("Cannot activate GL rendering context", ELL_ERROR); |
436 | wglDeleteContext(hrc); | 436 | wglDeleteContext(hrc); |
437 | return false; | 437 | return false; |
438 | } | 438 | } |
439 | 439 | ||
440 | int pf = GetPixelFormat(HDc); | 440 | int pf = GetPixelFormat(HDc); |
441 | DescribePixelFormat(HDc, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd); | 441 | DescribePixelFormat(HDc, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd); |
442 | if (pfd.cAlphaBits != 0) | 442 | if (pfd.cAlphaBits != 0) |
443 | { | 443 | { |
444 | if (pfd.cRedBits == 8) | 444 | if (pfd.cRedBits == 8) |
445 | ColorFormat = ECF_A8R8G8B8; | 445 | ColorFormat = ECF_A8R8G8B8; |
446 | else | 446 | else |
447 | ColorFormat = ECF_A1R5G5B5; | 447 | ColorFormat = ECF_A1R5G5B5; |
448 | } | 448 | } |
449 | else | 449 | else |
450 | { | 450 | { |
451 | if (pfd.cRedBits == 8) | 451 | if (pfd.cRedBits == 8) |
452 | ColorFormat = ECF_R8G8B8; | 452 | ColorFormat = ECF_R8G8B8; |
453 | else | 453 | else |
454 | ColorFormat = ECF_R5G6B5; | 454 | ColorFormat = ECF_R5G6B5; |
455 | } | 455 | } |
456 | 456 | ||
457 | genericDriverInit(); | 457 | genericDriverInit(); |
458 | 458 | ||
459 | extGlSwapInterval(Params.Vsync ? 1 : 0); | 459 | extGlSwapInterval(Params.Vsync ? 1 : 0); |
460 | return true; | 460 | return true; |
461 | } | 461 | } |
462 | 462 | ||
463 | #endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_ | 463 | #endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_ |
464 | 464 | ||
465 | // ----------------------------------------------------------------------- | 465 | // ----------------------------------------------------------------------- |
466 | // MacOSX CONSTRUCTOR | 466 | // MacOSX CONSTRUCTOR |
467 | // ----------------------------------------------------------------------- | 467 | // ----------------------------------------------------------------------- |
468 | #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ | 468 | #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ |
469 | //! Windows constructor and init code | 469 | //! Windows constructor and init code |
470 | COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, | 470 | COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, |
471 | io::IFileSystem* io, CIrrDeviceMacOSX *device) | 471 | io::IFileSystem* io, CIrrDeviceMacOSX *device) |
472 | : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), | 472 | : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), |
473 | CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), | 473 | CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), |
474 | AntiAlias(params.AntiAlias), RenderTargetTexture(0), | 474 | AntiAlias(params.AntiAlias), RenderTargetTexture(0), |
475 | CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), | 475 | CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), |
476 | CurrentTarget(ERT_FRAME_BUFFER), Params(params), | 476 | CurrentTarget(ERT_FRAME_BUFFER), Params(params), |
477 | OSXDevice(device), DeviceType(EIDT_OSX) | 477 | OSXDevice(device), DeviceType(EIDT_OSX) |
478 | { | 478 | { |
479 | #ifdef _DEBUG | 479 | #ifdef _DEBUG |
480 | setDebugName("COpenGLDriver"); | 480 | setDebugName("COpenGLDriver"); |
481 | #endif | 481 | #endif |
482 | 482 | ||
483 | #ifdef _IRR_COMPILE_WITH_CG_ | 483 | #ifdef _IRR_COMPILE_WITH_CG_ |
484 | CgContext = 0; | 484 | CgContext = 0; |
485 | #endif | 485 | #endif |
486 | 486 | ||
487 | genericDriverInit(); | 487 | genericDriverInit(); |
488 | } | 488 | } |
489 | 489 | ||
490 | #endif | 490 | #endif |
491 | 491 | ||
492 | // ----------------------------------------------------------------------- | 492 | // ----------------------------------------------------------------------- |
493 | // LINUX CONSTRUCTOR | 493 | // LINUX CONSTRUCTOR |
494 | // ----------------------------------------------------------------------- | 494 | // ----------------------------------------------------------------------- |
495 | #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ | 495 | #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ |
496 | //! Linux constructor and init code | 496 | //! Linux constructor and init code |
497 | COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, | 497 | COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, |
498 | io::IFileSystem* io, CIrrDeviceLinux* device) | 498 | io::IFileSystem* io, CIrrDeviceLinux* device) |
499 | : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), | 499 | : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), |
500 | CurrentRenderMode(ERM_NONE), ResetRenderStates(true), | 500 | CurrentRenderMode(ERM_NONE), ResetRenderStates(true), |
501 | Transformation3DChanged(true), AntiAlias(params.AntiAlias), | 501 | Transformation3DChanged(true), AntiAlias(params.AntiAlias), |
502 | RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), | 502 | RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), |
503 | CurrentTarget(ERT_FRAME_BUFFER), Params(params), | 503 | CurrentTarget(ERT_FRAME_BUFFER), Params(params), |
504 | X11Device(device), DeviceType(EIDT_X11) | 504 | X11Device(device), DeviceType(EIDT_X11) |
505 | { | 505 | { |
506 | #ifdef _DEBUG | 506 | #ifdef _DEBUG |
507 | setDebugName("COpenGLDriver"); | 507 | setDebugName("COpenGLDriver"); |
508 | #endif | 508 | #endif |
509 | 509 | ||
510 | #ifdef _IRR_COMPILE_WITH_CG_ | 510 | #ifdef _IRR_COMPILE_WITH_CG_ |
511 | CgContext = 0; | 511 | CgContext = 0; |
512 | #endif | 512 | #endif |
513 | } | 513 | } |
514 | 514 | ||
515 | 515 | ||
516 | bool COpenGLDriver::changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceLinux* device) | 516 | bool COpenGLDriver::changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceLinux* device) |
517 | { | 517 | { |
518 | if (videoData.OpenGLLinux.X11Window) | 518 | if (videoData.OpenGLLinux.X11Window) |
519 | { | 519 | { |
520 | if (videoData.OpenGLLinux.X11Display && videoData.OpenGLLinux.X11Context) | 520 | if (videoData.OpenGLLinux.X11Display && videoData.OpenGLLinux.X11Context) |
521 | { | 521 | { |
522 | if (!glXMakeCurrent((Display*)videoData.OpenGLLinux.X11Display, videoData.OpenGLLinux.X11Window, (GLXContext)videoData.OpenGLLinux.X11Context)) | 522 | if (!glXMakeCurrent((Display*)videoData.OpenGLLinux.X11Display, videoData.OpenGLLinux.X11Window, (GLXContext)videoData.OpenGLLinux.X11Context)) |
523 | { | 523 | { |
524 | os::Printer::log("Render Context switch failed."); | 524 | os::Printer::log("Render Context switch failed."); |
525 | return false; | 525 | return false; |
526 | } | 526 | } |
527 | else | 527 | else |
528 | { | 528 | { |
529 | Drawable = videoData.OpenGLLinux.X11Window; | 529 | Drawable = videoData.OpenGLLinux.X11Window; |
530 | X11Display = (Display*)videoData.OpenGLLinux.X11Display; | 530 | X11Display = (Display*)videoData.OpenGLLinux.X11Display; |
531 | } | 531 | } |
532 | } | 532 | } |
533 | else | 533 | else |
534 | { | 534 | { |
535 | // in case we only got a window ID, try with the existing values for display and context | 535 | // in case we only got a window ID, try with the existing values for display and context |
536 | if (!glXMakeCurrent((Display*)ExposedData.OpenGLLinux.X11Display, videoData.OpenGLLinux.X11Window, (GLXContext)ExposedData.OpenGLLinux.X11Context)) | 536 | if (!glXMakeCurrent((Display*)ExposedData.OpenGLLinux.X11Display, videoData.OpenGLLinux.X11Window, (GLXContext)ExposedData.OpenGLLinux.X11Context)) |
537 | { | 537 | { |
538 | os::Printer::log("Render Context switch failed."); | 538 | os::Printer::log("Render Context switch failed."); |
539 | return false; | 539 | return false; |
540 | } | 540 | } |
541 | else | 541 | else |
542 | { | 542 | { |
543 | Drawable = videoData.OpenGLLinux.X11Window; | 543 | Drawable = videoData.OpenGLLinux.X11Window; |
544 | X11Display = (Display*)ExposedData.OpenGLLinux.X11Display; | 544 | X11Display = (Display*)ExposedData.OpenGLLinux.X11Display; |
545 | } | 545 | } |
546 | } | 546 | } |
547 | } | 547 | } |
548 | // set back to main context | 548 | // set back to main context |
549 | else if (X11Display != ExposedData.OpenGLLinux.X11Display) | 549 | else if (X11Display != ExposedData.OpenGLLinux.X11Display) |
550 | { | 550 | { |
551 | if (!glXMakeCurrent((Display*)ExposedData.OpenGLLinux.X11Display, ExposedData.OpenGLLinux.X11Window, (GLXContext)ExposedData.OpenGLLinux.X11Context)) | 551 | if (!glXMakeCurrent((Display*)ExposedData.OpenGLLinux.X11Display, ExposedData.OpenGLLinux.X11Window, (GLXContext)ExposedData.OpenGLLinux.X11Context)) |
552 | { | 552 | { |
553 | os::Printer::log("Render Context switch failed."); | 553 | os::Printer::log("Render Context switch failed."); |
554 | return false; | 554 | return false; |
555 | } | 555 | } |
556 | else | 556 | else |
557 | { | 557 | { |
558 | Drawable = ExposedData.OpenGLLinux.X11Window; | 558 | Drawable = ExposedData.OpenGLLinux.X11Window; |
559 | X11Display = (Display*)ExposedData.OpenGLLinux.X11Display; | 559 | X11Display = (Display*)ExposedData.OpenGLLinux.X11Display; |
560 | } | 560 | } |
561 | } | 561 | } |
562 | return true; | 562 | return true; |
563 | } | 563 | } |
564 | 564 | ||
565 | 565 | ||
566 | //! inits the open gl driver | 566 | //! inits the open gl driver |
567 | bool COpenGLDriver::initDriver(CIrrDeviceLinux* device) | 567 | bool COpenGLDriver::initDriver(CIrrDeviceLinux* device) |
568 | { | 568 | { |
569 | ExposedData.OpenGLLinux.X11Context = glXGetCurrentContext(); | 569 | ExposedData.OpenGLLinux.X11Context = glXGetCurrentContext(); |
570 | ExposedData.OpenGLLinux.X11Display = glXGetCurrentDisplay(); | 570 | ExposedData.OpenGLLinux.X11Display = glXGetCurrentDisplay(); |
571 | ExposedData.OpenGLLinux.X11Window = (unsigned long)Params.WindowId; | 571 | ExposedData.OpenGLLinux.X11Window = (unsigned long)Params.WindowId; |
572 | Drawable = glXGetCurrentDrawable(); | 572 | Drawable = glXGetCurrentDrawable(); |
573 | X11Display = (Display*)ExposedData.OpenGLLinux.X11Display; | 573 | X11Display = (Display*)ExposedData.OpenGLLinux.X11Display; |
574 | 574 | ||
575 | genericDriverInit(); | 575 | genericDriverInit(); |
576 | 576 | ||
577 | // set vsync | 577 | // set vsync |
578 | extGlSwapInterval(Params.Vsync ? 1 : 0); | 578 | extGlSwapInterval(Params.Vsync ? 1 : 0); |
579 | return true; | 579 | return true; |
580 | } | 580 | } |
581 | 581 | ||
582 | #endif // _IRR_COMPILE_WITH_X11_DEVICE_ | 582 | #endif // _IRR_COMPILE_WITH_X11_DEVICE_ |
583 | 583 | ||
584 | 584 | ||
585 | // ----------------------------------------------------------------------- | 585 | // ----------------------------------------------------------------------- |
586 | // SDL CONSTRUCTOR | 586 | // SDL CONSTRUCTOR |
587 | // ----------------------------------------------------------------------- | 587 | // ----------------------------------------------------------------------- |
588 | #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ | 588 | #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ |
589 | //! SDL constructor and init code | 589 | //! SDL constructor and init code |
590 | COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, | 590 | COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, |
591 | io::IFileSystem* io, CIrrDeviceSDL* device) | 591 | io::IFileSystem* io, CIrrDeviceSDL* device) |
592 | : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), | 592 | : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), |
593 | CurrentRenderMode(ERM_NONE), ResetRenderStates(true), | 593 | CurrentRenderMode(ERM_NONE), ResetRenderStates(true), |
594 | Transformation3DChanged(true), AntiAlias(params.AntiAlias), | 594 | Transformation3DChanged(true), AntiAlias(params.AntiAlias), |
595 | RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), | 595 | RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), |
596 | CurrentTarget(ERT_FRAME_BUFFER), Params(params), | 596 | CurrentTarget(ERT_FRAME_BUFFER), Params(params), |
597 | SDLDevice(device), DeviceType(EIDT_SDL) | 597 | SDLDevice(device), DeviceType(EIDT_SDL) |
598 | { | 598 | { |
599 | #ifdef _DEBUG | 599 | #ifdef _DEBUG |
600 | setDebugName("COpenGLDriver"); | 600 | setDebugName("COpenGLDriver"); |
601 | #endif | 601 | #endif |
602 | 602 | ||
603 | #ifdef _IRR_COMPILE_WITH_CG_ | 603 | #ifdef _IRR_COMPILE_WITH_CG_ |
604 | CgContext = 0; | 604 | CgContext = 0; |
605 | #endif | 605 | #endif |
606 | 606 | ||
607 | genericDriverInit(); | 607 | genericDriverInit(); |
608 | } | 608 | } |
609 | 609 | ||
610 | #endif // _IRR_COMPILE_WITH_SDL_DEVICE_ | 610 | #endif // _IRR_COMPILE_WITH_SDL_DEVICE_ |
611 | 611 | ||
612 | 612 | ||
613 | //! destructor | 613 | //! destructor |
614 | COpenGLDriver::~COpenGLDriver() | 614 | COpenGLDriver::~COpenGLDriver() |
615 | { | 615 | { |
616 | #ifdef _IRR_COMPILE_WITH_CG_ | 616 | #ifdef _IRR_COMPILE_WITH_CG_ |
617 | if (CgContext) | 617 | if (CgContext) |
618 | cgDestroyContext(CgContext); | 618 | cgDestroyContext(CgContext); |
619 | #endif | 619 | #endif |
620 | 620 | ||
621 | RequestedLights.clear(); | 621 | RequestedLights.clear(); |
622 | 622 | ||
623 | deleteMaterialRenders(); | 623 | deleteMaterialRenders(); |
624 | 624 | ||
625 | CurrentTexture.clear(); | 625 | CurrentTexture.clear(); |
626 | // I get a blue screen on my laptop, when I do not delete the | 626 | // I get a blue screen on my laptop, when I do not delete the |
627 | // textures manually before releasing the dc. Oh how I love this. | 627 | // textures manually before releasing the dc. Oh how I love this. |
628 | deleteAllTextures(); | 628 | deleteAllTextures(); |
629 | removeAllOcclusionQueries(); | 629 | removeAllOcclusionQueries(); |
630 | removeAllHardwareBuffers(); | 630 | removeAllHardwareBuffers(); |
631 | 631 | ||
632 | #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ | 632 | #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ |
633 | if (DeviceType == EIDT_WIN32) | 633 | if (DeviceType == EIDT_WIN32) |
634 | { | 634 | { |
635 | 635 | ||
636 | if (ExposedData.OpenGLWin32.HRc) | 636 | if (ExposedData.OpenGLWin32.HRc) |
637 | { | 637 | { |
638 | if (!wglMakeCurrent(HDc, 0)) | 638 | if (!wglMakeCurrent(HDc, 0)) |
639 | os::Printer::log("Release of dc and rc failed.", ELL_WARNING); | 639 | os::Printer::log("Release of dc and rc failed.", ELL_WARNING); |
640 | 640 | ||
641 | if (!wglDeleteContext((HGLRC)ExposedData.OpenGLWin32.HRc)) | 641 | if (!wglDeleteContext((HGLRC)ExposedData.OpenGLWin32.HRc)) |
642 | os::Printer::log("Release of rendering context failed.", ELL_WARNING); | 642 | os::Printer::log("Release of rendering context failed.", ELL_WARNING); |
643 | } | 643 | } |
644 | 644 | ||
645 | if (HDc) | 645 | if (HDc) |
646 | ReleaseDC(Window, HDc); | 646 | ReleaseDC(Window, HDc); |
647 | } | 647 | } |
648 | #endif | 648 | #endif |
649 | } | 649 | } |
650 | 650 | ||
651 | // ----------------------------------------------------------------------- | 651 | // ----------------------------------------------------------------------- |
652 | // METHODS | 652 | // METHODS |
653 | // ----------------------------------------------------------------------- | 653 | // ----------------------------------------------------------------------- |
654 | 654 | ||
655 | bool COpenGLDriver::genericDriverInit() | 655 | bool COpenGLDriver::genericDriverInit() |
656 | { | 656 | { |
657 | Name=L"OpenGL "; | 657 | Name=L"OpenGL "; |
658 | Name.append(glGetString(GL_VERSION)); | 658 | Name.append(glGetString(GL_VERSION)); |
659 | s32 pos=Name.findNext(L' ', 7); | 659 | s32 pos=Name.findNext(L' ', 7); |
660 | if (pos != -1) | 660 | if (pos != -1) |
661 | Name=Name.subString(0, pos); | 661 | Name=Name.subString(0, pos); |
662 | printVersion(); | 662 | printVersion(); |
663 | 663 | ||
664 | // print renderer information | 664 | // print renderer information |
665 | const GLubyte* renderer = glGetString(GL_RENDERER); | 665 | const GLubyte* renderer = glGetString(GL_RENDERER); |
666 | const GLubyte* vendor = glGetString(GL_VENDOR); | 666 | const GLubyte* vendor = glGetString(GL_VENDOR); |
667 | if (renderer && vendor) | 667 | if (renderer && vendor) |
668 | { | 668 | { |
669 | os::Printer::log(reinterpret_cast<const c8*>(renderer), reinterpret_cast<const c8*>(vendor), ELL_INFORMATION); | 669 | os::Printer::log(reinterpret_cast<const c8*>(renderer), reinterpret_cast<const c8*>(vendor), ELL_INFORMATION); |
670 | VendorName = reinterpret_cast<const c8*>(vendor); | 670 | VendorName = reinterpret_cast<const c8*>(vendor); |
671 | } | 671 | } |
672 | 672 | ||
673 | u32 i; | 673 | u32 i; |
674 | CurrentTexture.clear(); | 674 | CurrentTexture.clear(); |
675 | // load extensions | 675 | // load extensions |
676 | initExtensions(Params.Stencilbuffer); | 676 | initExtensions(Params.Stencilbuffer); |
677 | if (queryFeature(EVDF_ARB_GLSL)) | 677 | if (queryFeature(EVDF_ARB_GLSL)) |
678 | { | 678 | { |
679 | char buf[32]; | 679 | char buf[32]; |
680 | const u32 maj = ShaderLanguageVersion/100; | 680 | const u32 maj = ShaderLanguageVersion/100; |
681 | snprintf(buf, 32, "%u.%u", maj, ShaderLanguageVersion-maj*100); | 681 | snprintf(buf, 32, "%u.%u", maj, ShaderLanguageVersion-maj*100); |
682 | os::Printer::log("GLSL version", buf, ELL_INFORMATION); | 682 | os::Printer::log("GLSL version", buf, ELL_INFORMATION); |
683 | } | 683 | } |
684 | else | 684 | else |
685 | os::Printer::log("GLSL not available.", ELL_INFORMATION); | 685 | os::Printer::log("GLSL not available.", ELL_INFORMATION); |
686 | DriverAttributes->setAttribute("MaxTextures", MaxTextureUnits); | 686 | DriverAttributes->setAttribute("MaxTextures", MaxTextureUnits); |
687 | DriverAttributes->setAttribute("MaxSupportedTextures", MaxSupportedTextures); | 687 | DriverAttributes->setAttribute("MaxSupportedTextures", MaxSupportedTextures); |
688 | DriverAttributes->setAttribute("MaxLights", MaxLights); | 688 | DriverAttributes->setAttribute("MaxLights", MaxLights); |
689 | DriverAttributes->setAttribute("MaxAnisotropy", MaxAnisotropy); | 689 | DriverAttributes->setAttribute("MaxAnisotropy", MaxAnisotropy); |
690 | DriverAttributes->setAttribute("MaxUserClipPlanes", MaxUserClipPlanes); | 690 | DriverAttributes->setAttribute("MaxUserClipPlanes", MaxUserClipPlanes); |
691 | DriverAttributes->setAttribute("MaxAuxBuffers", MaxAuxBuffers); | 691 | DriverAttributes->setAttribute("MaxAuxBuffers", MaxAuxBuffers); |
692 | DriverAttributes->setAttribute("MaxMultipleRenderTargets", MaxMultipleRenderTargets); | 692 | DriverAttributes->setAttribute("MaxMultipleRenderTargets", MaxMultipleRenderTargets); |
693 | DriverAttributes->setAttribute("MaxIndices", (s32)MaxIndices); | 693 | DriverAttributes->setAttribute("MaxIndices", (s32)MaxIndices); |
694 | DriverAttributes->setAttribute("MaxTextureSize", (s32)MaxTextureSize); | 694 | DriverAttributes->setAttribute("MaxTextureSize", (s32)MaxTextureSize); |
695 | DriverAttributes->setAttribute("MaxGeometryVerticesOut", (s32)MaxGeometryVerticesOut); | 695 | DriverAttributes->setAttribute("MaxGeometryVerticesOut", (s32)MaxGeometryVerticesOut); |
696 | DriverAttributes->setAttribute("MaxTextureLODBias", MaxTextureLODBias); | 696 | DriverAttributes->setAttribute("MaxTextureLODBias", MaxTextureLODBias); |
697 | DriverAttributes->setAttribute("Version", Version); | 697 | DriverAttributes->setAttribute("Version", Version); |
698 | DriverAttributes->setAttribute("ShaderLanguageVersion", ShaderLanguageVersion); | 698 | DriverAttributes->setAttribute("ShaderLanguageVersion", ShaderLanguageVersion); |
699 | DriverAttributes->setAttribute("AntiAlias", AntiAlias); | 699 | DriverAttributes->setAttribute("AntiAlias", AntiAlias); |
700 | 700 | ||
701 | glPixelStorei(GL_PACK_ALIGNMENT, 1); | 701 | glPixelStorei(GL_PACK_ALIGNMENT, 1); |
702 | 702 | ||
703 | // Reset The Current Viewport | 703 | // Reset The Current Viewport |
704 | glViewport(0, 0, Params.WindowSize.Width, Params.WindowSize.Height); | 704 | glViewport(0, 0, Params.WindowSize.Width, Params.WindowSize.Height); |
705 | 705 | ||
706 | UserClipPlanes.reallocate(MaxUserClipPlanes); | 706 | UserClipPlanes.reallocate(MaxUserClipPlanes); |
707 | for (i=0; i<MaxUserClipPlanes; ++i) | 707 | for (i=0; i<MaxUserClipPlanes; ++i) |
708 | UserClipPlanes.push_back(SUserClipPlane()); | 708 | UserClipPlanes.push_back(SUserClipPlane()); |
709 | 709 | ||
710 | for (i=0; i<ETS_COUNT; ++i) | 710 | for (i=0; i<ETS_COUNT; ++i) |
711 | setTransform(static_cast<E_TRANSFORMATION_STATE>(i), core::IdentityMatrix); | 711 | setTransform(static_cast<E_TRANSFORMATION_STATE>(i), core::IdentityMatrix); |
712 | 712 | ||
713 | setAmbientLight(SColorf(0.0f,0.0f,0.0f,0.0f)); | 713 | setAmbientLight(SColorf(0.0f,0.0f,0.0f,0.0f)); |
714 | #ifdef GL_EXT_separate_specular_color | 714 | #ifdef GL_EXT_separate_specular_color |
715 | if (FeatureAvailable[IRR_EXT_separate_specular_color]) | 715 | if (FeatureAvailable[IRR_EXT_separate_specular_color]) |
716 | glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); | 716 | glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); |
717 | #endif | 717 | #endif |
718 | glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); | 718 | glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); |
719 | 719 | ||
720 | Params.HandleSRGB &= ((FeatureAvailable[IRR_ARB_framebuffer_sRGB] || FeatureAvailable[IRR_EXT_framebuffer_sRGB]) && | 720 | Params.HandleSRGB &= ((FeatureAvailable[IRR_ARB_framebuffer_sRGB] || FeatureAvailable[IRR_EXT_framebuffer_sRGB]) && |
721 | FeatureAvailable[IRR_EXT_texture_sRGB]); | 721 | FeatureAvailable[IRR_EXT_texture_sRGB]); |
722 | #if defined(GL_ARB_framebuffer_sRGB) | 722 | #if defined(GL_ARB_framebuffer_sRGB) |
723 | if (Params.HandleSRGB) | 723 | if (Params.HandleSRGB) |
724 | glEnable(GL_FRAMEBUFFER_SRGB); | 724 | glEnable(GL_FRAMEBUFFER_SRGB); |
725 | #elif defined(GL_EXT_framebuffer_sRGB) | 725 | #elif defined(GL_EXT_framebuffer_sRGB) |
726 | if (Params.HandleSRGB) | 726 | if (Params.HandleSRGB) |
727 | glEnable(GL_FRAMEBUFFER_SRGB_EXT); | 727 | glEnable(GL_FRAMEBUFFER_SRGB_EXT); |
728 | #endif | 728 | #endif |
729 | 729 | ||
730 | // This is a fast replacement for NORMALIZE_NORMALS | 730 | // This is a fast replacement for NORMALIZE_NORMALS |
731 | // if ((Version>101) || FeatureAvailable[IRR_EXT_rescale_normal]) | 731 | // if ((Version>101) || FeatureAvailable[IRR_EXT_rescale_normal]) |
732 | // glEnable(GL_RESCALE_NORMAL_EXT); | 732 | // glEnable(GL_RESCALE_NORMAL_EXT); |
733 | 733 | ||
734 | glClearDepth(1.0); | 734 | glClearDepth(1.0); |
735 | glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); | 735 | glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); |
736 | glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); | 736 | glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); |
737 | glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST); | 737 | glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST); |
738 | glDepthFunc(GL_LEQUAL); | 738 | glDepthFunc(GL_LEQUAL); |
739 | glFrontFace(GL_CW); | 739 | glFrontFace(GL_CW); |
740 | // adjust flat coloring scheme to DirectX version | 740 | // adjust flat coloring scheme to DirectX version |
741 | #if defined(GL_ARB_provoking_vertex) || defined(GL_EXT_provoking_vertex) | 741 | #if defined(GL_ARB_provoking_vertex) || defined(GL_EXT_provoking_vertex) |
742 | extGlProvokingVertex(GL_FIRST_VERTEX_CONVENTION_EXT); | 742 | extGlProvokingVertex(GL_FIRST_VERTEX_CONVENTION_EXT); |
743 | #endif | 743 | #endif |
744 | 744 | ||
745 | // create material renderers | 745 | // create material renderers |
746 | createMaterialRenderers(); | 746 | createMaterialRenderers(); |
747 | 747 | ||
748 | // set the renderstates | 748 | // set the renderstates |
749 | setRenderStates3DMode(); | 749 | setRenderStates3DMode(); |
750 | 750 | ||
751 | glAlphaFunc(GL_GREATER, 0.f); | 751 | glAlphaFunc(GL_GREATER, 0.f); |
752 | 752 | ||
753 | // set fog mode | 753 | // set fog mode |
754 | setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog); | 754 | setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog); |
755 | 755 | ||
756 | // create matrix for flipping textures | 756 | // create matrix for flipping textures |
757 | TextureFlipMatrix.buildTextureTransform(0.0f, core::vector2df(0,0), core::vector2df(0,1.0f), core::vector2df(1.0f,-1.0f)); | 757 | TextureFlipMatrix.buildTextureTransform(0.0f, core::vector2df(0,0), core::vector2df(0,1.0f), core::vector2df(1.0f,-1.0f)); |
758 | 758 | ||
759 | // We need to reset once more at the beginning of the first rendering. | 759 | // We need to reset once more at the beginning of the first rendering. |
760 | // This fixes problems with intermediate changes to the material during texture load. | 760 | // This fixes problems with intermediate changes to the material during texture load. |
761 | ResetRenderStates = true; | 761 | ResetRenderStates = true; |
762 | 762 | ||
763 | #ifdef _IRR_COMPILE_WITH_CG_ | 763 | #ifdef _IRR_COMPILE_WITH_CG_ |
764 | CgContext = cgCreateContext(); | 764 | CgContext = cgCreateContext(); |
765 | #endif | 765 | #endif |
766 | 766 | ||
767 | return true; | 767 | return true; |
768 | } | 768 | } |
769 | 769 | ||
770 | 770 | ||
771 | void COpenGLDriver::createMaterialRenderers() | 771 | void COpenGLDriver::createMaterialRenderers() |
772 | { | 772 | { |
773 | // create OpenGL material renderers | 773 | // create OpenGL material renderers |
774 | 774 | ||
775 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_SOLID(this)); | 775 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_SOLID(this)); |
776 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_SOLID_2_LAYER(this)); | 776 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_SOLID_2_LAYER(this)); |
777 | 777 | ||
778 | // add the same renderer for all lightmap types | 778 | // add the same renderer for all lightmap types |
779 | COpenGLMaterialRenderer_LIGHTMAP* lmr = new COpenGLMaterialRenderer_LIGHTMAP(this); | 779 | COpenGLMaterialRenderer_LIGHTMAP* lmr = new COpenGLMaterialRenderer_LIGHTMAP(this); |
780 | addMaterialRenderer(lmr); // for EMT_LIGHTMAP: | 780 | addMaterialRenderer(lmr); // for EMT_LIGHTMAP: |
781 | addMaterialRenderer(lmr); // for EMT_LIGHTMAP_ADD: | 781 | addMaterialRenderer(lmr); // for EMT_LIGHTMAP_ADD: |
782 | addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M2: | 782 | addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M2: |
783 | addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M4: | 783 | addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M4: |
784 | addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING: | 784 | addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING: |
785 | addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M2: | 785 | addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M2: |
786 | addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M4: | 786 | addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M4: |
787 | lmr->drop(); | 787 | lmr->drop(); |
788 | 788 | ||
789 | // add remaining material renderer | 789 | // add remaining material renderer |
790 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_DETAIL_MAP(this)); | 790 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_DETAIL_MAP(this)); |
791 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_SPHERE_MAP(this)); | 791 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_SPHERE_MAP(this)); |
792 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_REFLECTION_2_LAYER(this)); | 792 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_REFLECTION_2_LAYER(this)); |
793 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_TRANSPARENT_ADD_COLOR(this)); | 793 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_TRANSPARENT_ADD_COLOR(this)); |
794 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(this)); | 794 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(this)); |
795 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(this)); | 795 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(this)); |
796 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_TRANSPARENT_VERTEX_ALPHA(this)); | 796 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_TRANSPARENT_VERTEX_ALPHA(this)); |
797 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(this)); | 797 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(this)); |
798 | 798 | ||
799 | // add normal map renderers | 799 | // add normal map renderers |
800 | s32 tmp = 0; | 800 | s32 tmp = 0; |
801 | video::IMaterialRenderer* renderer = 0; | 801 | video::IMaterialRenderer* renderer = 0; |
802 | renderer = new COpenGLNormalMapRenderer(this, tmp, MaterialRenderers[EMT_SOLID].Renderer); | 802 | renderer = new COpenGLNormalMapRenderer(this, tmp, MaterialRenderers[EMT_SOLID].Renderer); |
803 | renderer->drop(); | 803 | renderer->drop(); |
804 | renderer = new COpenGLNormalMapRenderer(this, tmp, MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer); | 804 | renderer = new COpenGLNormalMapRenderer(this, tmp, MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer); |
805 | renderer->drop(); | 805 | renderer->drop(); |
806 | renderer = new COpenGLNormalMapRenderer(this, tmp, MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer); | 806 | renderer = new COpenGLNormalMapRenderer(this, tmp, MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer); |
807 | renderer->drop(); | 807 | renderer->drop(); |
808 | 808 | ||
809 | // add parallax map renderers | 809 | // add parallax map renderers |
810 | renderer = new COpenGLParallaxMapRenderer(this, tmp, MaterialRenderers[EMT_SOLID].Renderer); | 810 | renderer = new COpenGLParallaxMapRenderer(this, tmp, MaterialRenderers[EMT_SOLID].Renderer); |
811 | renderer->drop(); | 811 | renderer->drop(); |
812 | renderer = new COpenGLParallaxMapRenderer(this, tmp, MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer); | 812 | renderer = new COpenGLParallaxMapRenderer(this, tmp, MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer); |
813 | renderer->drop(); | 813 | renderer->drop(); |
814 | renderer = new COpenGLParallaxMapRenderer(this, tmp, MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer); | 814 | renderer = new COpenGLParallaxMapRenderer(this, tmp, MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer); |
815 | renderer->drop(); | 815 | renderer->drop(); |
816 | 816 | ||
817 | // add basic 1 texture blending | 817 | // add basic 1 texture blending |
818 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_ONETEXTURE_BLEND(this)); | 818 | addAndDropMaterialRenderer(new COpenGLMaterialRenderer_ONETEXTURE_BLEND(this)); |
819 | } | 819 | } |
820 | 820 | ||
821 | 821 | ||
822 | //! presents the rendered scene on the screen, returns false if failed | 822 | //! presents the rendered scene on the screen, returns false if failed |
823 | bool COpenGLDriver::endScene() | 823 | bool COpenGLDriver::endScene() |
824 | { | 824 | { |
825 | CNullDriver::endScene(); | 825 | CNullDriver::endScene(); |
826 | 826 | ||
827 | glFlush(); | 827 | glFlush(); |
828 | 828 | ||
829 | #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ | 829 | #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ |
830 | if (DeviceType == EIDT_WIN32) | 830 | if (DeviceType == EIDT_WIN32) |
831 | return SwapBuffers(HDc) == TRUE; | 831 | return SwapBuffers(HDc) == TRUE; |
832 | #endif | 832 | #endif |
833 | 833 | ||
834 | #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ | 834 | #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ |
835 | if (DeviceType == EIDT_X11) | 835 | if (DeviceType == EIDT_X11) |
836 | { | 836 | { |
837 | glXSwapBuffers(X11Display, Drawable); | 837 | glXSwapBuffers(X11Display, Drawable); |
838 | return true; | 838 | return true; |
839 | } | 839 | } |
840 | #endif | 840 | #endif |
841 | 841 | ||
842 | #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ | 842 | #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ |
843 | if (DeviceType == EIDT_OSX) | 843 | if (DeviceType == EIDT_OSX) |
844 | { | 844 | { |
845 | OSXDevice->flush(); | 845 | OSXDevice->flush(); |
846 | return true; | 846 | return true; |
847 | } | 847 | } |
848 | #endif | 848 | #endif |
849 | 849 | ||
850 | #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ | 850 | #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ |
851 | if (DeviceType == EIDT_SDL) | 851 | if (DeviceType == EIDT_SDL) |
852 | { | 852 | { |
853 | SDL_GL_SwapBuffers(); | 853 | SDL_GL_SwapBuffers(); |
854 | return true; | 854 | return true; |
855 | } | 855 | } |
856 | #endif | 856 | #endif |
857 | 857 | ||
858 | // todo: console device present | 858 | // todo: console device present |
859 | 859 | ||
860 | return false; | 860 | return false; |
861 | } | 861 | } |
862 | 862 | ||
863 | 863 | ||
864 | //! clears the zbuffer and color buffer | 864 | //! clears the zbuffer and color buffer |
865 | void COpenGLDriver::clearBuffers(bool backBuffer, bool zBuffer, bool stencilBuffer, SColor color) | 865 | void COpenGLDriver::clearBuffers(bool backBuffer, bool zBuffer, bool stencilBuffer, SColor color) |
866 | { | 866 | { |
867 | GLbitfield mask = 0; | 867 | GLbitfield mask = 0; |
868 | if (backBuffer) | 868 | if (backBuffer) |
869 | { | 869 | { |
870 | const f32 inv = 1.0f / 255.0f; | 870 | const f32 inv = 1.0f / 255.0f; |
871 | glClearColor(color.getRed() * inv, color.getGreen() * inv, | 871 | glClearColor(color.getRed() * inv, color.getGreen() * inv, |
872 | color.getBlue() * inv, color.getAlpha() * inv); | 872 | color.getBlue() * inv, color.getAlpha() * inv); |
873 | 873 | ||
874 | mask |= GL_COLOR_BUFFER_BIT; | 874 | mask |= GL_COLOR_BUFFER_BIT; |
875 | } | 875 | } |
876 | 876 | ||
877 | if (zBuffer) | 877 | if (zBuffer) |
878 | { | 878 | { |
879 | glDepthMask(GL_TRUE); | 879 | glDepthMask(GL_TRUE); |
880 | LastMaterial.ZWriteEnable=true; | 880 | LastMaterial.ZWriteEnable=true; |
881 | mask |= GL_DEPTH_BUFFER_BIT; | 881 | mask |= GL_DEPTH_BUFFER_BIT; |
882 | } | 882 | } |
883 | 883 | ||
884 | if (stencilBuffer) | 884 | if (stencilBuffer) |
885 | mask |= GL_STENCIL_BUFFER_BIT; | 885 | mask |= GL_STENCIL_BUFFER_BIT; |
886 | 886 | ||
887 | if (mask) | 887 | if (mask) |
888 | glClear(mask); | 888 | glClear(mask); |
889 | } | 889 | } |
890 | 890 | ||
891 | 891 | ||
892 | //! init call for rendering start | 892 | //! init call for rendering start |
893 | bool COpenGLDriver::beginScene(bool backBuffer, bool zBuffer, SColor color, | 893 | bool COpenGLDriver::beginScene(bool backBuffer, bool zBuffer, SColor color, |
894 | const SExposedVideoData& videoData, core::rect<s32>* sourceRect) | 894 | const SExposedVideoData& videoData, core::rect<s32>* sourceRect) |
895 | { | 895 | { |
896 | CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); | 896 | CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); |
897 | 897 | ||
898 | switch (DeviceType) | 898 | switch (DeviceType) |
899 | { | 899 | { |
900 | #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ | 900 | #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ |
901 | case EIDT_WIN32: | 901 | case EIDT_WIN32: |
902 | changeRenderContext(videoData, Win32Device); | 902 | changeRenderContext(videoData, Win32Device); |
903 | break; | 903 | break; |
904 | #endif | 904 | #endif |
905 | #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ | 905 | #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ |
906 | case EIDT_X11: | 906 | case EIDT_X11: |
907 | changeRenderContext(videoData, X11Device); | 907 | changeRenderContext(videoData, X11Device); |
908 | break; | 908 | break; |
909 | #endif | 909 | #endif |
910 | default: | 910 | default: |
911 | changeRenderContext(videoData, (void*)0); | 911 | changeRenderContext(videoData, (void*)0); |
912 | break; | 912 | break; |
913 | } | 913 | } |
914 | 914 | ||
915 | #if defined(_IRR_COMPILE_WITH_SDL_DEVICE_) | 915 | #if defined(_IRR_COMPILE_WITH_SDL_DEVICE_) |
916 | if (DeviceType == EIDT_SDL) | 916 | if (DeviceType == EIDT_SDL) |
917 | { | 917 | { |
918 | // todo: SDL sets glFrontFace(GL_CCW) after driver creation, | 918 | // todo: SDL sets glFrontFace(GL_CCW) after driver creation, |
919 | // it would be better if this was fixed elsewhere. | 919 | // it would be better if this was fixed elsewhere. |
920 | glFrontFace(GL_CW); | 920 | glFrontFace(GL_CW); |
921 | } | 921 | } |
922 | #endif | 922 | #endif |
923 | 923 | ||
924 | clearBuffers(backBuffer, zBuffer, false, color); | 924 | clearBuffers(backBuffer, zBuffer, false, color); |
925 | return true; | 925 | return true; |
926 | } | 926 | } |
927 | 927 | ||
928 | 928 | ||
929 | //! Returns the transformation set by setTransform | 929 | //! Returns the transformation set by setTransform |
930 | const core::matrix4& COpenGLDriver::getTransform(E_TRANSFORMATION_STATE state) const | 930 | const core::matrix4& COpenGLDriver::getTransform(E_TRANSFORMATION_STATE state) const |
931 | { | 931 | { |
932 | return Matrices[state]; | 932 | return Matrices[state]; |
933 | } | 933 | } |
934 | 934 | ||
935 | 935 | ||
936 | //! sets transformation | 936 | //! sets transformation |
937 | void COpenGLDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) | 937 | void COpenGLDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) |
938 | { | 938 | { |
939 | Matrices[state] = mat; | 939 | Matrices[state] = mat; |
940 | Transformation3DChanged = true; | 940 | Transformation3DChanged = true; |
941 | 941 | ||
942 | switch (state) | 942 | switch (state) |
943 | { | 943 | { |
944 | case ETS_VIEW: | 944 | case ETS_VIEW: |
945 | case ETS_WORLD: | 945 | case ETS_WORLD: |
946 | { | 946 | { |
947 | // OpenGL only has a model matrix, view and world is not existent. so lets fake these two. | 947 | // OpenGL only has a model matrix, view and world is not existent. so lets fake these two. |
948 | glMatrixMode(GL_MODELVIEW); | 948 | glMatrixMode(GL_MODELVIEW); |
949 | 949 | ||
950 | // first load the viewing transformation for user clip planes | 950 | // first load the viewing transformation for user clip planes |
951 | glLoadMatrixf((Matrices[ETS_VIEW]).pointer()); | 951 | glLoadMatrixf((Matrices[ETS_VIEW]).pointer()); |
952 | 952 | ||
953 | // we have to update the clip planes to the latest view matrix | 953 | // we have to update the clip planes to the latest view matrix |
954 | for (u32 i=0; i<MaxUserClipPlanes; ++i) | 954 | for (u32 i=0; i<MaxUserClipPlanes; ++i) |
955 | if (UserClipPlanes[i].Enabled) | 955 | if (UserClipPlanes[i].Enabled) |
956 | uploadClipPlane(i); | 956 | uploadClipPlane(i); |
957 | 957 | ||
958 | // now the real model-view matrix | 958 | // now the real model-view matrix |
959 | glMultMatrixf(Matrices[ETS_WORLD].pointer()); | 959 | glMultMatrixf(Matrices[ETS_WORLD].pointer()); |
960 | } | 960 | } |
961 | break; | 961 | break; |
962 | case ETS_PROJECTION: | 962 | case ETS_PROJECTION: |
963 | { | 963 | { |
964 | glMatrixMode(GL_PROJECTION); | 964 | glMatrixMode(GL_PROJECTION); |
965 | glLoadMatrixf(mat.pointer()); | 965 | glLoadMatrixf(mat.pointer()); |
966 | } | 966 | } |
967 | break; | 967 | break; |
968 | case ETS_COUNT: | 968 | case ETS_COUNT: |
969 | return; | 969 | return; |
970 | default: | 970 | default: |
971 | { | 971 | { |
972 | const u32 i = state - ETS_TEXTURE_0; | 972 | const u32 i = state - ETS_TEXTURE_0; |
973 | if (i >= MATERIAL_MAX_TEXTURES) | 973 | if (i >= MATERIAL_MAX_TEXTURES) |
974 | break; | 974 | break; |
975 | 975 | ||
976 | const bool isRTT = Material.getTexture(i) && Material.getTexture(i)->isRenderTarget(); | 976 | const bool isRTT = Material.getTexture(i) && Material.getTexture(i)->isRenderTarget(); |
977 | 977 | ||
978 | if (MultiTextureExtension) | 978 | if (MultiTextureExtension) |
979 | extGlActiveTexture(GL_TEXTURE0_ARB + i); | 979 | extGlActiveTexture(GL_TEXTURE0_ARB + i); |
980 | 980 | ||
981 | glMatrixMode(GL_TEXTURE); | 981 | glMatrixMode(GL_TEXTURE); |
982 | if (!isRTT && mat.isIdentity() ) | 982 | if (!isRTT && mat.isIdentity() ) |
983 | glLoadIdentity(); | 983 | glLoadIdentity(); |
984 | else | 984 | else |
985 | { | 985 | { |
986 | GLfloat glmat[16]; | 986 | GLfloat glmat[16]; |
987 | if (isRTT) | 987 | if (isRTT) |
988 | getGLTextureMatrix(glmat, mat * TextureFlipMatrix); | 988 | getGLTextureMatrix(glmat, mat * TextureFlipMatrix); |
989 | else | 989 | else |
990 | getGLTextureMatrix(glmat, mat); | 990 | getGLTextureMatrix(glmat, mat); |
991 | glLoadMatrixf(glmat); | 991 | glLoadMatrixf(glmat); |
992 | } | 992 | } |
993 | break; | 993 | break; |
994 | } | 994 | } |
995 | } | 995 | } |
996 | } | 996 | } |
997 | 997 | ||
998 | 998 | ||
999 | bool COpenGLDriver::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) | 999 | bool COpenGLDriver::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) |
1000 | { | 1000 | { |
1001 | if (!HWBuffer) | 1001 | if (!HWBuffer) |
1002 | return false; | 1002 | return false; |
1003 | 1003 | ||
1004 | if (!FeatureAvailable[IRR_ARB_vertex_buffer_object]) | 1004 | if (!FeatureAvailable[IRR_ARB_vertex_buffer_object]) |
1005 | return false; | 1005 | return false; |
1006 | 1006 | ||
1007 | #if defined(GL_ARB_vertex_buffer_object) | 1007 | #if defined(GL_ARB_vertex_buffer_object) |
1008 | const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer; | 1008 | const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer; |
1009 | const void* vertices=mb->getVertices(); | 1009 | const void* vertices=mb->getVertices(); |
1010 | const u32 vertexCount=mb->getVertexCount(); | 1010 | const u32 vertexCount=mb->getVertexCount(); |
1011 | const E_VERTEX_TYPE vType=mb->getVertexType(); | 1011 | const E_VERTEX_TYPE vType=mb->getVertexType(); |
1012 | const u32 vertexSize = getVertexPitchFromType(vType); | 1012 | const u32 vertexSize = getVertexPitchFromType(vType); |
1013 | 1013 | ||
1014 | const c8* vbuf = static_cast<const c8*>(vertices); | 1014 | const c8* vbuf = static_cast<const c8*>(vertices); |
1015 | core::array<c8> buffer; | 1015 | core::array<c8> buffer; |
1016 | if (!FeatureAvailable[IRR_ARB_vertex_array_bgra] && !FeatureAvailable[IRR_EXT_vertex_array_bgra]) | 1016 | if (!FeatureAvailable[IRR_ARB_vertex_array_bgra] && !FeatureAvailable[IRR_EXT_vertex_array_bgra]) |
1017 | { | 1017 | { |
1018 | //buffer vertex data, and convert colors... | 1018 | //buffer vertex data, and convert colors... |
1019 | buffer.set_used(vertexSize * vertexCount); | 1019 | buffer.set_used(vertexSize * vertexCount); |
1020 | memcpy(buffer.pointer(), vertices, vertexSize * vertexCount); | 1020 | memcpy(buffer.pointer(), vertices, vertexSize * vertexCount); |
1021 | vbuf = buffer.const_pointer(); | 1021 | vbuf = buffer.const_pointer(); |
1022 | 1022 | ||
1023 | // in order to convert the colors into opengl format (RGBA) | 1023 | // in order to convert the colors into opengl format (RGBA) |
1024 | switch (vType) | 1024 | switch (vType) |
1025 | { | 1025 | { |
1026 | case EVT_STANDARD: | 1026 | case EVT_STANDARD: |
1027 | { | 1027 | { |
1028 | S3DVertex* pb = reinterpret_cast<S3DVertex*>(buffer.pointer()); | 1028 | S3DVertex* pb = reinterpret_cast<S3DVertex*>(buffer.pointer()); |
1029 | const S3DVertex* po = static_cast<const S3DVertex*>(vertices); | 1029 | const S3DVertex* po = static_cast<const S3DVertex*>(vertices); |
1030 | for (u32 i=0; i<vertexCount; i++) | 1030 | for (u32 i=0; i<vertexCount; i++) |
1031 | { | 1031 | { |
1032 | po[i].Color.toOpenGLColor((u8*)&(pb[i].Color)); | 1032 | po[i].Color.toOpenGLColor((u8*)&(pb[i].Color)); |
1033 | } | 1033 | } |
1034 | } | 1034 | } |
1035 | break; | 1035 | break; |
1036 | case EVT_2TCOORDS: | 1036 | case EVT_2TCOORDS: |
1037 | { | 1037 | { |
1038 | S3DVertex2TCoords* pb = reinterpret_cast<S3DVertex2TCoords*>(buffer.pointer()); | 1038 | S3DVertex2TCoords* pb = reinterpret_cast<S3DVertex2TCoords*>(buffer.pointer()); |
1039 | const S3DVertex2TCoords* po = static_cast<const S3DVertex2TCoords*>(vertices); | 1039 | const S3DVertex2TCoords* po = static_cast<const S3DVertex2TCoords*>(vertices); |
1040 | for (u32 i=0; i<vertexCount; i++) | 1040 | for (u32 i=0; i<vertexCount; i++) |
1041 | { | 1041 | { |
1042 | po[i].Color.toOpenGLColor((u8*)&(pb[i].Color)); | 1042 | po[i].Color.toOpenGLColor((u8*)&(pb[i].Color)); |
1043 | } | 1043 | } |
1044 | } | 1044 | } |
1045 | break; | 1045 | break; |
1046 | case EVT_TANGENTS: | 1046 | case EVT_TANGENTS: |
1047 | { | 1047 | { |
1048 | S3DVertexTangents* pb = reinterpret_cast<S3DVertexTangents*>(buffer.pointer()); | 1048 | S3DVertexTangents* pb = reinterpret_cast<S3DVertexTangents*>(buffer.pointer()); |
1049 | const S3DVertexTangents* po = static_cast<const S3DVertexTangents*>(vertices); | 1049 | const S3DVertexTangents* po = static_cast<const S3DVertexTangents*>(vertices); |
1050 | for (u32 i=0; i<vertexCount; i++) | 1050 | for (u32 i=0; i<vertexCount; i++) |
1051 | { | 1051 | { |
1052 | po[i].Color.toOpenGLColor((u8*)&(pb[i].Color)); | 1052 | po[i].Color.toOpenGLColor((u8*)&(pb[i].Color)); |
1053 | } | 1053 | } |
1054 | } | 1054 | } |
1055 | break; | 1055 | break; |
1056 | default: | 1056 | default: |
1057 | { | 1057 | { |
1058 | return false; | 1058 | return false; |
1059 | } | 1059 | } |
1060 | } | 1060 | } |
1061 | } | 1061 | } |
1062 | 1062 | ||
1063 | //get or create buffer | 1063 | //get or create buffer |
1064 | bool newBuffer=false; | 1064 | bool newBuffer=false; |
1065 | if (!HWBuffer->vbo_verticesID) | 1065 | if (!HWBuffer->vbo_verticesID) |
1066 | { | 1066 | { |
1067 | extGlGenBuffers(1, &HWBuffer->vbo_verticesID); | 1067 | extGlGenBuffers(1, &HWBuffer->vbo_verticesID); |
1068 | if (!HWBuffer->vbo_verticesID) | 1068 | if (!HWBuffer->vbo_verticesID) |
1069 | return false; | 1069 | return false; |
1070 | newBuffer=true; | 1070 | newBuffer=true; |
1071 | } | 1071 | } |
1072 | else if (HWBuffer->vbo_verticesSize < vertexCount*vertexSize) | 1072 | else if (HWBuffer->vbo_verticesSize < vertexCount*vertexSize) |
1073 | { | 1073 | { |
1074 | newBuffer=true; | 1074 | newBuffer=true; |
1075 | } | 1075 | } |
1076 | 1076 | ||
1077 | extGlBindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID); | 1077 | extGlBindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID); |
1078 | 1078 | ||
1079 | //copy data to graphics card | 1079 | //copy data to graphics card |
1080 | glGetError(); // clear error storage | 1080 | glGetError(); // clear error storage |
1081 | if (!newBuffer) | 1081 | if (!newBuffer) |
1082 | extGlBufferSubData(GL_ARRAY_BUFFER, 0, vertexCount * vertexSize, vbuf); | 1082 | extGlBufferSubData(GL_ARRAY_BUFFER, 0, vertexCount * vertexSize, vbuf); |
1083 | else | 1083 | else |
1084 | { | 1084 | { |
1085 | HWBuffer->vbo_verticesSize = vertexCount*vertexSize; | 1085 | HWBuffer->vbo_verticesSize = vertexCount*vertexSize; |
1086 | 1086 | ||
1087 | if (HWBuffer->Mapped_Vertex==scene::EHM_STATIC) | 1087 | if (HWBuffer->Mapped_Vertex==scene::EHM_STATIC) |
1088 | extGlBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, vbuf, GL_STATIC_DRAW); | 1088 | extGlBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, vbuf, GL_STATIC_DRAW); |
1089 | else if (HWBuffer->Mapped_Vertex==scene::EHM_DYNAMIC) | 1089 | else if (HWBuffer->Mapped_Vertex==scene::EHM_DYNAMIC) |
1090 | extGlBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, vbuf, GL_DYNAMIC_DRAW); | 1090 | extGlBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, vbuf, GL_DYNAMIC_DRAW); |
1091 | else //scene::EHM_STREAM | 1091 | else //scene::EHM_STREAM |
1092 | extGlBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, vbuf, GL_STREAM_DRAW); | 1092 | extGlBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, vbuf, GL_STREAM_DRAW); |
1093 | } | 1093 | } |
1094 | 1094 | ||
1095 | extGlBindBuffer(GL_ARRAY_BUFFER, 0); | 1095 | extGlBindBuffer(GL_ARRAY_BUFFER, 0); |
1096 | 1096 | ||
1097 | return (glGetError() == GL_NO_ERROR); | 1097 | return (glGetError() == GL_NO_ERROR); |
1098 | #else | 1098 | #else |
1099 | return false; | 1099 | return false; |
1100 | #endif | 1100 | #endif |
1101 | } | 1101 | } |
1102 | 1102 | ||
1103 | 1103 | ||
1104 | bool COpenGLDriver::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) | 1104 | bool COpenGLDriver::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) |
1105 | { | 1105 | { |
1106 | if (!HWBuffer) | 1106 | if (!HWBuffer) |
1107 | return false; | 1107 | return false; |
1108 | 1108 | ||
1109 | if (!FeatureAvailable[IRR_ARB_vertex_buffer_object]) | 1109 | if (!FeatureAvailable[IRR_ARB_vertex_buffer_object]) |
1110 | return false; | 1110 | return false; |
1111 | 1111 | ||
1112 | #if defined(GL_ARB_vertex_buffer_object) | 1112 | #if defined(GL_ARB_vertex_buffer_object) |
1113 | const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer; | 1113 | const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer; |
1114 | 1114 | ||
1115 | const void* indices=mb->getIndices(); | 1115 | const void* indices=mb->getIndices(); |
1116 | u32 indexCount= mb->getIndexCount(); | 1116 | u32 indexCount= mb->getIndexCount(); |
1117 | 1117 | ||
1118 | GLenum indexSize; | 1118 | GLenum indexSize; |
1119 | switch (mb->getIndexType()) | 1119 | switch (mb->getIndexType()) |
1120 | { | 1120 | { |
1121 | case EIT_16BIT: | 1121 | case EIT_16BIT: |
1122 | { | 1122 | { |
1123 | indexSize=sizeof(u16); | 1123 | indexSize=sizeof(u16); |
1124 | break; | 1124 | break; |
1125 | } | 1125 | } |
1126 | case EIT_32BIT: | 1126 | case EIT_32BIT: |
1127 | { | 1127 | { |
1128 | indexSize=sizeof(u32); | 1128 | indexSize=sizeof(u32); |
1129 | break; | 1129 | break; |
1130 | } | 1130 | } |
1131 | default: | 1131 | default: |
1132 | { | 1132 | { |
1133 | return false; | 1133 | return false; |
1134 | } | 1134 | } |
1135 | } | 1135 | } |
1136 | 1136 | ||
1137 | 1137 | ||
1138 | //get or create buffer | 1138 | //get or create buffer |
1139 | bool newBuffer=false; | 1139 | bool newBuffer=false; |
1140 | if (!HWBuffer->vbo_indicesID) | 1140 | if (!HWBuffer->vbo_indicesID) |
1141 | { | 1141 | { |
1142 | extGlGenBuffers(1, &HWBuffer->vbo_indicesID); | 1142 | extGlGenBuffers(1, &HWBuffer->vbo_indicesID); |
1143 | if (!HWBuffer->vbo_indicesID) | 1143 | if (!HWBuffer->vbo_indicesID) |
1144 | return false; | 1144 | return false; |
1145 | newBuffer=true; | 1145 | newBuffer=true; |
1146 | } | 1146 | } |
1147 | else if (HWBuffer->vbo_indicesSize < indexCount*indexSize) | 1147 | else if (HWBuffer->vbo_indicesSize < indexCount*indexSize) |
1148 | { | 1148 | { |
1149 | newBuffer=true; | 1149 | newBuffer=true; |
1150 | } | 1150 | } |
1151 | 1151 | ||
1152 | extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID); | 1152 | extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID); |
1153 | 1153 | ||
1154 | //copy data to graphics card | 1154 | //copy data to graphics card |
1155 | glGetError(); // clear error storage | 1155 | glGetError(); // clear error storage |
1156 | if (!newBuffer) | 1156 | if (!newBuffer) |
1157 | extGlBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexCount * indexSize, indices); | 1157 | extGlBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexCount * indexSize, indices); |
1158 | else | 1158 | else |
1159 | { | 1159 | { |
1160 | HWBuffer->vbo_indicesSize = indexCount*indexSize; | 1160 | HWBuffer->vbo_indicesSize = indexCount*indexSize; |
1161 | 1161 | ||
1162 | if (HWBuffer->Mapped_Index==scene::EHM_STATIC) | 1162 | if (HWBuffer->Mapped_Index==scene::EHM_STATIC) |
1163 | extGlBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_STATIC_DRAW); | 1163 | extGlBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_STATIC_DRAW); |
1164 | else if (HWBuffer->Mapped_Index==scene::EHM_DYNAMIC) | 1164 | else if (HWBuffer->Mapped_Index==scene::EHM_DYNAMIC) |
1165 | extGlBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_DYNAMIC_DRAW); | 1165 | extGlBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_DYNAMIC_DRAW); |
1166 | else //scene::EHM_STREAM | 1166 | else //scene::EHM_STREAM |
1167 | extGlBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_STREAM_DRAW); | 1167 | extGlBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_STREAM_DRAW); |
1168 | } | 1168 | } |
1169 | 1169 | ||
1170 | extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); | 1170 | extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); |
1171 | 1171 | ||
1172 | return (glGetError() == GL_NO_ERROR); | 1172 | return (glGetError() == GL_NO_ERROR); |
1173 | #else | 1173 | #else |
1174 | return false; | 1174 | return false; |
1175 | #endif | 1175 | #endif |
1176 | } | 1176 | } |
1177 | 1177 | ||
1178 | 1178 | ||
1179 | //! updates hardware buffer if needed | 1179 | //! updates hardware buffer if needed |
1180 | bool COpenGLDriver::updateHardwareBuffer(SHWBufferLink *HWBuffer) | 1180 | bool COpenGLDriver::updateHardwareBuffer(SHWBufferLink *HWBuffer) |
1181 | { | 1181 | { |
1182 | if (!HWBuffer) | 1182 | if (!HWBuffer) |
1183 | return false; | 1183 | return false; |
1184 | 1184 | ||
1185 | if (HWBuffer->Mapped_Vertex!=scene::EHM_NEVER) | 1185 | if (HWBuffer->Mapped_Vertex!=scene::EHM_NEVER) |
1186 | { | 1186 | { |
1187 | if (HWBuffer->ChangedID_Vertex != HWBuffer->MeshBuffer->getChangedID_Vertex() | 1187 | if (HWBuffer->ChangedID_Vertex != HWBuffer->MeshBuffer->getChangedID_Vertex() |
1188 | || !((SHWBufferLink_opengl*)HWBuffer)->vbo_verticesID) | 1188 | || !((SHWBufferLink_opengl*)HWBuffer)->vbo_verticesID) |
1189 | { | 1189 | { |
1190 | 1190 | ||
1191 | HWBuffer->ChangedID_Vertex = HWBuffer->MeshBuffer->getChangedID_Vertex(); | 1191 | HWBuffer->ChangedID_Vertex = HWBuffer->MeshBuffer->getChangedID_Vertex(); |
1192 | 1192 | ||
1193 | if (!updateVertexHardwareBuffer((SHWBufferLink_opengl*)HWBuffer)) | 1193 | if (!updateVertexHardwareBuffer((SHWBufferLink_opengl*)HWBuffer)) |
1194 | return false; | 1194 | return false; |
1195 | } | 1195 | } |
1196 | } | 1196 | } |
1197 | 1197 | ||
1198 | if (HWBuffer->Mapped_Index!=scene::EHM_NEVER) | 1198 | if (HWBuffer->Mapped_Index!=scene::EHM_NEVER) |
1199 | { | 1199 | { |
1200 | if (HWBuffer->ChangedID_Index != HWBuffer->MeshBuffer->getChangedID_Index() | 1200 | if (HWBuffer->ChangedID_Index != HWBuffer->MeshBuffer->getChangedID_Index() |
1201 | || !((SHWBufferLink_opengl*)HWBuffer)->vbo_indicesID) | 1201 | || !((SHWBufferLink_opengl*)HWBuffer)->vbo_indicesID) |
1202 | { | 1202 | { |
1203 | 1203 | ||
1204 | HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index(); | 1204 | HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index(); |
1205 | 1205 | ||
1206 | if (!updateIndexHardwareBuffer((SHWBufferLink_opengl*)HWBuffer)) | 1206 | if (!updateIndexHardwareBuffer((SHWBufferLink_opengl*)HWBuffer)) |
1207 | return false; | 1207 | return false; |
1208 | } | 1208 | } |
1209 | } | 1209 | } |
1210 | 1210 | ||
1211 | return true; | 1211 | return true; |
1212 | } | 1212 | } |
1213 | 1213 | ||
1214 | 1214 | ||
1215 | //! Create hardware buffer from meshbuffer | 1215 | //! Create hardware buffer from meshbuffer |
1216 | COpenGLDriver::SHWBufferLink *COpenGLDriver::createHardwareBuffer(const scene::IMeshBuffer* mb) | 1216 | COpenGLDriver::SHWBufferLink *COpenGLDriver::createHardwareBuffer(const scene::IMeshBuffer* mb) |
1217 | { | 1217 | { |
1218 | #if defined(GL_ARB_vertex_buffer_object) | 1218 | #if defined(GL_ARB_vertex_buffer_object) |
1219 | if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER)) | 1219 | if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER)) |
1220 | return 0; | 1220 | return 0; |
1221 | 1221 | ||
1222 | SHWBufferLink_opengl *HWBuffer=new SHWBufferLink_opengl(mb); | 1222 | SHWBufferLink_opengl *HWBuffer=new SHWBufferLink_opengl(mb); |
1223 | 1223 | ||
1224 | //add to map | 1224 | //add to map |
1225 | HWBufferMap.insert(HWBuffer->MeshBuffer, HWBuffer); | 1225 | HWBufferMap.insert(HWBuffer->MeshBuffer, HWBuffer); |
1226 | 1226 | ||
1227 | HWBuffer->ChangedID_Vertex=HWBuffer->MeshBuffer->getChangedID_Vertex(); | 1227 | HWBuffer->ChangedID_Vertex=HWBuffer->MeshBuffer->getChangedID_Vertex(); |
1228 | HWBuffer->ChangedID_Index=HWBuffer->MeshBuffer->getChangedID_Index(); | 1228 | HWBuffer->ChangedID_Index=HWBuffer->MeshBuffer->getChangedID_Index(); |
1229 | HWBuffer->Mapped_Vertex=mb->getHardwareMappingHint_Vertex(); | 1229 | HWBuffer->Mapped_Vertex=mb->getHardwareMappingHint_Vertex(); |
1230 | HWBuffer->Mapped_Index=mb->getHardwareMappingHint_Index(); | 1230 | HWBuffer->Mapped_Index=mb->getHardwareMappingHint_Index(); |
1231 | HWBuffer->LastUsed=0; | 1231 | HWBuffer->LastUsed=0; |
1232 | HWBuffer->vbo_verticesID=0; | 1232 | HWBuffer->vbo_verticesID=0; |
1233 | HWBuffer->vbo_indicesID=0; | 1233 | HWBuffer->vbo_indicesID=0; |
1234 | HWBuffer->vbo_verticesSize=0; | 1234 | HWBuffer->vbo_verticesSize=0; |
1235 | HWBuffer->vbo_indicesSize=0; | 1235 | HWBuffer->vbo_indicesSize=0; |
1236 | 1236 | ||
1237 | if (!updateHardwareBuffer(HWBuffer)) | 1237 | if (!updateHardwareBuffer(HWBuffer)) |
1238 | { | 1238 | { |
1239 | deleteHardwareBuffer(HWBuffer); | 1239 | deleteHardwareBuffer(HWBuffer); |
1240 | return 0; | 1240 | return 0; |
1241 | } | 1241 | } |
1242 | 1242 | ||
1243 | return HWBuffer; | 1243 | return HWBuffer; |
1244 | #else | 1244 | #else |
1245 | return 0; | 1245 | return 0; |
1246 | #endif | 1246 | #endif |
1247 | } | 1247 | } |
1248 | 1248 | ||
1249 | 1249 | ||
1250 | void COpenGLDriver::deleteHardwareBuffer(SHWBufferLink *_HWBuffer) | 1250 | void COpenGLDriver::deleteHardwareBuffer(SHWBufferLink *_HWBuffer) |
1251 | { | 1251 | { |
1252 | if (!_HWBuffer) | 1252 | if (!_HWBuffer) |
1253 | return; | 1253 | return; |
1254 | 1254 | ||
1255 | #if defined(GL_ARB_vertex_buffer_object) | 1255 | #if defined(GL_ARB_vertex_buffer_object) |
1256 | SHWBufferLink_opengl *HWBuffer=(SHWBufferLink_opengl*)_HWBuffer; | 1256 | SHWBufferLink_opengl *HWBuffer=(SHWBufferLink_opengl*)_HWBuffer; |
1257 | if (HWBuffer->vbo_verticesID) | 1257 | if (HWBuffer->vbo_verticesID) |
1258 | { | 1258 | { |
1259 | extGlDeleteBuffers(1, &HWBuffer->vbo_verticesID); | 1259 | extGlDeleteBuffers(1, &HWBuffer->vbo_verticesID); |
1260 | HWBuffer->vbo_verticesID=0; | 1260 | HWBuffer->vbo_verticesID=0; |
1261 | } | 1261 | } |
1262 | if (HWBuffer->vbo_indicesID) | 1262 | if (HWBuffer->vbo_indicesID) |
1263 | { | 1263 | { |
1264 | extGlDeleteBuffers(1, &HWBuffer->vbo_indicesID); | 1264 | extGlDeleteBuffers(1, &HWBuffer->vbo_indicesID); |
1265 | HWBuffer->vbo_indicesID=0; | 1265 | HWBuffer->vbo_indicesID=0; |
1266 | } | 1266 | } |
1267 | #endif | 1267 | #endif |
1268 | 1268 | ||
1269 | CNullDriver::deleteHardwareBuffer(_HWBuffer); | 1269 | CNullDriver::deleteHardwareBuffer(_HWBuffer); |
1270 | } | 1270 | } |
1271 | 1271 | ||
1272 | 1272 | ||
1273 | //! Draw hardware buffer | 1273 | //! Draw hardware buffer |
1274 | void COpenGLDriver::drawHardwareBuffer(SHWBufferLink *_HWBuffer) | 1274 | void COpenGLDriver::drawHardwareBuffer(SHWBufferLink *_HWBuffer) |
1275 | { | 1275 | { |
1276 | if (!_HWBuffer) | 1276 | if (!_HWBuffer) |
1277 | return; | 1277 | return; |
1278 | 1278 | ||
1279 | updateHardwareBuffer(_HWBuffer); //check if update is needed | 1279 | updateHardwareBuffer(_HWBuffer); //check if update is needed |
1280 | _HWBuffer->LastUsed=0; //reset count | 1280 | _HWBuffer->LastUsed=0; //reset count |
1281 | 1281 | ||
1282 | #if defined(GL_ARB_vertex_buffer_object) | 1282 | #if defined(GL_ARB_vertex_buffer_object) |
1283 | SHWBufferLink_opengl *HWBuffer=(SHWBufferLink_opengl*)_HWBuffer; | 1283 | SHWBufferLink_opengl *HWBuffer=(SHWBufferLink_opengl*)_HWBuffer; |
1284 | 1284 | ||
1285 | const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer; | 1285 | const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer; |
1286 | const void *vertices=mb->getVertices(); | 1286 | const void *vertices=mb->getVertices(); |
1287 | const void *indexList=mb->getIndices(); | 1287 | const void *indexList=mb->getIndices(); |
1288 | 1288 | ||
1289 | if (HWBuffer->Mapped_Vertex!=scene::EHM_NEVER) | 1289 | if (HWBuffer->Mapped_Vertex!=scene::EHM_NEVER) |
1290 | { | 1290 | { |
1291 | extGlBindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID); | 1291 | extGlBindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID); |
1292 | vertices=0; | 1292 | vertices=0; |
1293 | } | 1293 | } |
1294 | 1294 | ||
1295 | if (HWBuffer->Mapped_Index!=scene::EHM_NEVER) | 1295 | if (HWBuffer->Mapped_Index!=scene::EHM_NEVER) |
1296 | { | 1296 | { |
1297 | extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID); | 1297 | extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID); |
1298 | indexList=0; | 1298 | indexList=0; |
1299 | } | 1299 | } |
1300 | 1300 | ||
1301 | drawVertexPrimitiveList(vertices, mb->getVertexCount(), indexList, mb->getIndexCount()/3, mb->getVertexType(), scene::EPT_TRIANGLES, mb->getIndexType()); | 1301 | drawVertexPrimitiveList(vertices, mb->getVertexCount(), indexList, mb->getIndexCount()/3, mb->getVertexType(), scene::EPT_TRIANGLES, mb->getIndexType()); |
1302 | 1302 | ||
1303 | if (HWBuffer->Mapped_Vertex!=scene::EHM_NEVER) | 1303 | if (HWBuffer->Mapped_Vertex!=scene::EHM_NEVER) |
1304 | extGlBindBuffer(GL_ARRAY_BUFFER, 0); | 1304 | extGlBindBuffer(GL_ARRAY_BUFFER, 0); |
1305 | if (HWBuffer->Mapped_Index!=scene::EHM_NEVER) | 1305 | if (HWBuffer->Mapped_Index!=scene::EHM_NEVER) |
1306 | extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); | 1306 | extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); |
1307 | #endif | 1307 | #endif |
1308 | } | 1308 | } |
1309 | 1309 | ||
1310 | 1310 | ||
1311 | //! Create occlusion query. | 1311 | //! Create occlusion query. |
1312 | /** Use node for identification and mesh for occlusion test. */ | 1312 | /** Use node for identification and mesh for occlusion test. */ |
1313 | void COpenGLDriver::addOcclusionQuery(scene::ISceneNode* node, | 1313 | void COpenGLDriver::addOcclusionQuery(scene::ISceneNode* node, |
1314 | const scene::IMesh* mesh) | 1314 | const scene::IMesh* mesh) |
1315 | { | 1315 | { |
1316 | if (!queryFeature(EVDF_OCCLUSION_QUERY)) | 1316 | if (!queryFeature(EVDF_OCCLUSION_QUERY)) |
1317 | return; | 1317 | return; |
1318 | 1318 | ||
1319 | CNullDriver::addOcclusionQuery(node, mesh); | 1319 | CNullDriver::addOcclusionQuery(node, mesh); |
1320 | const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); | 1320 | const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); |
1321 | if ((index != -1) && (OcclusionQueries[index].UID == 0)) | 1321 | if ((index != -1) && (OcclusionQueries[index].UID == 0)) |
1322 | extGlGenQueries(1, reinterpret_cast<GLuint*>(&OcclusionQueries[index].UID)); | 1322 | extGlGenQueries(1, reinterpret_cast<GLuint*>(&OcclusionQueries[index].UID)); |
1323 | } | 1323 | } |
1324 | 1324 | ||
1325 | 1325 | ||
1326 | //! Remove occlusion query. | 1326 | //! Remove occlusion query. |
1327 | void COpenGLDriver::removeOcclusionQuery(scene::ISceneNode* node) | 1327 | void COpenGLDriver::removeOcclusionQuery(scene::ISceneNode* node) |
1328 | { | 1328 | { |
1329 | const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); | 1329 | const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); |
1330 | if (index != -1) | 1330 | if (index != -1) |
1331 | { | 1331 | { |
1332 | if (OcclusionQueries[index].UID != 0) | 1332 | if (OcclusionQueries[index].UID != 0) |
1333 | extGlDeleteQueries(1, reinterpret_cast<GLuint*>(&OcclusionQueries[index].UID)); | 1333 | extGlDeleteQueries(1, reinterpret_cast<GLuint*>(&OcclusionQueries[index].UID)); |
1334 | CNullDriver::removeOcclusionQuery(node); | 1334 | CNullDriver::removeOcclusionQuery(node); |
1335 | } | 1335 | } |
1336 | } | 1336 | } |
1337 | 1337 | ||
1338 | 1338 | ||
1339 | //! Run occlusion query. Draws mesh stored in query. | 1339 | //! Run occlusion query. Draws mesh stored in query. |
1340 | /** If the mesh shall not be rendered visible, use | 1340 | /** If the mesh shall not be rendered visible, use |
1341 | overrideMaterial to disable the color and depth buffer. */ | 1341 | overrideMaterial to disable the color and depth buffer. */ |
1342 | void COpenGLDriver::runOcclusionQuery(scene::ISceneNode* node, bool visible) | 1342 | void COpenGLDriver::runOcclusionQuery(scene::ISceneNode* node, bool visible) |
1343 | { | 1343 | { |
1344 | if (!node) | 1344 | if (!node) |
1345 | return; | 1345 | return; |
1346 | 1346 | ||
1347 | const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); | 1347 | const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); |
1348 | if (index != -1) | 1348 | if (index != -1) |
1349 | { | 1349 | { |
1350 | if (OcclusionQueries[index].UID) | 1350 | if (OcclusionQueries[index].UID) |
1351 | extGlBeginQuery( | 1351 | extGlBeginQuery( |
1352 | #ifdef GL_ARB_occlusion_query | 1352 | #ifdef GL_ARB_occlusion_query |
1353 | GL_SAMPLES_PASSED_ARB, | 1353 | GL_SAMPLES_PASSED_ARB, |
1354 | #else | 1354 | #else |
1355 | 0, | 1355 | 0, |
1356 | #endif | 1356 | #endif |
1357 | OcclusionQueries[index].UID); | 1357 | OcclusionQueries[index].UID); |
1358 | CNullDriver::runOcclusionQuery(node,visible); | 1358 | CNullDriver::runOcclusionQuery(node,visible); |
1359 | if (OcclusionQueries[index].UID) | 1359 | if (OcclusionQueries[index].UID) |
1360 | extGlEndQuery( | 1360 | extGlEndQuery( |
1361 | #ifdef GL_ARB_occlusion_query | 1361 | #ifdef GL_ARB_occlusion_query |
1362 | GL_SAMPLES_PASSED_ARB); | 1362 | GL_SAMPLES_PASSED_ARB); |
1363 | #else | 1363 | #else |
1364 | 0); | 1364 | 0); |
1365 | #endif | 1365 | #endif |
1366 | testGLError(); | 1366 | testGLError(); |
1367 | } | 1367 | } |
1368 | } | 1368 | } |
1369 | 1369 | ||
1370 | 1370 | ||
1371 | //! Update occlusion query. Retrieves results from GPU. | 1371 | //! Update occlusion query. Retrieves results from GPU. |
1372 | /** If the query shall not block, set the flag to false. | 1372 | /** If the query shall not block, set the flag to false. |
1373 | Update might not occur in this case, though */ | 1373 | Update might not occur in this case, though */ |
1374 | void COpenGLDriver::updateOcclusionQuery(scene::ISceneNode* node, bool block) | 1374 | void COpenGLDriver::updateOcclusionQuery(scene::ISceneNode* node, bool block) |
1375 | { | 1375 | { |
1376 | const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); | 1376 | const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); |
1377 | if (index != -1) | 1377 | if (index != -1) |
1378 | { | 1378 | { |
1379 | // not yet started | 1379 | // not yet started |
1380 | if (OcclusionQueries[index].Run==u32(~0)) | 1380 | if (OcclusionQueries[index].Run==u32(~0)) |
1381 | return; | 1381 | return; |
1382 | GLint available = block?GL_TRUE:GL_FALSE; | 1382 | GLint available = block?GL_TRUE:GL_FALSE; |
1383 | if (!block) | 1383 | if (!block) |
1384 | extGlGetQueryObjectiv(OcclusionQueries[index].UID, | 1384 | extGlGetQueryObjectiv(OcclusionQueries[index].UID, |
1385 | #ifdef GL_ARB_occlusion_query | 1385 | #ifdef GL_ARB_occlusion_query |
1386 | GL_QUERY_RESULT_AVAILABLE_ARB, | 1386 | GL_QUERY_RESULT_AVAILABLE_ARB, |
1387 | #elif defined(GL_NV_occlusion_query) | 1387 | #elif defined(GL_NV_occlusion_query) |
1388 | GL_PIXEL_COUNT_AVAILABLE_NV, | 1388 | GL_PIXEL_COUNT_AVAILABLE_NV, |
1389 | #else | 1389 | #else |
1390 | 0, | 1390 | 0, |
1391 | #endif | 1391 | #endif |
1392 | &available); | 1392 | &available); |
1393 | testGLError(); | 1393 | testGLError(); |
1394 | if (available==GL_TRUE) | 1394 | if (available==GL_TRUE) |
1395 | { | 1395 | { |
1396 | extGlGetQueryObjectiv(OcclusionQueries[index].UID, | 1396 | extGlGetQueryObjectiv(OcclusionQueries[index].UID, |
1397 | #ifdef GL_ARB_occlusion_query | 1397 | #ifdef GL_ARB_occlusion_query |
1398 | GL_QUERY_RESULT_ARB, | 1398 | GL_QUERY_RESULT_ARB, |
1399 | #elif defined(GL_NV_occlusion_query) | 1399 | #elif defined(GL_NV_occlusion_query) |
1400 | GL_PIXEL_COUNT_NV, | 1400 | GL_PIXEL_COUNT_NV, |
1401 | #else | 1401 | #else |
1402 | 0, | 1402 | 0, |
1403 | #endif | 1403 | #endif |
1404 | &available); | 1404 | &available); |
1405 | if (queryFeature(EVDF_OCCLUSION_QUERY)) | 1405 | if (queryFeature(EVDF_OCCLUSION_QUERY)) |
1406 | OcclusionQueries[index].Result = available; | 1406 | OcclusionQueries[index].Result = available; |
1407 | } | 1407 | } |
1408 | testGLError(); | 1408 | testGLError(); |
1409 | } | 1409 | } |
1410 | } | 1410 | } |
1411 | 1411 | ||
1412 | 1412 | ||
1413 | //! Return query result. | 1413 | //! Return query result. |
1414 | /** Return value is the number of visible pixels/fragments. | 1414 | /** Return value is the number of visible pixels/fragments. |
1415 | The value is a safe approximation, i.e. can be larger than the | 1415 | The value is a safe approximation, i.e. can be larger than the |
1416 | actual value of pixels. */ | 1416 | actual value of pixels. */ |
1417 | u32 COpenGLDriver::getOcclusionQueryResult(scene::ISceneNode* node) const | 1417 | u32 COpenGLDriver::getOcclusionQueryResult(scene::ISceneNode* node) const |
1418 | { | 1418 | { |
1419 | const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); | 1419 | const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); |
1420 | if (index != -1) | 1420 | if (index != -1) |
1421 | return OcclusionQueries[index].Result; | 1421 | return OcclusionQueries[index].Result; |
1422 | else | 1422 | else |
1423 | return ~0; | 1423 | return ~0; |
1424 | } | 1424 | } |
1425 | 1425 | ||
1426 | 1426 | ||
1427 | // small helper function to create vertex buffer object adress offsets | 1427 | // small helper function to create vertex buffer object adress offsets |
1428 | static inline u8* buffer_offset(const long offset) | 1428 | static inline u8* buffer_offset(const long offset) |
1429 | { | 1429 | { |
1430 | return ((u8*)0 + offset); | 1430 | return ((u8*)0 + offset); |
1431 | } | 1431 | } |
1432 | 1432 | ||
1433 | 1433 | ||
1434 | //! draws a vertex primitive list | 1434 | //! draws a vertex primitive list |
1435 | void COpenGLDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, | 1435 | void COpenGLDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, |
1436 | const void* indexList, u32 primitiveCount, | 1436 | const void* indexList, u32 primitiveCount, |
1437 | E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) | 1437 | E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) |
1438 | { | 1438 | { |
1439 | if (!primitiveCount || !vertexCount) | 1439 | if (!primitiveCount || !vertexCount) |
1440 | return; | 1440 | return; |
1441 | 1441 | ||
1442 | if (!checkPrimitiveCount(primitiveCount)) | 1442 | if (!checkPrimitiveCount(primitiveCount)) |
1443 | return; | 1443 | return; |
1444 | 1444 | ||
1445 | CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType); | 1445 | CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType); |
1446 | 1446 | ||
1447 | if (vertices && !FeatureAvailable[IRR_ARB_vertex_array_bgra] && !FeatureAvailable[IRR_EXT_vertex_array_bgra]) | 1447 | if (vertices && !FeatureAvailable[IRR_ARB_vertex_array_bgra] && !FeatureAvailable[IRR_EXT_vertex_array_bgra]) |
1448 | getColorBuffer(vertices, vertexCount, vType); | 1448 | getColorBuffer(vertices, vertexCount, vType); |
1449 | 1449 | ||
1450 | // draw everything | 1450 | // draw everything |
1451 | setRenderStates3DMode(); | 1451 | setRenderStates3DMode(); |
1452 | 1452 | ||
1453 | if (MultiTextureExtension) | 1453 | if (MultiTextureExtension) |
1454 | extGlClientActiveTexture(GL_TEXTURE0_ARB); | 1454 | extGlClientActiveTexture(GL_TEXTURE0_ARB); |
1455 | 1455 | ||
1456 | glEnableClientState(GL_COLOR_ARRAY); | 1456 | glEnableClientState(GL_COLOR_ARRAY); |
1457 | glEnableClientState(GL_VERTEX_ARRAY); | 1457 | glEnableClientState(GL_VERTEX_ARRAY); |
1458 | if ((pType!=scene::EPT_POINTS) && (pType!=scene::EPT_POINT_SPRITES)) | 1458 | if ((pType!=scene::EPT_POINTS) && (pType!=scene::EPT_POINT_SPRITES)) |
1459 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | 1459 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
1460 | if ((pType!=scene::EPT_POINTS) && (pType!=scene::EPT_POINT_SPRITES)) | 1460 | if ((pType!=scene::EPT_POINTS) && (pType!=scene::EPT_POINT_SPRITES)) |
1461 | glEnableClientState(GL_NORMAL_ARRAY); | 1461 | glEnableClientState(GL_NORMAL_ARRAY); |
1462 | 1462 | ||
1463 | //due to missing defines in OSX headers, we have to be more specific with this check | 1463 | //due to missing defines in OSX headers, we have to be more specific with this check |
1464 | //#if defined(GL_ARB_vertex_array_bgra) || defined(GL_EXT_vertex_array_bgra) | 1464 | //#if defined(GL_ARB_vertex_array_bgra) || defined(GL_EXT_vertex_array_bgra) |
1465 | #ifdef GL_BGRA | 1465 | #ifdef GL_BGRA |
1466 | const GLint colorSize=(FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra])?GL_BGRA:4; | 1466 | const GLint colorSize=(FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra])?GL_BGRA:4; |
1467 | #else | 1467 | #else |
1468 | const GLint colorSize=4; | 1468 | const GLint colorSize=4; |
1469 | #endif | 1469 | #endif |
1470 | if (vertices) | 1470 | if (vertices) |
1471 | { | 1471 | { |
1472 | if (FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra]) | 1472 | if (FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra]) |
1473 | { | 1473 | { |
1474 | switch (vType) | 1474 | switch (vType) |
1475 | { | 1475 | { |
1476 | case EVT_STANDARD: | 1476 | case EVT_STANDARD: |
1477 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Color); | 1477 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Color); |
1478 | break; | 1478 | break; |
1479 | case EVT_2TCOORDS: | 1479 | case EVT_2TCOORDS: |
1480 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Color); | 1480 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Color); |
1481 | break; | 1481 | break; |
1482 | case EVT_TANGENTS: | 1482 | case EVT_TANGENTS: |
1483 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Color); | 1483 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Color); |
1484 | break; | 1484 | break; |
1485 | } | 1485 | } |
1486 | } | 1486 | } |
1487 | else | 1487 | else |
1488 | { | 1488 | { |
1489 | // avoid passing broken pointer to OpenGL | 1489 | // avoid passing broken pointer to OpenGL |
1490 | _IRR_DEBUG_BREAK_IF(ColorBuffer.size()==0); | 1490 | _IRR_DEBUG_BREAK_IF(ColorBuffer.size()==0); |
1491 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]); | 1491 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]); |
1492 | } | 1492 | } |
1493 | } | 1493 | } |
1494 | 1494 | ||
1495 | switch (vType) | 1495 | switch (vType) |
1496 | { | 1496 | { |
1497 | case EVT_STANDARD: | 1497 | case EVT_STANDARD: |
1498 | if (vertices) | 1498 | if (vertices) |
1499 | { | 1499 | { |
1500 | glNormalPointer(GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Normal); | 1500 | glNormalPointer(GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Normal); |
1501 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].TCoords); | 1501 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].TCoords); |
1502 | glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Pos); | 1502 | glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Pos); |
1503 | } | 1503 | } |
1504 | else | 1504 | else |
1505 | { | 1505 | { |
1506 | glNormalPointer(GL_FLOAT, sizeof(S3DVertex), buffer_offset(12)); | 1506 | glNormalPointer(GL_FLOAT, sizeof(S3DVertex), buffer_offset(12)); |
1507 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), buffer_offset(24)); | 1507 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), buffer_offset(24)); |
1508 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), buffer_offset(28)); | 1508 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), buffer_offset(28)); |
1509 | glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex), 0); | 1509 | glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex), 0); |
1510 | } | 1510 | } |
1511 | 1511 | ||
1512 | if (MultiTextureExtension && CurrentTexture[1]) | 1512 | if (MultiTextureExtension && CurrentTexture[1]) |
1513 | { | 1513 | { |
1514 | extGlClientActiveTexture(GL_TEXTURE1_ARB); | 1514 | extGlClientActiveTexture(GL_TEXTURE1_ARB); |
1515 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | 1515 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
1516 | if (vertices) | 1516 | if (vertices) |
1517 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].TCoords); | 1517 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].TCoords); |
1518 | else | 1518 | else |
1519 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), buffer_offset(28)); | 1519 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), buffer_offset(28)); |
1520 | } | 1520 | } |
1521 | break; | 1521 | break; |
1522 | case EVT_2TCOORDS: | 1522 | case EVT_2TCOORDS: |
1523 | if (vertices) | 1523 | if (vertices) |
1524 | { | 1524 | { |
1525 | glNormalPointer(GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Normal); | 1525 | glNormalPointer(GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Normal); |
1526 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].TCoords); | 1526 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].TCoords); |
1527 | glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Pos); | 1527 | glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Pos); |
1528 | } | 1528 | } |
1529 | else | 1529 | else |
1530 | { | 1530 | { |
1531 | glNormalPointer(GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(12)); | 1531 | glNormalPointer(GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(12)); |
1532 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex2TCoords), buffer_offset(24)); | 1532 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex2TCoords), buffer_offset(24)); |
1533 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(28)); | 1533 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(28)); |
1534 | glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(0)); | 1534 | glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(0)); |
1535 | } | 1535 | } |
1536 | 1536 | ||
1537 | 1537 | ||
1538 | if (MultiTextureExtension) | 1538 | if (MultiTextureExtension) |
1539 | { | 1539 | { |
1540 | extGlClientActiveTexture(GL_TEXTURE1_ARB); | 1540 | extGlClientActiveTexture(GL_TEXTURE1_ARB); |
1541 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | 1541 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
1542 | if (vertices) | 1542 | if (vertices) |
1543 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].TCoords2); | 1543 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].TCoords2); |
1544 | else | 1544 | else |
1545 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(36)); | 1545 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(36)); |
1546 | } | 1546 | } |
1547 | break; | 1547 | break; |
1548 | case EVT_TANGENTS: | 1548 | case EVT_TANGENTS: |
1549 | if (vertices) | 1549 | if (vertices) |
1550 | { | 1550 | { |
1551 | glNormalPointer(GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Normal); | 1551 | glNormalPointer(GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Normal); |
1552 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].TCoords); | 1552 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].TCoords); |
1553 | glVertexPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Pos); | 1553 | glVertexPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Pos); |
1554 | } | 1554 | } |
1555 | else | 1555 | else |
1556 | { | 1556 | { |
1557 | glNormalPointer(GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(12)); | 1557 | glNormalPointer(GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(12)); |
1558 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertexTangents), buffer_offset(24)); | 1558 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertexTangents), buffer_offset(24)); |
1559 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(28)); | 1559 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(28)); |
1560 | glVertexPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(0)); | 1560 | glVertexPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(0)); |
1561 | } | 1561 | } |
1562 | 1562 | ||
1563 | if (MultiTextureExtension) | 1563 | if (MultiTextureExtension) |
1564 | { | 1564 | { |
1565 | extGlClientActiveTexture(GL_TEXTURE1_ARB); | 1565 | extGlClientActiveTexture(GL_TEXTURE1_ARB); |
1566 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | 1566 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
1567 | if (vertices) | 1567 | if (vertices) |
1568 | glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Tangent); | 1568 | glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Tangent); |
1569 | else | 1569 | else |
1570 | glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(36)); | 1570 | glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(36)); |
1571 | 1571 | ||
1572 | extGlClientActiveTexture(GL_TEXTURE2_ARB); | 1572 | extGlClientActiveTexture(GL_TEXTURE2_ARB); |
1573 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | 1573 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
1574 | if (vertices) | 1574 | if (vertices) |
1575 | glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Binormal); | 1575 | glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Binormal); |
1576 | else | 1576 | else |
1577 | glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(48)); | 1577 | glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(48)); |
1578 | } | 1578 | } |
1579 | break; | 1579 | break; |
1580 | } | 1580 | } |
1581 | 1581 | ||
1582 | renderArray(indexList, primitiveCount, pType, iType); | 1582 | renderArray(indexList, primitiveCount, pType, iType); |
1583 | 1583 | ||
1584 | if (MultiTextureExtension) | 1584 | if (MultiTextureExtension) |
1585 | { | 1585 | { |
1586 | if (vType==EVT_TANGENTS) | 1586 | if (vType==EVT_TANGENTS) |
1587 | { | 1587 | { |
1588 | extGlClientActiveTexture(GL_TEXTURE2_ARB); | 1588 | extGlClientActiveTexture(GL_TEXTURE2_ARB); |
1589 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | 1589 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
1590 | } | 1590 | } |
1591 | if ((vType!=EVT_STANDARD) || CurrentTexture[1]) | 1591 | if ((vType!=EVT_STANDARD) || CurrentTexture[1]) |
1592 | { | 1592 | { |
1593 | extGlClientActiveTexture(GL_TEXTURE1_ARB); | 1593 | extGlClientActiveTexture(GL_TEXTURE1_ARB); |
1594 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | 1594 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
1595 | } | 1595 | } |
1596 | extGlClientActiveTexture(GL_TEXTURE0_ARB); | 1596 | extGlClientActiveTexture(GL_TEXTURE0_ARB); |
1597 | } | 1597 | } |
1598 | glDisableClientState(GL_COLOR_ARRAY); | 1598 | glDisableClientState(GL_COLOR_ARRAY); |
1599 | glDisableClientState(GL_VERTEX_ARRAY); | 1599 | glDisableClientState(GL_VERTEX_ARRAY); |
1600 | glDisableClientState(GL_NORMAL_ARRAY); | 1600 | glDisableClientState(GL_NORMAL_ARRAY); |
1601 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | 1601 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
1602 | } | 1602 | } |
1603 | 1603 | ||
1604 | 1604 | ||
1605 | void COpenGLDriver::getColorBuffer(const void* vertices, u32 vertexCount, E_VERTEX_TYPE vType) | 1605 | void COpenGLDriver::getColorBuffer(const void* vertices, u32 vertexCount, E_VERTEX_TYPE vType) |
1606 | { | 1606 | { |
1607 | // convert colors to gl color format. | 1607 | // convert colors to gl color format. |
1608 | vertexCount *= 4; //reused as color component count | 1608 | vertexCount *= 4; //reused as color component count |
1609 | ColorBuffer.set_used(vertexCount); | 1609 | ColorBuffer.set_used(vertexCount); |
1610 | u32 i; | 1610 | u32 i; |
1611 | 1611 | ||
1612 | switch (vType) | 1612 | switch (vType) |
1613 | { | 1613 | { |
1614 | case EVT_STANDARD: | 1614 | case EVT_STANDARD: |
1615 | { | 1615 | { |
1616 | const S3DVertex* p = static_cast<const S3DVertex*>(vertices); | 1616 | const S3DVertex* p = static_cast<const S3DVertex*>(vertices); |
1617 | for (i=0; i<vertexCount; i+=4) | 1617 | for (i=0; i<vertexCount; i+=4) |
1618 | { | 1618 | { |
1619 | p->Color.toOpenGLColor(&ColorBuffer[i]); | 1619 | p->Color.toOpenGLColor(&ColorBuffer[i]); |
1620 | ++p; | 1620 | ++p; |
1621 | } | 1621 | } |
1622 | } | 1622 | } |
1623 | break; | 1623 | break; |
1624 | case EVT_2TCOORDS: | 1624 | case EVT_2TCOORDS: |
1625 | { | 1625 | { |
1626 | const S3DVertex2TCoords* p = static_cast<const S3DVertex2TCoords*>(vertices); | 1626 | const S3DVertex2TCoords* p = static_cast<const S3DVertex2TCoords*>(vertices); |
1627 | for (i=0; i<vertexCount; i+=4) | 1627 | for (i=0; i<vertexCount; i+=4) |
1628 | { | 1628 | { |
1629 | p->Color.toOpenGLColor(&ColorBuffer[i]); | 1629 | p->Color.toOpenGLColor(&ColorBuffer[i]); |
1630 | ++p; | 1630 | ++p; |
1631 | } | 1631 | } |
1632 | } | 1632 | } |
1633 | break; | 1633 | break; |
1634 | case EVT_TANGENTS: | 1634 | case EVT_TANGENTS: |
1635 | { | 1635 | { |
1636 | const S3DVertexTangents* p = static_cast<const S3DVertexTangents*>(vertices); | 1636 | const S3DVertexTangents* p = static_cast<const S3DVertexTangents*>(vertices); |
1637 | for (i=0; i<vertexCount; i+=4) | 1637 | for (i=0; i<vertexCount; i+=4) |
1638 | { | 1638 | { |
1639 | p->Color.toOpenGLColor(&ColorBuffer[i]); | 1639 | p->Color.toOpenGLColor(&ColorBuffer[i]); |
1640 | ++p; | 1640 | ++p; |
1641 | } | 1641 | } |
1642 | } | 1642 | } |
1643 | break; | 1643 | break; |
1644 | } | 1644 | } |
1645 | } | 1645 | } |
1646 | 1646 | ||
1647 | 1647 | ||
1648 | void COpenGLDriver::renderArray(const void* indexList, u32 primitiveCount, | 1648 | void COpenGLDriver::renderArray(const void* indexList, u32 primitiveCount, |
1649 | scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) | 1649 | scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) |
1650 | { | 1650 | { |
1651 | GLenum indexSize=0; | 1651 | GLenum indexSize=0; |
1652 | 1652 | ||
1653 | switch (iType) | 1653 | switch (iType) |
1654 | { | 1654 | { |
1655 | case EIT_16BIT: | 1655 | case EIT_16BIT: |
1656 | { | 1656 | { |
1657 | indexSize=GL_UNSIGNED_SHORT; | 1657 | indexSize=GL_UNSIGNED_SHORT; |
1658 | break; | 1658 | break; |
1659 | } | 1659 | } |
1660 | case EIT_32BIT: | 1660 | case EIT_32BIT: |
1661 | { | 1661 | { |
1662 | indexSize=GL_UNSIGNED_INT; | 1662 | indexSize=GL_UNSIGNED_INT; |
1663 | break; | 1663 | break; |
1664 | } | 1664 | } |
1665 | } | 1665 | } |
1666 | 1666 | ||
1667 | switch (pType) | 1667 | switch (pType) |
1668 | { | 1668 | { |
1669 | case scene::EPT_POINTS: | 1669 | case scene::EPT_POINTS: |
1670 | case scene::EPT_POINT_SPRITES: | 1670 | case scene::EPT_POINT_SPRITES: |
1671 | { | 1671 | { |
1672 | #ifdef GL_ARB_point_sprite | 1672 | #ifdef GL_ARB_point_sprite |
1673 | if (pType==scene::EPT_POINT_SPRITES && FeatureAvailable[IRR_ARB_point_sprite]) | 1673 | if (pType==scene::EPT_POINT_SPRITES && FeatureAvailable[IRR_ARB_point_sprite]) |
1674 | glEnable(GL_POINT_SPRITE_ARB); | 1674 | glEnable(GL_POINT_SPRITE_ARB); |
1675 | #endif | 1675 | #endif |
1676 | 1676 | ||
1677 | // prepare size and attenuation (where supported) | 1677 | // prepare size and attenuation (where supported) |
1678 | GLfloat particleSize=Material.Thickness; | 1678 | GLfloat particleSize=Material.Thickness; |
1679 | // if (AntiAlias) | 1679 | // if (AntiAlias) |
1680 | // particleSize=core::clamp(particleSize, DimSmoothedPoint[0], DimSmoothedPoint[1]); | 1680 | // particleSize=core::clamp(particleSize, DimSmoothedPoint[0], DimSmoothedPoint[1]); |
1681 | // else | 1681 | // else |
1682 | particleSize=core::clamp(particleSize, DimAliasedPoint[0], DimAliasedPoint[1]); | 1682 | particleSize=core::clamp(particleSize, DimAliasedPoint[0], DimAliasedPoint[1]); |
1683 | #if defined(GL_VERSION_1_4) || defined(GL_ARB_point_parameters) || defined(GL_EXT_point_parameters) || defined(GL_SGIS_point_parameters) | 1683 | #if defined(GL_VERSION_1_4) || defined(GL_ARB_point_parameters) || defined(GL_EXT_point_parameters) || defined(GL_SGIS_point_parameters) |
1684 | const float att[] = {1.0f, 1.0f, 0.0f}; | 1684 | const float att[] = {1.0f, 1.0f, 0.0f}; |
1685 | #if defined(GL_VERSION_1_4) | 1685 | #if defined(GL_VERSION_1_4) |
1686 | extGlPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, att); | 1686 | extGlPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, att); |
1687 | // extGlPointParameterf(GL_POINT_SIZE_MIN,1.f); | 1687 | // extGlPointParameterf(GL_POINT_SIZE_MIN,1.f); |
1688 | extGlPointParameterf(GL_POINT_SIZE_MAX, particleSize); | 1688 | extGlPointParameterf(GL_POINT_SIZE_MAX, particleSize); |
1689 | extGlPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE, 1.0f); | 1689 | extGlPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE, 1.0f); |
1690 | #elif defined(GL_ARB_point_parameters) | 1690 | #elif defined(GL_ARB_point_parameters) |
1691 | extGlPointParameterfv(GL_POINT_DISTANCE_ATTENUATION_ARB, att); | 1691 | extGlPointParameterfv(GL_POINT_DISTANCE_ATTENUATION_ARB, att); |
1692 | // extGlPointParameterf(GL_POINT_SIZE_MIN_ARB,1.f); | 1692 | // extGlPointParameterf(GL_POINT_SIZE_MIN_ARB,1.f); |
1693 | extGlPointParameterf(GL_POINT_SIZE_MAX_ARB, particleSize); | 1693 | extGlPointParameterf(GL_POINT_SIZE_MAX_ARB, particleSize); |
1694 | extGlPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_ARB, 1.0f); | 1694 | extGlPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_ARB, 1.0f); |
1695 | #elif defined(GL_EXT_point_parameters) | 1695 | #elif defined(GL_EXT_point_parameters) |
1696 | extGlPointParameterfv(GL_DISTANCE_ATTENUATION_EXT, att); | 1696 | extGlPointParameterfv(GL_DISTANCE_ATTENUATION_EXT, att); |
1697 | // extGlPointParameterf(GL_POINT_SIZE_MIN_EXT,1.f); | 1697 | // extGlPointParameterf(GL_POINT_SIZE_MIN_EXT,1.f); |
1698 | extGlPointParameterf(GL_POINT_SIZE_MAX_EXT, particleSize); | 1698 | extGlPointParameterf(GL_POINT_SIZE_MAX_EXT, particleSize); |
1699 | extGlPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_EXT, 1.0f); | 1699 | extGlPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_EXT, 1.0f); |
1700 | #elif defined(GL_SGIS_point_parameters) | 1700 | #elif defined(GL_SGIS_point_parameters) |
1701 | extGlPointParameterfv(GL_DISTANCE_ATTENUATION_SGIS, att); | 1701 | extGlPointParameterfv(GL_DISTANCE_ATTENUATION_SGIS, att); |
1702 | // extGlPointParameterf(GL_POINT_SIZE_MIN_SGIS,1.f); | 1702 | // extGlPointParameterf(GL_POINT_SIZE_MIN_SGIS,1.f); |
1703 | extGlPointParameterf(GL_POINT_SIZE_MAX_SGIS, particleSize); | 1703 | extGlPointParameterf(GL_POINT_SIZE_MAX_SGIS, particleSize); |
1704 | extGlPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_SGIS, 1.0f); | 1704 | extGlPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_SGIS, 1.0f); |
1705 | #endif | 1705 | #endif |
1706 | #endif | 1706 | #endif |
1707 | glPointSize(particleSize); | 1707 | glPointSize(particleSize); |
1708 | 1708 | ||
1709 | #ifdef GL_ARB_point_sprite | 1709 | #ifdef GL_ARB_point_sprite |
1710 | if (pType==scene::EPT_POINT_SPRITES && FeatureAvailable[IRR_ARB_point_sprite]) | 1710 | if (pType==scene::EPT_POINT_SPRITES && FeatureAvailable[IRR_ARB_point_sprite]) |
1711 | glTexEnvf(GL_POINT_SPRITE_ARB,GL_COORD_REPLACE, GL_TRUE); | 1711 | glTexEnvf(GL_POINT_SPRITE_ARB,GL_COORD_REPLACE, GL_TRUE); |
1712 | #endif | 1712 | #endif |
1713 | glDrawArrays(GL_POINTS, 0, primitiveCount); | 1713 | glDrawArrays(GL_POINTS, 0, primitiveCount); |
1714 | #ifdef GL_ARB_point_sprite | 1714 | #ifdef GL_ARB_point_sprite |
1715 | if (pType==scene::EPT_POINT_SPRITES && FeatureAvailable[IRR_ARB_point_sprite]) | 1715 | if (pType==scene::EPT_POINT_SPRITES && FeatureAvailable[IRR_ARB_point_sprite]) |
1716 | { | 1716 | { |
1717 | glDisable(GL_POINT_SPRITE_ARB); | 1717 | glDisable(GL_POINT_SPRITE_ARB); |
1718 | glTexEnvf(GL_POINT_SPRITE_ARB,GL_COORD_REPLACE, GL_FALSE); | 1718 | glTexEnvf(GL_POINT_SPRITE_ARB,GL_COORD_REPLACE, GL_FALSE); |
1719 | } | 1719 | } |
1720 | #endif | 1720 | #endif |
1721 | } | 1721 | } |
1722 | break; | 1722 | break; |
1723 | case scene::EPT_LINE_STRIP: | 1723 | case scene::EPT_LINE_STRIP: |
1724 | glDrawElements(GL_LINE_STRIP, primitiveCount+1, indexSize, indexList); | 1724 | glDrawElements(GL_LINE_STRIP, primitiveCount+1, indexSize, indexList); |
1725 | break; | 1725 | break; |
1726 | case scene::EPT_LINE_LOOP: | 1726 | case scene::EPT_LINE_LOOP: |
1727 | glDrawElements(GL_LINE_LOOP, primitiveCount, indexSize, indexList); | 1727 | glDrawElements(GL_LINE_LOOP, primitiveCount, indexSize, indexList); |
1728 | break; | 1728 | break; |
1729 | case scene::EPT_LINES: | 1729 | case scene::EPT_LINES: |
1730 | glDrawElements(GL_LINES, primitiveCount*2, indexSize, indexList); | 1730 | glDrawElements(GL_LINES, primitiveCount*2, indexSize, indexList); |
1731 | break; | 1731 | break; |
1732 | case scene::EPT_TRIANGLE_STRIP: | 1732 | case scene::EPT_TRIANGLE_STRIP: |
1733 | glDrawElements(GL_TRIANGLE_STRIP, primitiveCount+2, indexSize, indexList); | 1733 | glDrawElements(GL_TRIANGLE_STRIP, primitiveCount+2, indexSize, indexList); |
1734 | break; | 1734 | break; |
1735 | case scene::EPT_TRIANGLE_FAN: | 1735 | case scene::EPT_TRIANGLE_FAN: |
1736 | glDrawElements(GL_TRIANGLE_FAN, primitiveCount+2, indexSize, indexList); | 1736 | glDrawElements(GL_TRIANGLE_FAN, primitiveCount+2, indexSize, indexList); |
1737 | break; | 1737 | break; |
1738 | case scene::EPT_TRIANGLES: | 1738 | case scene::EPT_TRIANGLES: |
1739 | glDrawElements(GL_TRIANGLES, primitiveCount*3, indexSize, indexList); | 1739 | glDrawElements(GL_TRIANGLES, primitiveCount*3, indexSize, indexList); |
1740 | break; | 1740 | break; |
1741 | case scene::EPT_QUAD_STRIP: | 1741 | case scene::EPT_QUAD_STRIP: |
1742 | glDrawElements(GL_QUAD_STRIP, primitiveCount*2+2, indexSize, indexList); | 1742 | glDrawElements(GL_QUAD_STRIP, primitiveCount*2+2, indexSize, indexList); |
1743 | break; | 1743 | break; |
1744 | case scene::EPT_QUADS: | 1744 | case scene::EPT_QUADS: |
1745 | glDrawElements(GL_QUADS, primitiveCount*4, indexSize, indexList); | 1745 | glDrawElements(GL_QUADS, primitiveCount*4, indexSize, indexList); |
1746 | break; | 1746 | break; |
1747 | case scene::EPT_POLYGON: | 1747 | case scene::EPT_POLYGON: |
1748 | glDrawElements(GL_POLYGON, primitiveCount, indexSize, indexList); | 1748 | glDrawElements(GL_POLYGON, primitiveCount, indexSize, indexList); |
1749 | break; | 1749 | break; |
1750 | } | 1750 | } |
1751 | } | 1751 | } |
1752 | 1752 | ||
1753 | 1753 | ||
1754 | //! draws a vertex primitive list in 2d | 1754 | //! draws a vertex primitive list in 2d |
1755 | void COpenGLDriver::draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, | 1755 | void COpenGLDriver::draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, |
1756 | const void* indexList, u32 primitiveCount, | 1756 | const void* indexList, u32 primitiveCount, |
1757 | E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) | 1757 | E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) |
1758 | { | 1758 | { |
1759 | if (!primitiveCount || !vertexCount) | 1759 | if (!primitiveCount || !vertexCount) |
1760 | return; | 1760 | return; |
1761 | 1761 | ||
1762 | if (!checkPrimitiveCount(primitiveCount)) | 1762 | if (!checkPrimitiveCount(primitiveCount)) |
1763 | return; | 1763 | return; |
1764 | 1764 | ||
1765 | CNullDriver::draw2DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType); | 1765 | CNullDriver::draw2DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType); |
1766 | 1766 | ||
1767 | if (vertices && !FeatureAvailable[IRR_ARB_vertex_array_bgra] && !FeatureAvailable[IRR_EXT_vertex_array_bgra]) | 1767 | if (vertices && !FeatureAvailable[IRR_ARB_vertex_array_bgra] && !FeatureAvailable[IRR_EXT_vertex_array_bgra]) |
1768 | getColorBuffer(vertices, vertexCount, vType); | 1768 | getColorBuffer(vertices, vertexCount, vType); |
1769 | 1769 | ||
1770 | // draw everything | 1770 | // draw everything |
1771 | this->setActiveTexture(0, Material.getTexture(0)); | 1771 | this->setActiveTexture(0, Material.getTexture(0)); |
1772 | if (Material.MaterialType==EMT_ONETEXTURE_BLEND) | 1772 | if (Material.MaterialType==EMT_ONETEXTURE_BLEND) |
1773 | { | 1773 | { |
1774 | E_BLEND_FACTOR srcFact; | 1774 | E_BLEND_FACTOR srcFact; |
1775 | E_BLEND_FACTOR dstFact; | 1775 | E_BLEND_FACTOR dstFact; |
1776 | E_MODULATE_FUNC modulo; | 1776 | E_MODULATE_FUNC modulo; |
1777 | u32 alphaSource; | 1777 | u32 alphaSource; |
1778 | unpack_textureBlendFunc ( srcFact, dstFact, modulo, alphaSource, Material.MaterialTypeParam); | 1778 | unpack_textureBlendFunc ( srcFact, dstFact, modulo, alphaSource, Material.MaterialTypeParam); |
1779 | setRenderStates2DMode(alphaSource&video::EAS_VERTEX_COLOR, (Material.getTexture(0) != 0), (alphaSource&video::EAS_TEXTURE) != 0); | 1779 | setRenderStates2DMode(alphaSource&video::EAS_VERTEX_COLOR, (Material.getTexture(0) != 0), (alphaSource&video::EAS_TEXTURE) != 0); |
1780 | } | 1780 | } |
1781 | else | 1781 | else |
1782 | setRenderStates2DMode(Material.MaterialType==EMT_TRANSPARENT_VERTEX_ALPHA, (Material.getTexture(0) != 0), Material.MaterialType==EMT_TRANSPARENT_ALPHA_CHANNEL); | 1782 | setRenderStates2DMode(Material.MaterialType==EMT_TRANSPARENT_VERTEX_ALPHA, (Material.getTexture(0) != 0), Material.MaterialType==EMT_TRANSPARENT_ALPHA_CHANNEL); |
1783 | 1783 | ||
1784 | if (MultiTextureExtension) | 1784 | if (MultiTextureExtension) |
1785 | extGlClientActiveTexture(GL_TEXTURE0_ARB); | 1785 | extGlClientActiveTexture(GL_TEXTURE0_ARB); |
1786 | 1786 | ||
1787 | glEnableClientState(GL_COLOR_ARRAY); | 1787 | glEnableClientState(GL_COLOR_ARRAY); |
1788 | glEnableClientState(GL_VERTEX_ARRAY); | 1788 | glEnableClientState(GL_VERTEX_ARRAY); |
1789 | if ((pType!=scene::EPT_POINTS) && (pType!=scene::EPT_POINT_SPRITES)) | 1789 | if ((pType!=scene::EPT_POINTS) && (pType!=scene::EPT_POINT_SPRITES)) |
1790 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | 1790 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
1791 | 1791 | ||
1792 | //due to missing defines in OSX headers, we have to be more specific with this check | 1792 | //due to missing defines in OSX headers, we have to be more specific with this check |
1793 | //#if defined(GL_ARB_vertex_array_bgra) || defined(GL_EXT_vertex_array_bgra) | 1793 | //#if defined(GL_ARB_vertex_array_bgra) || defined(GL_EXT_vertex_array_bgra) |
1794 | #ifdef GL_BGRA | 1794 | #ifdef GL_BGRA |
1795 | const GLint colorSize=(FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra])?GL_BGRA:4; | 1795 | const GLint colorSize=(FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra])?GL_BGRA:4; |
1796 | #else | 1796 | #else |
1797 | const GLint colorSize=4; | 1797 | const GLint colorSize=4; |
1798 | #endif | 1798 | #endif |
1799 | if (vertices) | 1799 | if (vertices) |
1800 | { | 1800 | { |
1801 | if (FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra]) | 1801 | if (FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra]) |
1802 | { | 1802 | { |
1803 | switch (vType) | 1803 | switch (vType) |
1804 | { | 1804 | { |
1805 | case EVT_STANDARD: | 1805 | case EVT_STANDARD: |
1806 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Color); | 1806 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Color); |
1807 | break; | 1807 | break; |
1808 | case EVT_2TCOORDS: | 1808 | case EVT_2TCOORDS: |
1809 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Color); | 1809 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Color); |
1810 | break; | 1810 | break; |
1811 | case EVT_TANGENTS: | 1811 | case EVT_TANGENTS: |
1812 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Color); | 1812 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Color); |
1813 | break; | 1813 | break; |
1814 | } | 1814 | } |
1815 | } | 1815 | } |
1816 | else | 1816 | else |
1817 | { | 1817 | { |
1818 | // avoid passing broken pointer to OpenGL | 1818 | // avoid passing broken pointer to OpenGL |
1819 | _IRR_DEBUG_BREAK_IF(ColorBuffer.size()==0); | 1819 | _IRR_DEBUG_BREAK_IF(ColorBuffer.size()==0); |
1820 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]); | 1820 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]); |
1821 | } | 1821 | } |
1822 | } | 1822 | } |
1823 | 1823 | ||
1824 | switch (vType) | 1824 | switch (vType) |
1825 | { | 1825 | { |
1826 | case EVT_STANDARD: | 1826 | case EVT_STANDARD: |
1827 | if (vertices) | 1827 | if (vertices) |
1828 | { | 1828 | { |
1829 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].TCoords); | 1829 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].TCoords); |
1830 | glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Pos); | 1830 | glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Pos); |
1831 | } | 1831 | } |
1832 | else | 1832 | else |
1833 | { | 1833 | { |
1834 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), buffer_offset(24)); | 1834 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), buffer_offset(24)); |
1835 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), buffer_offset(28)); | 1835 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), buffer_offset(28)); |
1836 | glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex), 0); | 1836 | glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex), 0); |
1837 | } | 1837 | } |
1838 | 1838 | ||
1839 | if (MultiTextureExtension && CurrentTexture[1]) | 1839 | if (MultiTextureExtension && CurrentTexture[1]) |
1840 | { | 1840 | { |
1841 | extGlClientActiveTexture(GL_TEXTURE1_ARB); | 1841 | extGlClientActiveTexture(GL_TEXTURE1_ARB); |
1842 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | 1842 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
1843 | if (vertices) | 1843 | if (vertices) |
1844 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].TCoords); | 1844 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].TCoords); |
1845 | else | 1845 | else |
1846 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), buffer_offset(28)); | 1846 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), buffer_offset(28)); |
1847 | } | 1847 | } |
1848 | break; | 1848 | break; |
1849 | case EVT_2TCOORDS: | 1849 | case EVT_2TCOORDS: |
1850 | if (vertices) | 1850 | if (vertices) |
1851 | { | 1851 | { |
1852 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].TCoords); | 1852 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].TCoords); |
1853 | glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Pos); | 1853 | glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Pos); |
1854 | } | 1854 | } |
1855 | else | 1855 | else |
1856 | { | 1856 | { |
1857 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex2TCoords), buffer_offset(24)); | 1857 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex2TCoords), buffer_offset(24)); |
1858 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(28)); | 1858 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(28)); |
1859 | glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(0)); | 1859 | glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(0)); |
1860 | } | 1860 | } |
1861 | 1861 | ||
1862 | if (MultiTextureExtension) | 1862 | if (MultiTextureExtension) |
1863 | { | 1863 | { |
1864 | extGlClientActiveTexture(GL_TEXTURE1_ARB); | 1864 | extGlClientActiveTexture(GL_TEXTURE1_ARB); |
1865 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | 1865 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
1866 | if (vertices) | 1866 | if (vertices) |
1867 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].TCoords2); | 1867 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].TCoords2); |
1868 | else | 1868 | else |
1869 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(36)); | 1869 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(36)); |
1870 | } | 1870 | } |
1871 | break; | 1871 | break; |
1872 | case EVT_TANGENTS: | 1872 | case EVT_TANGENTS: |
1873 | if (vertices) | 1873 | if (vertices) |
1874 | { | 1874 | { |
1875 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].TCoords); | 1875 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].TCoords); |
1876 | glVertexPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Pos); | 1876 | glVertexPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Pos); |
1877 | } | 1877 | } |
1878 | else | 1878 | else |
1879 | { | 1879 | { |
1880 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertexTangents), buffer_offset(24)); | 1880 | glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertexTangents), buffer_offset(24)); |
1881 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(28)); | 1881 | glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(28)); |
1882 | glVertexPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(0)); | 1882 | glVertexPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(0)); |
1883 | } | 1883 | } |
1884 | 1884 | ||
1885 | break; | 1885 | break; |
1886 | } | 1886 | } |
1887 | 1887 | ||
1888 | renderArray(indexList, primitiveCount, pType, iType); | 1888 | renderArray(indexList, primitiveCount, pType, iType); |
1889 | 1889 | ||
1890 | if (MultiTextureExtension) | 1890 | if (MultiTextureExtension) |
1891 | { | 1891 | { |
1892 | if ((vType!=EVT_STANDARD) || CurrentTexture[1]) | 1892 | if ((vType!=EVT_STANDARD) || CurrentTexture[1]) |
1893 | { | 1893 | { |
1894 | extGlClientActiveTexture(GL_TEXTURE1_ARB); | 1894 | extGlClientActiveTexture(GL_TEXTURE1_ARB); |
1895 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | 1895 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
1896 | } | 1896 | } |
1897 | extGlClientActiveTexture(GL_TEXTURE0_ARB); | 1897 | extGlClientActiveTexture(GL_TEXTURE0_ARB); |
1898 | } | 1898 | } |
1899 | glDisableClientState(GL_COLOR_ARRAY); | 1899 | glDisableClientState(GL_COLOR_ARRAY); |
1900 | glDisableClientState(GL_VERTEX_ARRAY); | 1900 | glDisableClientState(GL_VERTEX_ARRAY); |
1901 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | 1901 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
1902 | } | 1902 | } |
1903 | 1903 | ||
1904 | 1904 | ||
1905 | //! draws a set of 2d images, using a color and the alpha channel of the | 1905 | //! draws a set of 2d images, using a color and the alpha channel of the |
1906 | //! texture if desired. | 1906 | //! texture if desired. |
1907 | void COpenGLDriver::draw2DImageBatch(const video::ITexture* texture, | 1907 | void COpenGLDriver::draw2DImageBatch(const video::ITexture* texture, |
1908 | const core::array<core::position2d<s32> >& positions, | 1908 | const core::array<core::position2d<s32> >& positions, |
1909 | const core::array<core::rect<s32> >& sourceRects, | 1909 | const core::array<core::rect<s32> >& sourceRects, |
1910 | const core::rect<s32>* clipRect, | 1910 | const core::rect<s32>* clipRect, |
1911 | SColor color, | 1911 | SColor color, |
1912 | bool useAlphaChannelOfTexture) | 1912 | bool useAlphaChannelOfTexture) |
1913 | { | 1913 | { |
1914 | if (!texture) | 1914 | if (!texture) |
1915 | return; | 1915 | return; |
1916 | 1916 | ||
1917 | const u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size()); | 1917 | const u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size()); |
1918 | 1918 | ||
1919 | const core::dimension2d<u32>& ss = texture->getOriginalSize(); | 1919 | const core::dimension2d<u32>& ss = texture->getOriginalSize(); |
1920 | const f32 invW = 1.f / static_cast<f32>(ss.Width); | 1920 | const f32 invW = 1.f / static_cast<f32>(ss.Width); |
1921 | const f32 invH = 1.f / static_cast<f32>(ss.Height); | 1921 | const f32 invH = 1.f / static_cast<f32>(ss.Height); |
1922 | const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize(); | 1922 | const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize(); |
1923 | 1923 | ||
1924 | disableTextures(1); | 1924 | disableTextures(1); |
1925 | if (!setActiveTexture(0, texture)) | 1925 | if (!setActiveTexture(0, texture)) |
1926 | return; | 1926 | return; |
1927 | setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); | 1927 | setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); |
1928 | 1928 | ||
1929 | glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); | 1929 | glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); |
1930 | glBegin(GL_QUADS); | 1930 | glBegin(GL_QUADS); |
1931 | 1931 | ||
1932 | for (u32 i=0; i<drawCount; ++i) | 1932 | for (u32 i=0; i<drawCount; ++i) |
1933 | { | 1933 | { |
1934 | if (!sourceRects[i].isValid()) | 1934 | if (!sourceRects[i].isValid()) |
1935 | continue; | 1935 | continue; |
1936 | 1936 | ||
1937 | core::position2d<s32> targetPos(positions[i]); | 1937 | core::position2d<s32> targetPos(positions[i]); |
1938 | core::position2d<s32> sourcePos(sourceRects[i].UpperLeftCorner); | 1938 | core::position2d<s32> sourcePos(sourceRects[i].UpperLeftCorner); |
1939 | // This needs to be signed as it may go negative. | 1939 | // This needs to be signed as it may go negative. |
1940 | core::dimension2d<s32> sourceSize(sourceRects[i].getSize()); | 1940 | core::dimension2d<s32> sourceSize(sourceRects[i].getSize()); |
1941 | if (clipRect) | 1941 | if (clipRect) |
1942 | { | 1942 | { |
1943 | if (targetPos.X < clipRect->UpperLeftCorner.X) | 1943 | if (targetPos.X < clipRect->UpperLeftCorner.X) |
1944 | { | 1944 | { |
1945 | sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X; | 1945 | sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X; |
1946 | if (sourceSize.Width <= 0) | 1946 | if (sourceSize.Width <= 0) |
1947 | continue; | 1947 | continue; |
1948 | 1948 | ||
1949 | sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X; | 1949 | sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X; |
1950 | targetPos.X = clipRect->UpperLeftCorner.X; | 1950 | targetPos.X = clipRect->UpperLeftCorner.X; |
1951 | } | 1951 | } |
1952 | 1952 | ||
1953 | if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X) | 1953 | if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X) |
1954 | { | 1954 | { |
1955 | sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X; | 1955 | sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X; |
1956 | if (sourceSize.Width <= 0) | 1956 | if (sourceSize.Width <= 0) |
1957 | continue; | 1957 | continue; |
1958 | } | 1958 | } |
1959 | 1959 | ||
1960 | if (targetPos.Y < clipRect->UpperLeftCorner.Y) | 1960 | if (targetPos.Y < clipRect->UpperLeftCorner.Y) |
1961 | { | 1961 | { |
1962 | sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y; | 1962 | sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y; |
1963 | if (sourceSize.Height <= 0) | 1963 | if (sourceSize.Height <= 0) |
1964 | continue; | 1964 | continue; |
1965 | 1965 | ||
1966 | sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y; | 1966 | sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y; |
1967 | targetPos.Y = clipRect->UpperLeftCorner.Y; | 1967 | targetPos.Y = clipRect->UpperLeftCorner.Y; |
1968 | } | 1968 | } |
1969 | 1969 | ||
1970 | if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y) | 1970 | if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y) |
1971 | { | 1971 | { |
1972 | sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y; | 1972 | sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y; |
1973 | if (sourceSize.Height <= 0) | 1973 | if (sourceSize.Height <= 0) |
1974 | continue; | 1974 | continue; |
1975 | } | 1975 | } |
1976 | } | 1976 | } |
1977 | 1977 | ||
1978 | // clip these coordinates | 1978 | // clip these coordinates |
1979 | 1979 | ||
1980 | if (targetPos.X<0) | 1980 | if (targetPos.X<0) |
1981 | { | 1981 | { |
1982 | sourceSize.Width += targetPos.X; | 1982 | sourceSize.Width += targetPos.X; |
1983 | if (sourceSize.Width <= 0) | 1983 | if (sourceSize.Width <= 0) |
1984 | continue; | 1984 | continue; |
1985 | 1985 | ||
1986 | sourcePos.X -= targetPos.X; | 1986 | sourcePos.X -= targetPos.X; |
1987 | targetPos.X = 0; | 1987 | targetPos.X = 0; |
1988 | } | 1988 | } |
1989 | 1989 | ||
1990 | if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width) | 1990 | if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width) |
1991 | { | 1991 | { |
1992 | sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width; | 1992 | sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width; |
1993 | if (sourceSize.Width <= 0) | 1993 | if (sourceSize.Width <= 0) |
1994 | continue; | 1994 | continue; |
1995 | } | 1995 | } |
1996 | 1996 | ||
1997 | if (targetPos.Y<0) | 1997 | if (targetPos.Y<0) |
1998 | { | 1998 | { |
1999 | sourceSize.Height += targetPos.Y; | 1999 | sourceSize.Height += targetPos.Y; |
2000 | if (sourceSize.Height <= 0) | 2000 | if (sourceSize.Height <= 0) |
2001 | continue; | 2001 | continue; |
2002 | 2002 | ||
2003 | sourcePos.Y -= targetPos.Y; | 2003 | sourcePos.Y -= targetPos.Y; |
2004 | targetPos.Y = 0; | 2004 | targetPos.Y = 0; |
2005 | } | 2005 | } |
2006 | 2006 | ||
2007 | if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height) | 2007 | if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height) |
2008 | { | 2008 | { |
2009 | sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height; | 2009 | sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height; |
2010 | if (sourceSize.Height <= 0) | 2010 | if (sourceSize.Height <= 0) |
2011 | continue; | 2011 | continue; |
2012 | } | 2012 | } |
2013 | 2013 | ||
2014 | // ok, we've clipped everything. | 2014 | // ok, we've clipped everything. |
2015 | // now draw it. | 2015 | // now draw it. |
2016 | 2016 | ||
2017 | const core::rect<f32> tcoords( | 2017 | const core::rect<f32> tcoords( |
2018 | sourcePos.X * invW, | 2018 | sourcePos.X * invW, |
2019 | sourcePos.Y * invH, | 2019 | sourcePos.Y * invH, |
2020 | (sourcePos.X + sourceSize.Width) * invW, | 2020 | (sourcePos.X + sourceSize.Width) * invW, |
2021 | (sourcePos.Y + sourceSize.Height) * invH); | 2021 | (sourcePos.Y + sourceSize.Height) * invH); |
2022 | 2022 | ||
2023 | const core::rect<s32> poss(targetPos, sourceSize); | 2023 | const core::rect<s32> poss(targetPos, sourceSize); |
2024 | 2024 | ||
2025 | glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); | 2025 | glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); |
2026 | glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.UpperLeftCorner.Y)); | 2026 | glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.UpperLeftCorner.Y)); |
2027 | 2027 | ||
2028 | glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); | 2028 | glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); |
2029 | glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.UpperLeftCorner.Y)); | 2029 | glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.UpperLeftCorner.Y)); |
2030 | 2030 | ||
2031 | glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); | 2031 | glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); |
2032 | glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.LowerRightCorner.Y)); | 2032 | glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.LowerRightCorner.Y)); |
2033 | 2033 | ||
2034 | glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); | 2034 | glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); |
2035 | glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.LowerRightCorner.Y)); | 2035 | glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.LowerRightCorner.Y)); |
2036 | } | 2036 | } |
2037 | glEnd(); | 2037 | glEnd(); |
2038 | } | 2038 | } |
2039 | 2039 | ||
2040 | 2040 | ||
2041 | //! draws a 2d image, using a color and the alpha channel of the texture if | 2041 | //! draws a 2d image, using a color and the alpha channel of the texture if |
2042 | //! desired. The image is drawn at pos, clipped against clipRect (if != 0). | 2042 | //! desired. The image is drawn at pos, clipped against clipRect (if != 0). |
2043 | //! Only the subtexture defined by sourceRect is used. | 2043 | //! Only the subtexture defined by sourceRect is used. |
2044 | void COpenGLDriver::draw2DImage(const video::ITexture* texture, | 2044 | void COpenGLDriver::draw2DImage(const video::ITexture* texture, |
2045 | const core::position2d<s32>& pos, | 2045 | const core::position2d<s32>& pos, |
2046 | const core::rect<s32>& sourceRect, | 2046 | const core::rect<s32>& sourceRect, |
2047 | const core::rect<s32>* clipRect, SColor color, | 2047 | const core::rect<s32>* clipRect, SColor color, |
2048 | bool useAlphaChannelOfTexture) | 2048 | bool useAlphaChannelOfTexture) |
2049 | { | 2049 | { |
2050 | if (!texture) | 2050 | if (!texture) |
2051 | return; | 2051 | return; |
2052 | 2052 | ||
2053 | if (!sourceRect.isValid()) | 2053 | if (!sourceRect.isValid()) |
2054 | return; | 2054 | return; |
2055 | 2055 | ||
2056 | core::position2d<s32> targetPos(pos); | 2056 | core::position2d<s32> targetPos(pos); |
2057 | core::position2d<s32> sourcePos(sourceRect.UpperLeftCorner); | 2057 | core::position2d<s32> sourcePos(sourceRect.UpperLeftCorner); |
2058 | // This needs to be signed as it may go negative. | 2058 | // This needs to be signed as it may go negative. |
2059 | core::dimension2d<s32> sourceSize(sourceRect.getSize()); | 2059 | core::dimension2d<s32> sourceSize(sourceRect.getSize()); |
2060 | if (clipRect) | 2060 | if (clipRect) |
2061 | { | 2061 | { |
2062 | if (targetPos.X < clipRect->UpperLeftCorner.X) | 2062 | if (targetPos.X < clipRect->UpperLeftCorner.X) |
2063 | { | 2063 | { |
2064 | sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X; | 2064 | sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X; |
2065 | if (sourceSize.Width <= 0) | 2065 | if (sourceSize.Width <= 0) |
2066 | return; | 2066 | return; |
2067 | 2067 | ||
2068 | sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X; | 2068 | sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X; |
2069 | targetPos.X = clipRect->UpperLeftCorner.X; | 2069 | targetPos.X = clipRect->UpperLeftCorner.X; |
2070 | } | 2070 | } |
2071 | 2071 | ||
2072 | if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X) | 2072 | if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X) |
2073 | { | 2073 | { |
2074 | sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X; | 2074 | sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X; |
2075 | if (sourceSize.Width <= 0) | 2075 | if (sourceSize.Width <= 0) |
2076 | return; | 2076 | return; |
2077 | } | 2077 | } |
2078 | 2078 | ||
2079 | if (targetPos.Y < clipRect->UpperLeftCorner.Y) | 2079 | if (targetPos.Y < clipRect->UpperLeftCorner.Y) |
2080 | { | 2080 | { |
2081 | sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y; | 2081 | sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y; |
2082 | if (sourceSize.Height <= 0) | 2082 | if (sourceSize.Height <= 0) |
2083 | return; | 2083 | return; |
2084 | 2084 | ||
2085 | sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y; | 2085 | sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y; |
2086 | targetPos.Y = clipRect->UpperLeftCorner.Y; | 2086 | targetPos.Y = clipRect->UpperLeftCorner.Y; |
2087 | } | 2087 | } |
2088 | 2088 | ||
2089 | if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y) | 2089 | if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y) |
2090 | { | 2090 | { |
2091 | sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y; | 2091 | sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y; |
2092 | if (sourceSize.Height <= 0) | 2092 | if (sourceSize.Height <= 0) |
2093 | return; | 2093 | return; |
2094 | } | 2094 | } |
2095 | } | 2095 | } |
2096 | 2096 | ||
2097 | // clip these coordinates | 2097 | // clip these coordinates |
2098 | 2098 | ||
2099 | if (targetPos.X<0) | 2099 | if (targetPos.X<0) |
2100 | { | 2100 | { |
2101 | sourceSize.Width += targetPos.X; | 2101 | sourceSize.Width += targetPos.X; |
2102 | if (sourceSize.Width <= 0) | 2102 | if (sourceSize.Width <= 0) |
2103 | return; | 2103 | return; |
2104 | 2104 | ||
2105 | sourcePos.X -= targetPos.X; | 2105 | sourcePos.X -= targetPos.X; |
2106 | targetPos.X = 0; | 2106 | targetPos.X = 0; |
2107 | } | 2107 | } |
2108 | 2108 | ||
2109 | const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize(); | 2109 | const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize(); |
2110 | 2110 | ||
2111 | if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width) | 2111 | if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width) |
2112 | { | 2112 | { |
2113 | sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width; | 2113 | sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width; |
2114 | if (sourceSize.Width <= 0) | 2114 | if (sourceSize.Width <= 0) |
2115 | return; | 2115 | return; |
2116 | } | 2116 | } |
2117 | 2117 | ||
2118 | if (targetPos.Y<0) | 2118 | if (targetPos.Y<0) |
2119 | { | 2119 | { |
2120 | sourceSize.Height += targetPos.Y; | 2120 | sourceSize.Height += targetPos.Y; |
2121 | if (sourceSize.Height <= 0) | 2121 | if (sourceSize.Height <= 0) |
2122 | return; | 2122 | return; |
2123 | 2123 | ||
2124 | sourcePos.Y -= targetPos.Y; | 2124 | sourcePos.Y -= targetPos.Y; |
2125 | targetPos.Y = 0; | 2125 | targetPos.Y = 0; |
2126 | } | 2126 | } |
2127 | 2127 | ||
2128 | if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height) | 2128 | if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height) |
2129 | { | 2129 | { |
2130 | sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height; | 2130 | sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height; |
2131 | if (sourceSize.Height <= 0) | 2131 | if (sourceSize.Height <= 0) |
2132 | return; | 2132 | return; |
2133 | } | 2133 | } |
2134 | 2134 | ||
2135 | // ok, we've clipped everything. | 2135 | // ok, we've clipped everything. |
2136 | // now draw it. | 2136 | // now draw it. |
2137 | 2137 | ||
2138 | const core::dimension2d<u32>& ss = texture->getOriginalSize(); | 2138 | const core::dimension2d<u32>& ss = texture->getOriginalSize(); |
2139 | const f32 invW = 1.f / static_cast<f32>(ss.Width); | 2139 | const f32 invW = 1.f / static_cast<f32>(ss.Width); |
2140 | const f32 invH = 1.f / static_cast<f32>(ss.Height); | 2140 | const f32 invH = 1.f / static_cast<f32>(ss.Height); |
2141 | const core::rect<f32> tcoords( | 2141 | const core::rect<f32> tcoords( |
2142 | sourcePos.X * invW, | 2142 | sourcePos.X * invW, |
2143 | sourcePos.Y * invH, | 2143 | sourcePos.Y * invH, |
2144 | (sourcePos.X + sourceSize.Width) * invW, | 2144 | (sourcePos.X + sourceSize.Width) * invW, |
2145 | (sourcePos.Y + sourceSize.Height) * invH); | 2145 | (sourcePos.Y + sourceSize.Height) * invH); |
2146 | 2146 | ||
2147 | const core::rect<s32> poss(targetPos, sourceSize); | 2147 | const core::rect<s32> poss(targetPos, sourceSize); |
2148 | 2148 | ||
2149 | disableTextures(1); | 2149 | disableTextures(1); |
2150 | if (!setActiveTexture(0, texture)) | 2150 | if (!setActiveTexture(0, texture)) |
2151 | return; | 2151 | return; |
2152 | setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); | 2152 | setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); |
2153 | 2153 | ||
2154 | glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); | 2154 | glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); |
2155 | glBegin(GL_QUADS); | 2155 | glBegin(GL_QUADS); |
2156 | 2156 | ||
2157 | glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); | 2157 | glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); |
2158 | glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.UpperLeftCorner.Y)); | 2158 | glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.UpperLeftCorner.Y)); |
2159 | 2159 | ||
2160 | glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); | 2160 | glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); |
2161 | glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.UpperLeftCorner.Y)); | 2161 | glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.UpperLeftCorner.Y)); |
2162 | 2162 | ||
2163 | glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); | 2163 | glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); |
2164 | glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.LowerRightCorner.Y)); | 2164 | glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.LowerRightCorner.Y)); |
2165 | 2165 | ||
2166 | glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); | 2166 | glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); |
2167 | glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.LowerRightCorner.Y)); | 2167 | glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.LowerRightCorner.Y)); |
2168 | 2168 | ||
2169 | glEnd(); | 2169 | glEnd(); |
2170 | } | 2170 | } |
2171 | 2171 | ||
2172 | 2172 | ||
2173 | //! The same, but with a four element array of colors, one for each vertex | 2173 | //! The same, but with a four element array of colors, one for each vertex |
2174 | void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect, | 2174 | void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect, |
2175 | const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect, | 2175 | const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect, |
2176 | const video::SColor* const colors, bool useAlphaChannelOfTexture) | 2176 | const video::SColor* const colors, bool useAlphaChannelOfTexture) |
2177 | { | 2177 | { |
2178 | if (!texture) | 2178 | if (!texture) |
2179 | return; | 2179 | return; |
2180 | 2180 | ||
2181 | const core::dimension2d<u32>& ss = texture->getOriginalSize(); | 2181 | const core::dimension2d<u32>& ss = texture->getOriginalSize(); |
2182 | const f32 invW = 1.f / static_cast<f32>(ss.Width); | 2182 | const f32 invW = 1.f / static_cast<f32>(ss.Width); |
2183 | const f32 invH = 1.f / static_cast<f32>(ss.Height); | 2183 | const f32 invH = 1.f / static_cast<f32>(ss.Height); |
2184 | const core::rect<f32> tcoords( | 2184 | const core::rect<f32> tcoords( |
2185 | sourceRect.UpperLeftCorner.X * invW, | 2185 | sourceRect.UpperLeftCorner.X * invW, |
2186 | sourceRect.UpperLeftCorner.Y * invH, | 2186 | sourceRect.UpperLeftCorner.Y * invH, |
2187 | sourceRect.LowerRightCorner.X * invW, | 2187 | sourceRect.LowerRightCorner.X * invW, |
2188 | sourceRect.LowerRightCorner.Y *invH); | 2188 | sourceRect.LowerRightCorner.Y *invH); |
2189 | 2189 | ||
2190 | const video::SColor temp[4] = | 2190 | const video::SColor temp[4] = |
2191 | { | 2191 | { |
2192 | 0xFFFFFFFF, | 2192 | 0xFFFFFFFF, |
2193 | 0xFFFFFFFF, | 2193 | 0xFFFFFFFF, |
2194 | 0xFFFFFFFF, | 2194 | 0xFFFFFFFF, |
2195 | 0xFFFFFFFF | 2195 | 0xFFFFFFFF |
2196 | }; | 2196 | }; |
2197 | 2197 | ||
2198 | const video::SColor* const useColor = colors ? colors : temp; | 2198 | const video::SColor* const useColor = colors ? colors : temp; |
2199 | 2199 | ||
2200 | disableTextures(1); | 2200 | disableTextures(1); |
2201 | setActiveTexture(0, texture); | 2201 | setActiveTexture(0, texture); |
2202 | setRenderStates2DMode(useColor[0].getAlpha()<255 || useColor[1].getAlpha()<255 || | 2202 | setRenderStates2DMode(useColor[0].getAlpha()<255 || useColor[1].getAlpha()<255 || |
2203 | useColor[2].getAlpha()<255 || useColor[3].getAlpha()<255, | 2203 | useColor[2].getAlpha()<255 || useColor[3].getAlpha()<255, |
2204 | true, useAlphaChannelOfTexture); | 2204 | true, useAlphaChannelOfTexture); |
2205 | 2205 | ||
2206 | if (clipRect) | 2206 | if (clipRect) |
2207 | { | 2207 | { |
2208 | if (!clipRect->isValid()) | 2208 | if (!clipRect->isValid()) |
2209 | return; | 2209 | return; |
2210 | 2210 | ||
2211 | glEnable(GL_SCISSOR_TEST); | 2211 | glEnable(GL_SCISSOR_TEST); |
2212 | const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize(); | 2212 | const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize(); |
2213 | glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height-clipRect->LowerRightCorner.Y, | 2213 | glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height-clipRect->LowerRightCorner.Y, |
2214 | clipRect->getWidth(), clipRect->getHeight()); | 2214 | clipRect->getWidth(), clipRect->getHeight()); |
2215 | } | 2215 | } |
2216 | 2216 | ||
2217 | glBegin(GL_QUADS); | 2217 | glBegin(GL_QUADS); |
2218 | 2218 | ||
2219 | glColor4ub(useColor[0].getRed(), useColor[0].getGreen(), useColor[0].getBlue(), useColor[0].getAlpha()); | 2219 | glColor4ub(useColor[0].getRed(), useColor[0].getGreen(), useColor[0].getBlue(), useColor[0].getAlpha()); |
2220 | glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); | 2220 | glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); |
2221 | glVertex2f(GLfloat(destRect.UpperLeftCorner.X), GLfloat(destRect.UpperLeftCorner.Y)); | 2221 | glVertex2f(GLfloat(destRect.UpperLeftCorner.X), GLfloat(destRect.UpperLeftCorner.Y)); |
2222 | 2222 | ||
2223 | glColor4ub(useColor[3].getRed(), useColor[3].getGreen(), useColor[3].getBlue(), useColor[3].getAlpha()); | 2223 | glColor4ub(useColor[3].getRed(), useColor[3].getGreen(), useColor[3].getBlue(), useColor[3].getAlpha()); |
2224 | glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); | 2224 | glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); |
2225 | glVertex2f(GLfloat(destRect.LowerRightCorner.X), GLfloat(destRect.UpperLeftCorner.Y)); | 2225 | glVertex2f(GLfloat(destRect.LowerRightCorner.X), GLfloat(destRect.UpperLeftCorner.Y)); |
2226 | 2226 | ||
2227 | glColor4ub(useColor[2].getRed(), useColor[2].getGreen(), useColor[2].getBlue(), useColor[2].getAlpha()); | 2227 | glColor4ub(useColor[2].getRed(), useColor[2].getGreen(), useColor[2].getBlue(), useColor[2].getAlpha()); |
2228 | glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); | 2228 | glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); |
2229 | glVertex2f(GLfloat(destRect.LowerRightCorner.X), GLfloat(destRect.LowerRightCorner.Y)); | 2229 | glVertex2f(GLfloat(destRect.LowerRightCorner.X), GLfloat(destRect.LowerRightCorner.Y)); |
2230 | 2230 | ||
2231 | glColor4ub(useColor[1].getRed(), useColor[1].getGreen(), useColor[1].getBlue(), useColor[1].getAlpha()); | 2231 | glColor4ub(useColor[1].getRed(), useColor[1].getGreen(), useColor[1].getBlue(), useColor[1].getAlpha()); |
2232 | glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); | 2232 | glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); |
2233 | glVertex2f(GLfloat(destRect.UpperLeftCorner.X), GLfloat(destRect.LowerRightCorner.Y)); | 2233 | glVertex2f(GLfloat(destRect.UpperLeftCorner.X), GLfloat(destRect.LowerRightCorner.Y)); |
2234 | 2234 | ||
2235 | glEnd(); | 2235 | glEnd(); |
2236 | 2236 | ||
2237 | if (clipRect) | 2237 | if (clipRect) |
2238 | glDisable(GL_SCISSOR_TEST); | 2238 | glDisable(GL_SCISSOR_TEST); |
2239 | } | 2239 | } |
2240 | 2240 | ||
2241 | 2241 | ||
2242 | //! draws a set of 2d images, using a color and the alpha channel of the | 2242 | //! draws a set of 2d images, using a color and the alpha channel of the |
2243 | //! texture if desired. The images are drawn beginning at pos and concatenated | 2243 | //! texture if desired. The images are drawn beginning at pos and concatenated |
2244 | //! in one line. All drawings are clipped against clipRect (if != 0). | 2244 | //! in one line. All drawings are clipped against clipRect (if != 0). |
2245 | //! The subtextures are defined by the array of sourceRects and are chosen | 2245 | //! The subtextures are defined by the array of sourceRects and are chosen |
2246 | //! by the indices given. | 2246 | //! by the indices given. |
2247 | void COpenGLDriver::draw2DImage(const video::ITexture* texture, | 2247 | void COpenGLDriver::draw2DImage(const video::ITexture* texture, |
2248 | const core::position2d<s32>& pos, | 2248 | const core::position2d<s32>& pos, |
2249 | const core::array<core::rect<s32> >& sourceRects, | 2249 | const core::array<core::rect<s32> >& sourceRects, |
2250 | const core::array<s32>& indices, | 2250 | const core::array<s32>& indices, |
2251 | const core::rect<s32>* clipRect, SColor color, | 2251 | const core::rect<s32>* clipRect, SColor color, |
2252 | bool useAlphaChannelOfTexture) | 2252 | bool useAlphaChannelOfTexture) |
2253 | { | 2253 | { |
2254 | if (!texture) | 2254 | if (!texture) |
2255 | return; | 2255 | return; |
2256 | 2256 | ||
2257 | disableTextures(1); | 2257 | disableTextures(1); |
2258 | if (!setActiveTexture(0, texture)) | 2258 | if (!setActiveTexture(0, texture)) |
2259 | return; | 2259 | return; |
2260 | setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); | 2260 | setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); |
2261 | 2261 | ||
2262 | glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); | 2262 | glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); |
2263 | if (clipRect) | 2263 | if (clipRect) |
2264 | { | 2264 | { |
2265 | if (!clipRect->isValid()) | 2265 | if (!clipRect->isValid()) |
2266 | return; | 2266 | return; |
2267 | 2267 | ||
2268 | glEnable(GL_SCISSOR_TEST); | 2268 | glEnable(GL_SCISSOR_TEST); |
2269 | const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize(); | 2269 | const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize(); |
2270 | glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height-clipRect->LowerRightCorner.Y, | 2270 | glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height-clipRect->LowerRightCorner.Y, |
2271 | clipRect->getWidth(),clipRect->getHeight()); | 2271 | clipRect->getWidth(),clipRect->getHeight()); |
2272 | } | 2272 | } |
2273 | 2273 | ||
2274 | const core::dimension2d<u32>& ss = texture->getOriginalSize(); | 2274 | const core::dimension2d<u32>& ss = texture->getOriginalSize(); |
2275 | core::position2d<s32> targetPos(pos); | 2275 | core::position2d<s32> targetPos(pos); |
2276 | const f32 invW = 1.f / static_cast<f32>(ss.Width); | 2276 | const f32 invW = 1.f / static_cast<f32>(ss.Width); |
2277 | const f32 invH = 1.f / static_cast<f32>(ss.Height); | 2277 | const f32 invH = 1.f / static_cast<f32>(ss.Height); |
2278 | 2278 | ||
2279 | for (u32 i=0; i<indices.size(); ++i) | 2279 | for (u32 i=0; i<indices.size(); ++i) |
2280 | { | 2280 | { |
2281 | const s32 currentIndex = indices[i]; | 2281 | const s32 currentIndex = indices[i]; |
2282 | if (!sourceRects[currentIndex].isValid()) | 2282 | if (!sourceRects[currentIndex].isValid()) |
2283 | break; | 2283 | break; |
2284 | 2284 | ||
2285 | const core::rect<f32> tcoords( | 2285 | const core::rect<f32> tcoords( |
2286 | sourceRects[currentIndex].UpperLeftCorner.X * invW, | 2286 | sourceRects[currentIndex].UpperLeftCorner.X * invW, |
2287 | sourceRects[currentIndex].UpperLeftCorner.Y * invH, | 2287 | sourceRects[currentIndex].UpperLeftCorner.Y * invH, |
2288 | sourceRects[currentIndex].LowerRightCorner.X * invW, | 2288 | sourceRects[currentIndex].LowerRightCorner.X * invW, |
2289 | sourceRects[currentIndex].LowerRightCorner.Y * invH); | 2289 | sourceRects[currentIndex].LowerRightCorner.Y * invH); |
2290 | 2290 | ||
2291 | const core::rect<s32> poss(targetPos, sourceRects[currentIndex].getSize()); | 2291 | const core::rect<s32> poss(targetPos, sourceRects[currentIndex].getSize()); |
2292 | 2292 | ||
2293 | glBegin(GL_QUADS); | 2293 | glBegin(GL_QUADS); |
2294 | 2294 | ||
2295 | glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); | 2295 | glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); |
2296 | glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.UpperLeftCorner.Y)); | 2296 | glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.UpperLeftCorner.Y)); |
2297 | 2297 | ||
2298 | glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); | 2298 | glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); |
2299 | glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.UpperLeftCorner.Y)); | 2299 | glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.UpperLeftCorner.Y)); |
2300 | 2300 | ||
2301 | glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); | 2301 | glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); |
2302 | glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.LowerRightCorner.Y)); | 2302 | glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.LowerRightCorner.Y)); |
2303 | 2303 | ||
2304 | glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); | 2304 | glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); |
2305 | glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.LowerRightCorner.Y)); | 2305 | glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.LowerRightCorner.Y)); |
2306 | 2306 | ||
2307 | glEnd(); | 2307 | glEnd(); |
2308 | targetPos.X += sourceRects[currentIndex].getWidth(); | 2308 | targetPos.X += sourceRects[currentIndex].getWidth(); |
2309 | } | 2309 | } |
2310 | if (clipRect) | 2310 | if (clipRect) |
2311 | glDisable(GL_SCISSOR_TEST); | 2311 | glDisable(GL_SCISSOR_TEST); |
2312 | } | 2312 | } |
2313 | 2313 | ||
2314 | 2314 | ||
2315 | //! draw a 2d rectangle | 2315 | //! draw a 2d rectangle |
2316 | void COpenGLDriver::draw2DRectangle(SColor color, const core::rect<s32>& position, | 2316 | void COpenGLDriver::draw2DRectangle(SColor color, const core::rect<s32>& position, |
2317 | const core::rect<s32>* clip) | 2317 | const core::rect<s32>* clip) |
2318 | { | 2318 | { |
2319 | disableTextures(); | 2319 | disableTextures(); |
2320 | setRenderStates2DMode(color.getAlpha() < 255, false, false); | 2320 | setRenderStates2DMode(color.getAlpha() < 255, false, false); |
2321 | 2321 | ||
2322 | core::rect<s32> pos = position; | 2322 | core::rect<s32> pos = position; |
2323 | 2323 | ||
2324 | if (clip) | 2324 | if (clip) |
2325 | pos.clipAgainst(*clip); | 2325 | pos.clipAgainst(*clip); |
2326 | 2326 | ||
2327 | if (!pos.isValid()) | 2327 | if (!pos.isValid()) |
2328 | return; | 2328 | return; |
2329 | 2329 | ||
2330 | glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); | 2330 | glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); |
2331 | glRectf(GLfloat(pos.UpperLeftCorner.X), GLfloat(pos.UpperLeftCorner.Y), | 2331 | glRectf(GLfloat(pos.UpperLeftCorner.X), GLfloat(pos.UpperLeftCorner.Y), |
2332 | GLfloat(pos.LowerRightCorner.X), GLfloat(pos.LowerRightCorner.Y)); | 2332 | GLfloat(pos.LowerRightCorner.X), GLfloat(pos.LowerRightCorner.Y)); |
2333 | } | 2333 | } |
2334 | 2334 | ||
2335 | 2335 | ||
2336 | //! draw an 2d rectangle | 2336 | //! draw an 2d rectangle |
2337 | void COpenGLDriver::draw2DRectangle(const core::rect<s32>& position, | 2337 | void COpenGLDriver::draw2DRectangle(const core::rect<s32>& position, |
2338 | SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, | 2338 | SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, |
2339 | const core::rect<s32>* clip) | 2339 | const core::rect<s32>* clip) |
2340 | { | 2340 | { |
2341 | core::rect<s32> pos = position; | 2341 | core::rect<s32> pos = position; |
2342 | 2342 | ||
2343 | if (clip) | 2343 | if (clip) |
2344 | pos.clipAgainst(*clip); | 2344 | pos.clipAgainst(*clip); |
2345 | 2345 | ||
2346 | if (!pos.isValid()) | 2346 | if (!pos.isValid()) |
2347 | return; | 2347 | return; |
2348 | 2348 | ||
2349 | disableTextures(); | 2349 | disableTextures(); |
2350 | 2350 | ||
2351 | setRenderStates2DMode(colorLeftUp.getAlpha() < 255 || | 2351 | setRenderStates2DMode(colorLeftUp.getAlpha() < 255 || |
2352 | colorRightUp.getAlpha() < 255 || | 2352 | colorRightUp.getAlpha() < 255 || |
2353 | colorLeftDown.getAlpha() < 255 || | 2353 | colorLeftDown.getAlpha() < 255 || |
2354 | colorRightDown.getAlpha() < 255, false, false); | 2354 | colorRightDown.getAlpha() < 255, false, false); |
2355 | 2355 | ||
2356 | glBegin(GL_QUADS); | 2356 | glBegin(GL_QUADS); |
2357 | glColor4ub(colorLeftUp.getRed(), colorLeftUp.getGreen(), | 2357 | glColor4ub(colorLeftUp.getRed(), colorLeftUp.getGreen(), |
2358 | colorLeftUp.getBlue(), colorLeftUp.getAlpha()); | 2358 | colorLeftUp.getBlue(), colorLeftUp.getAlpha()); |
2359 | glVertex2f(GLfloat(pos.UpperLeftCorner.X), GLfloat(pos.UpperLeftCorner.Y)); | 2359 | glVertex2f(GLfloat(pos.UpperLeftCorner.X), GLfloat(pos.UpperLeftCorner.Y)); |
2360 | 2360 | ||
2361 | glColor4ub(colorRightUp.getRed(), colorRightUp.getGreen(), | 2361 | glColor4ub(colorRightUp.getRed(), colorRightUp.getGreen(), |
2362 | colorRightUp.getBlue(), colorRightUp.getAlpha()); | 2362 | colorRightUp.getBlue(), colorRightUp.getAlpha()); |
2363 | glVertex2f(GLfloat(pos.LowerRightCorner.X), GLfloat(pos.UpperLeftCorner.Y)); | 2363 | glVertex2f(GLfloat(pos.LowerRightCorner.X), GLfloat(pos.UpperLeftCorner.Y)); |
2364 | 2364 | ||
2365 | glColor4ub(colorRightDown.getRed(), colorRightDown.getGreen(), | 2365 | glColor4ub(colorRightDown.getRed(), colorRightDown.getGreen(), |
2366 | colorRightDown.getBlue(), colorRightDown.getAlpha()); | 2366 | colorRightDown.getBlue(), colorRightDown.getAlpha()); |
2367 | glVertex2f(GLfloat(pos.LowerRightCorner.X), GLfloat(pos.LowerRightCorner.Y)); | 2367 | glVertex2f(GLfloat(pos.LowerRightCorner.X), GLfloat(pos.LowerRightCorner.Y)); |
2368 | 2368 | ||
2369 | glColor4ub(colorLeftDown.getRed(), colorLeftDown.getGreen(), | 2369 | glColor4ub(colorLeftDown.getRed(), colorLeftDown.getGreen(), |
2370 | colorLeftDown.getBlue(), colorLeftDown.getAlpha()); | 2370 | colorLeftDown.getBlue(), colorLeftDown.getAlpha()); |
2371 | glVertex2f(GLfloat(pos.UpperLeftCorner.X), GLfloat(pos.LowerRightCorner.Y)); | 2371 | glVertex2f(GLfloat(pos.UpperLeftCorner.X), GLfloat(pos.LowerRightCorner.Y)); |
2372 | 2372 | ||
2373 | glEnd(); | 2373 | glEnd(); |
2374 | } | 2374 | } |
2375 | 2375 | ||
2376 | 2376 | ||
2377 | //! Draws a 2d line. | 2377 | //! Draws a 2d line. |
2378 | void COpenGLDriver::draw2DLine(const core::position2d<s32>& start, | 2378 | void COpenGLDriver::draw2DLine(const core::position2d<s32>& start, |
2379 | const core::position2d<s32>& end, SColor color) | 2379 | const core::position2d<s32>& end, SColor color) |
2380 | { | 2380 | { |
2381 | if (start==end) | 2381 | if (start==end) |
2382 | drawPixel(start.X, start.Y, color); | 2382 | drawPixel(start.X, start.Y, color); |
2383 | else | 2383 | else |
2384 | { | 2384 | { |
2385 | disableTextures(); | 2385 | disableTextures(); |
2386 | setRenderStates2DMode(color.getAlpha() < 255, false, false); | 2386 | setRenderStates2DMode(color.getAlpha() < 255, false, false); |
2387 | 2387 | ||
2388 | glBegin(GL_LINES); | 2388 | glBegin(GL_LINES); |
2389 | glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); | 2389 | glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); |
2390 | GLfloat x=(GLfloat)start.X; | 2390 | GLfloat x=(GLfloat)start.X; |
2391 | GLfloat y=(GLfloat)start.Y; | 2391 | GLfloat y=(GLfloat)start.Y; |
2392 | if (x>end.X) | 2392 | if (x>end.X) |
2393 | x += 0.5f; | 2393 | x += 0.5f; |
2394 | if (y>end.Y) | 2394 | if (y>end.Y) |
2395 | y += 0.5f; | 2395 | y += 0.5f; |
2396 | glVertex2f(GLfloat(x), GLfloat(y)); | 2396 | glVertex2f(GLfloat(x), GLfloat(y)); |
2397 | x=(GLfloat)end.X; | 2397 | x=(GLfloat)end.X; |
2398 | y=(GLfloat)end.Y; | 2398 | y=(GLfloat)end.Y; |
2399 | if (x>start.X) | 2399 | if (x>start.X) |
2400 | x += 0.5f; | 2400 | x += 0.5f; |
2401 | if (y>start.Y) | 2401 | if (y>start.Y) |
2402 | y += 0.5f; | 2402 | y += 0.5f; |
2403 | glVertex2f(GLfloat(x), GLfloat(y)); | 2403 | glVertex2f(GLfloat(x), GLfloat(y)); |
2404 | glEnd(); | 2404 | glEnd(); |
2405 | } | 2405 | } |
2406 | } | 2406 | } |
2407 | 2407 | ||
2408 | //! Draws a pixel | 2408 | //! Draws a pixel |
2409 | void COpenGLDriver::drawPixel(u32 x, u32 y, const SColor &color) | 2409 | void COpenGLDriver::drawPixel(u32 x, u32 y, const SColor &color) |
2410 | { | 2410 | { |
2411 | const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize(); | 2411 | const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize(); |
2412 | if (x > (u32)renderTargetSize.Width || y > (u32)renderTargetSize.Height) | 2412 | if (x > (u32)renderTargetSize.Width || y > (u32)renderTargetSize.Height) |
2413 | return; | 2413 | return; |
2414 | 2414 | ||
2415 | disableTextures(); | 2415 | disableTextures(); |
2416 | setRenderStates2DMode(color.getAlpha() < 255, false, false); | 2416 | setRenderStates2DMode(color.getAlpha() < 255, false, false); |
2417 | 2417 | ||
2418 | glBegin(GL_POINTS); | 2418 | glBegin(GL_POINTS); |
2419 | glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); | 2419 | glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); |
2420 | glVertex2i(x, y); | 2420 | glVertex2i(x, y); |
2421 | glEnd(); | 2421 | glEnd(); |
2422 | } | 2422 | } |
2423 | 2423 | ||
2424 | bool COpenGLDriver::setActiveTexture(u32 stage, const video::ITexture* texture) | 2424 | bool COpenGLDriver::setActiveTexture(u32 stage, const video::ITexture* texture) |
2425 | { | 2425 | { |
2426 | if (stage >= MaxSupportedTextures) | 2426 | if (stage >= MaxSupportedTextures) |
2427 | return false; | 2427 | return false; |
2428 | 2428 | ||
2429 | if (CurrentTexture[stage]==texture) | 2429 | if (CurrentTexture[stage]==texture) |
2430 | return true; | 2430 | return true; |
2431 | 2431 | ||
2432 | if (MultiTextureExtension) | 2432 | if (MultiTextureExtension) |
2433 | extGlActiveTexture(GL_TEXTURE0_ARB + stage); | 2433 | extGlActiveTexture(GL_TEXTURE0_ARB + stage); |
2434 | 2434 | ||
2435 | CurrentTexture.set(stage,texture); | 2435 | CurrentTexture.set(stage,texture); |
2436 | 2436 | ||
2437 | if (!texture) | 2437 | if (!texture) |
2438 | { | 2438 | { |
2439 | glDisable(GL_TEXTURE_2D); | 2439 | glDisable(GL_TEXTURE_2D); |
2440 | return true; | 2440 | return true; |
2441 | } | 2441 | } |
2442 | else | 2442 | else |
2443 | { | 2443 | { |
2444 | if (texture->getDriverType() != EDT_OPENGL) | 2444 | if (texture->getDriverType() != EDT_OPENGL) |
2445 | { | 2445 | { |
2446 | glDisable(GL_TEXTURE_2D); | 2446 | glDisable(GL_TEXTURE_2D); |
2447 | CurrentTexture.set(stage, 0); | 2447 | CurrentTexture.set(stage, 0); |
2448 | os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); | 2448 | os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); |
2449 | return false; | 2449 | return false; |
2450 | } | 2450 | } |
2451 | 2451 | ||
2452 | glEnable(GL_TEXTURE_2D); | 2452 | glEnable(GL_TEXTURE_2D); |
2453 | glBindTexture(GL_TEXTURE_2D, | 2453 | glBindTexture(GL_TEXTURE_2D, |
2454 | static_cast<const COpenGLTexture*>(texture)->getOpenGLTextureName()); | 2454 | static_cast<const COpenGLTexture*>(texture)->getOpenGLTextureName()); |
2455 | } | 2455 | } |
2456 | return true; | 2456 | return true; |
2457 | } | 2457 | } |
2458 | 2458 | ||
2459 | 2459 | ||
2460 | //! disables all textures beginning with the optional fromStage parameter. Otherwise all texture stages are disabled. | 2460 | //! disables all textures beginning with the optional fromStage parameter. Otherwise all texture stages are disabled. |
2461 | //! Returns whether disabling was successful or not. | 2461 | //! Returns whether disabling was successful or not. |
2462 | bool COpenGLDriver::disableTextures(u32 fromStage) | 2462 | bool COpenGLDriver::disableTextures(u32 fromStage) |
2463 | { | 2463 | { |
2464 | bool result=true; | 2464 | bool result=true; |
2465 | for (u32 i=fromStage; i<MaxSupportedTextures; ++i) | 2465 | for (u32 i=fromStage; i<MaxSupportedTextures; ++i) |
2466 | result &= setActiveTexture(i, 0); | 2466 | result &= setActiveTexture(i, 0); |
2467 | return result; | 2467 | return result; |
2468 | } | 2468 | } |
2469 | 2469 | ||
2470 | 2470 | ||
2471 | //! creates a matrix in supplied GLfloat array to pass to OpenGL | 2471 | //! creates a matrix in supplied GLfloat array to pass to OpenGL |
2472 | inline void COpenGLDriver::getGLMatrix(GLfloat gl_matrix[16], const core::matrix4& m) | 2472 | inline void COpenGLDriver::getGLMatrix(GLfloat gl_matrix[16], const core::matrix4& m) |
2473 | { | 2473 | { |
2474 | memcpy(gl_matrix, m.pointer(), 16 * sizeof(f32)); | 2474 | memcpy(gl_matrix, m.pointer(), 16 * sizeof(f32)); |
2475 | } | 2475 | } |
2476 | 2476 | ||
2477 | 2477 | ||
2478 | //! creates a opengltexturematrix from a D3D style texture matrix | 2478 | //! creates a opengltexturematrix from a D3D style texture matrix |
2479 | inline void COpenGLDriver::getGLTextureMatrix(GLfloat *o, const core::matrix4& m) | 2479 | inline void COpenGLDriver::getGLTextureMatrix(GLfloat *o, const core::matrix4& m) |
2480 | { | 2480 | { |
2481 | o[0] = m[0]; | 2481 | o[0] = m[0]; |
2482 | o[1] = m[1]; | 2482 | o[1] = m[1]; |
2483 | o[2] = 0.f; | 2483 | o[2] = 0.f; |
2484 | o[3] = 0.f; | 2484 | o[3] = 0.f; |
2485 | 2485 | ||
2486 | o[4] = m[4]; | 2486 | o[4] = m[4]; |
2487 | o[5] = m[5]; | 2487 | o[5] = m[5]; |
2488 | o[6] = 0.f; | 2488 | o[6] = 0.f; |
2489 | o[7] = 0.f; | 2489 | o[7] = 0.f; |
2490 | 2490 | ||
2491 | o[8] = 0.f; | 2491 | o[8] = 0.f; |
2492 | o[9] = 0.f; | 2492 | o[9] = 0.f; |
2493 | o[10] = 1.f; | 2493 | o[10] = 1.f; |
2494 | o[11] = 0.f; | 2494 | o[11] = 0.f; |
2495 | 2495 | ||
2496 | o[12] = m[8]; | 2496 | o[12] = m[8]; |
2497 | o[13] = m[9]; | 2497 | o[13] = m[9]; |
2498 | o[14] = 0.f; | 2498 | o[14] = 0.f; |
2499 | o[15] = 1.f; | 2499 | o[15] = 1.f; |
2500 | } | 2500 | } |
2501 | 2501 | ||
2502 | 2502 | ||
2503 | //! returns a device dependent texture from a software surface (IImage) | 2503 | //! returns a device dependent texture from a software surface (IImage) |
2504 | video::ITexture* COpenGLDriver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData) | 2504 | video::ITexture* COpenGLDriver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData) |
2505 | { | 2505 | { |
2506 | return new COpenGLTexture(surface, name, mipmapData, this); | 2506 | return new COpenGLTexture(surface, name, mipmapData, this); |
2507 | } | 2507 | } |
2508 | 2508 | ||
2509 | 2509 | ||
2510 | //! Sets a material. All 3d drawing functions draw geometry now using this material. | 2510 | //! Sets a material. All 3d drawing functions draw geometry now using this material. |
2511 | void COpenGLDriver::setMaterial(const SMaterial& material) | 2511 | void COpenGLDriver::setMaterial(const SMaterial& material) |
2512 | { | 2512 | { |
2513 | Material = material; | 2513 | Material = material; |
2514 | OverrideMaterial.apply(Material); | 2514 | OverrideMaterial.apply(Material); |
2515 | 2515 | ||
2516 | for (s32 i = MaxTextureUnits-1; i>= 0; --i) | 2516 | for (s32 i = MaxTextureUnits-1; i>= 0; --i) |
2517 | { | 2517 | { |
2518 | setActiveTexture(i, material.getTexture(i)); | 2518 | setActiveTexture(i, material.getTexture(i)); |
2519 | setTransform ((E_TRANSFORMATION_STATE) (ETS_TEXTURE_0 + i), | 2519 | setTransform ((E_TRANSFORMATION_STATE) (ETS_TEXTURE_0 + i), |
2520 | Material.getTextureMatrix(i)); | 2520 | Material.getTextureMatrix(i)); |
2521 | } | 2521 | } |
2522 | } | 2522 | } |
2523 | 2523 | ||
2524 | 2524 | ||
2525 | //! prints error if an error happened. | 2525 | //! prints error if an error happened. |
2526 | bool COpenGLDriver::testGLError() | 2526 | bool COpenGLDriver::testGLError() |
2527 | { | 2527 | { |
2528 | #ifdef _DEBUG | 2528 | #ifdef _DEBUG |
2529 | GLenum g = glGetError(); | 2529 | GLenum g = glGetError(); |
2530 | switch (g) | 2530 | switch (g) |
2531 | { | 2531 | { |
2532 | case GL_NO_ERROR: | 2532 | case GL_NO_ERROR: |
2533 | return false; | 2533 | return false; |
2534 | case GL_INVALID_ENUM: | 2534 | case GL_INVALID_ENUM: |
2535 | os::Printer::log("GL_INVALID_ENUM", ELL_ERROR); break; | 2535 | os::Printer::log("GL_INVALID_ENUM", ELL_ERROR); break; |
2536 | case GL_INVALID_VALUE: | 2536 | case GL_INVALID_VALUE: |
2537 | os::Printer::log("GL_INVALID_VALUE", ELL_ERROR); break; | 2537 | os::Printer::log("GL_INVALID_VALUE", ELL_ERROR); break; |
2538 | case GL_INVALID_OPERATION: | 2538 | case GL_INVALID_OPERATION: |
2539 | os::Printer::log("GL_INVALID_OPERATION", ELL_ERROR); break; | 2539 | os::Printer::log("GL_INVALID_OPERATION", ELL_ERROR); break; |
2540 | case GL_STACK_OVERFLOW: | 2540 | case GL_STACK_OVERFLOW: |
2541 | os::Printer::log("GL_STACK_OVERFLOW", ELL_ERROR); break; | 2541 | os::Printer::log("GL_STACK_OVERFLOW", ELL_ERROR); break; |
2542 | case GL_STACK_UNDERFLOW: | 2542 | case GL_STACK_UNDERFLOW: |
2543 | os::Printer::log("GL_STACK_UNDERFLOW", ELL_ERROR); break; | 2543 | os::Printer::log("GL_STACK_UNDERFLOW", ELL_ERROR); break; |
2544 | case GL_OUT_OF_MEMORY: | 2544 | case GL_OUT_OF_MEMORY: |
2545 | os::Printer::log("GL_OUT_OF_MEMORY", ELL_ERROR); break; | 2545 | os::Printer::log("GL_OUT_OF_MEMORY", ELL_ERROR); break; |
2546 | case GL_TABLE_TOO_LARGE: | 2546 | case GL_TABLE_TOO_LARGE: |
2547 | os::Printer::log("GL_TABLE_TOO_LARGE", ELL_ERROR); break; | 2547 | os::Printer::log("GL_TABLE_TOO_LARGE", ELL_ERROR); break; |
2548 | #if defined(GL_EXT_framebuffer_object) | 2548 | #if defined(GL_EXT_framebuffer_object) |
2549 | case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: | 2549 | case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: |
2550 | os::Printer::log("GL_INVALID_FRAMEBUFFER_OPERATION", ELL_ERROR); break; | 2550 | os::Printer::log("GL_INVALID_FRAMEBUFFER_OPERATION", ELL_ERROR); break; |
2551 | #endif | 2551 | #endif |
2552 | }; | 2552 | }; |
2553 | // _IRR_DEBUG_BREAK_IF(true); | 2553 | // _IRR_DEBUG_BREAK_IF(true); |
2554 | return true; | 2554 | return true; |
2555 | #else | 2555 | #else |
2556 | return false; | 2556 | return false; |
2557 | #endif | 2557 | #endif |
2558 | } | 2558 | } |
2559 | 2559 | ||
2560 | 2560 | ||
2561 | //! sets the needed renderstates | 2561 | //! sets the needed renderstates |
2562 | void COpenGLDriver::setRenderStates3DMode() | 2562 | void COpenGLDriver::setRenderStates3DMode() |
2563 | { | 2563 | { |
2564 | if (CurrentRenderMode != ERM_3D) | 2564 | if (CurrentRenderMode != ERM_3D) |
2565 | { | 2565 | { |
2566 | // Reset Texture Stages | 2566 | // Reset Texture Stages |
2567 | glDisable(GL_BLEND); | 2567 | glDisable(GL_BLEND); |
2568 | glDisable(GL_ALPHA_TEST); | 2568 | glDisable(GL_ALPHA_TEST); |
2569 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 2569 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
2570 | 2570 | ||
2571 | // switch back the matrices | 2571 | // switch back the matrices |
2572 | glMatrixMode(GL_MODELVIEW); | 2572 | glMatrixMode(GL_MODELVIEW); |
2573 | glLoadMatrixf((Matrices[ETS_VIEW] * Matrices[ETS_WORLD]).pointer()); | 2573 | glLoadMatrixf((Matrices[ETS_VIEW] * Matrices[ETS_WORLD]).pointer()); |
2574 | 2574 | ||
2575 | glMatrixMode(GL_PROJECTION); | 2575 | glMatrixMode(GL_PROJECTION); |
2576 | glLoadMatrixf(Matrices[ETS_PROJECTION].pointer()); | 2576 | glLoadMatrixf(Matrices[ETS_PROJECTION].pointer()); |
2577 | 2577 | ||
2578 | ResetRenderStates = true; | 2578 | ResetRenderStates = true; |
2579 | #ifdef GL_EXT_clip_volume_hint | 2579 | #ifdef GL_EXT_clip_volume_hint |
2580 | if (FeatureAvailable[IRR_EXT_clip_volume_hint]) | 2580 | if (FeatureAvailable[IRR_EXT_clip_volume_hint]) |
2581 | glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_NICEST); | 2581 | glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_NICEST); |
2582 | #endif | 2582 | #endif |
2583 | } | 2583 | } |
2584 | 2584 | ||
2585 | if (ResetRenderStates || LastMaterial != Material) | 2585 | if (ResetRenderStates || LastMaterial != Material) |
2586 | { | 2586 | { |
2587 | // unset old material | 2587 | // unset old material |
2588 | 2588 | ||
2589 | if (LastMaterial.MaterialType != Material.MaterialType && | 2589 | if (LastMaterial.MaterialType != Material.MaterialType && |
2590 | static_cast<u32>(LastMaterial.MaterialType) < MaterialRenderers.size()) | 2590 | static_cast<u32>(LastMaterial.MaterialType) < MaterialRenderers.size()) |
2591 | MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); | 2591 | MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); |
2592 | 2592 | ||
2593 | // set new material. | 2593 | // set new material. |
2594 | if (static_cast<u32>(Material.MaterialType) < MaterialRenderers.size()) | 2594 | if (static_cast<u32>(Material.MaterialType) < MaterialRenderers.size()) |
2595 | MaterialRenderers[Material.MaterialType].Renderer->OnSetMaterial( | 2595 | MaterialRenderers[Material.MaterialType].Renderer->OnSetMaterial( |
2596 | Material, LastMaterial, ResetRenderStates, this); | 2596 | Material, LastMaterial, ResetRenderStates, this); |
2597 | 2597 | ||
2598 | LastMaterial = Material; | 2598 | LastMaterial = Material; |
2599 | ResetRenderStates = false; | 2599 | ResetRenderStates = false; |
2600 | } | 2600 | } |
2601 | 2601 | ||
2602 | if (static_cast<u32>(Material.MaterialType) < MaterialRenderers.size()) | 2602 | if (static_cast<u32>(Material.MaterialType) < MaterialRenderers.size()) |
2603 | MaterialRenderers[Material.MaterialType].Renderer->OnRender(this, video::EVT_STANDARD); | 2603 | MaterialRenderers[Material.MaterialType].Renderer->OnRender(this, video::EVT_STANDARD); |
2604 | 2604 | ||
2605 | CurrentRenderMode = ERM_3D; | 2605 | CurrentRenderMode = ERM_3D; |
2606 | } | 2606 | } |
2607 | 2607 | ||
2608 | 2608 | ||
2609 | //! Get native wrap mode value | 2609 | //! Get native wrap mode value |
2610 | GLint COpenGLDriver::getTextureWrapMode(const u8 clamp) | 2610 | GLint COpenGLDriver::getTextureWrapMode(const u8 clamp) |
2611 | { | 2611 | { |
2612 | GLint mode=GL_REPEAT; | 2612 | GLint mode=GL_REPEAT; |
2613 | switch (clamp) | 2613 | switch (clamp) |
2614 | { | 2614 | { |
2615 | case ETC_REPEAT: | 2615 | case ETC_REPEAT: |
2616 | mode=GL_REPEAT; | 2616 | mode=GL_REPEAT; |
2617 | break; | 2617 | break; |
2618 | case ETC_CLAMP: | 2618 | case ETC_CLAMP: |
2619 | mode=GL_CLAMP; | 2619 | mode=GL_CLAMP; |
2620 | break; | 2620 | break; |
2621 | case ETC_CLAMP_TO_EDGE: | 2621 | case ETC_CLAMP_TO_EDGE: |
2622 | #ifdef GL_VERSION_1_2 | 2622 | #ifdef GL_VERSION_1_2 |
2623 | if (Version>101) | 2623 | if (Version>101) |
2624 | mode=GL_CLAMP_TO_EDGE; | 2624 | mode=GL_CLAMP_TO_EDGE; |
2625 | else | 2625 | else |
2626 | #endif | 2626 | #endif |
2627 | #ifdef GL_SGIS_texture_edge_clamp | 2627 | #ifdef GL_SGIS_texture_edge_clamp |
2628 | if (FeatureAvailable[IRR_SGIS_texture_edge_clamp]) | 2628 | if (FeatureAvailable[IRR_SGIS_texture_edge_clamp]) |
2629 | mode=GL_CLAMP_TO_EDGE_SGIS; | 2629 | mode=GL_CLAMP_TO_EDGE_SGIS; |
2630 | else | 2630 | else |
2631 | #endif | 2631 | #endif |
2632 | // fallback | 2632 | // fallback |
2633 | mode=GL_CLAMP; | 2633 | mode=GL_CLAMP; |
2634 | break; | 2634 | break; |
2635 | case ETC_CLAMP_TO_BORDER: | 2635 | case ETC_CLAMP_TO_BORDER: |
2636 | #ifdef GL_VERSION_1_3 | 2636 | #ifdef GL_VERSION_1_3 |
2637 | if (Version>102) | 2637 | if (Version>102) |
2638 | mode=GL_CLAMP_TO_BORDER; | 2638 | mode=GL_CLAMP_TO_BORDER; |
2639 | else | 2639 | else |
2640 | #endif | 2640 | #endif |
2641 | #ifdef GL_ARB_texture_border_clamp | 2641 | #ifdef GL_ARB_texture_border_clamp |
2642 | if (FeatureAvailable[IRR_ARB_texture_border_clamp]) | 2642 | if (FeatureAvailable[IRR_ARB_texture_border_clamp]) |
2643 | mode=GL_CLAMP_TO_BORDER_ARB; | 2643 | mode=GL_CLAMP_TO_BORDER_ARB; |
2644 | else | 2644 | else |
2645 | #endif | 2645 | #endif |
2646 | #ifdef GL_SGIS_texture_border_clamp | 2646 | #ifdef GL_SGIS_texture_border_clamp |
2647 | if (FeatureAvailable[IRR_SGIS_texture_border_clamp]) | 2647 | if (FeatureAvailable[IRR_SGIS_texture_border_clamp]) |
2648 | mode=GL_CLAMP_TO_BORDER_SGIS; | 2648 | mode=GL_CLAMP_TO_BORDER_SGIS; |
2649 | else | 2649 | else |
2650 | #endif | 2650 | #endif |
2651 | // fallback | 2651 | // fallback |
2652 | mode=GL_CLAMP; | 2652 | mode=GL_CLAMP; |
2653 | break; | 2653 | break; |
2654 | case ETC_MIRROR: | 2654 | case ETC_MIRROR: |
2655 | #ifdef GL_VERSION_1_4 | 2655 | #ifdef GL_VERSION_1_4 |
2656 | if (Version>103) | 2656 | if (Version>103) |
2657 | mode=GL_MIRRORED_REPEAT; | 2657 | mode=GL_MIRRORED_REPEAT; |
2658 | else | 2658 | else |
2659 | #endif | 2659 | #endif |
2660 | #ifdef GL_ARB_texture_border_clamp | 2660 | #ifdef GL_ARB_texture_border_clamp |
2661 | if (FeatureAvailable[IRR_ARB_texture_mirrored_repeat]) | 2661 | if (FeatureAvailable[IRR_ARB_texture_mirrored_repeat]) |
2662 | mode=GL_MIRRORED_REPEAT_ARB; | 2662 | mode=GL_MIRRORED_REPEAT_ARB; |
2663 | else | 2663 | else |
2664 | #endif | 2664 | #endif |
2665 | #ifdef GL_IBM_texture_mirrored_repeat | 2665 | #ifdef GL_IBM_texture_mirrored_repeat |
2666 | if (FeatureAvailable[IRR_IBM_texture_mirrored_repeat]) | 2666 | if (FeatureAvailable[IRR_IBM_texture_mirrored_repeat]) |
2667 | mode=GL_MIRRORED_REPEAT_IBM; | 2667 | mode=GL_MIRRORED_REPEAT_IBM; |
2668 | else | 2668 | else |
2669 | #endif | 2669 | #endif |
2670 | mode=GL_REPEAT; | 2670 | mode=GL_REPEAT; |
2671 | break; | 2671 | break; |
2672 | case ETC_MIRROR_CLAMP: | 2672 | case ETC_MIRROR_CLAMP: |
2673 | #ifdef GL_EXT_texture_mirror_clamp | 2673 | #ifdef GL_EXT_texture_mirror_clamp |
2674 | if (FeatureAvailable[IRR_EXT_texture_mirror_clamp]) | 2674 | if (FeatureAvailable[IRR_EXT_texture_mirror_clamp]) |
2675 | mode=GL_MIRROR_CLAMP_EXT; | 2675 | mode=GL_MIRROR_CLAMP_EXT; |
2676 | else | 2676 | else |
2677 | #endif | 2677 | #endif |
2678 | #if defined(GL_ATI_texture_mirror_once) | 2678 | #if defined(GL_ATI_texture_mirror_once) |
2679 | if (FeatureAvailable[IRR_ATI_texture_mirror_once]) | 2679 | if (FeatureAvailable[IRR_ATI_texture_mirror_once]) |
2680 | mode=GL_MIRROR_CLAMP_ATI; | 2680 | mode=GL_MIRROR_CLAMP_ATI; |
2681 | else | 2681 | else |
2682 | #endif | 2682 | #endif |
2683 | mode=GL_CLAMP; | 2683 | mode=GL_CLAMP; |
2684 | break; | 2684 | break; |
2685 | case ETC_MIRROR_CLAMP_TO_EDGE: | 2685 | case ETC_MIRROR_CLAMP_TO_EDGE: |
2686 | #ifdef GL_EXT_texture_mirror_clamp | 2686 | #ifdef GL_EXT_texture_mirror_clamp |
2687 | if (FeatureAvailable[IRR_EXT_texture_mirror_clamp]) | 2687 | if (FeatureAvailable[IRR_EXT_texture_mirror_clamp]) |
2688 | mode=GL_MIRROR_CLAMP_TO_EDGE_EXT; | 2688 | mode=GL_MIRROR_CLAMP_TO_EDGE_EXT; |
2689 | else | 2689 | else |
2690 | #endif | 2690 | #endif |
2691 | #if defined(GL_ATI_texture_mirror_once) | 2691 | #if defined(GL_ATI_texture_mirror_once) |
2692 | if (FeatureAvailable[IRR_ATI_texture_mirror_once]) | 2692 | if (FeatureAvailable[IRR_ATI_texture_mirror_once]) |
2693 | mode=GL_MIRROR_CLAMP_TO_EDGE_ATI; | 2693 | mode=GL_MIRROR_CLAMP_TO_EDGE_ATI; |
2694 | else | 2694 | else |
2695 | #endif | 2695 | #endif |
2696 | mode=GL_CLAMP; | 2696 | mode=GL_CLAMP; |
2697 | break; | 2697 | break; |
2698 | case ETC_MIRROR_CLAMP_TO_BORDER: | 2698 | case ETC_MIRROR_CLAMP_TO_BORDER: |
2699 | #ifdef GL_EXT_texture_mirror_clamp | 2699 | #ifdef GL_EXT_texture_mirror_clamp |
2700 | if (FeatureAvailable[IRR_EXT_texture_mirror_clamp]) | 2700 | if (FeatureAvailable[IRR_EXT_texture_mirror_clamp]) |
2701 | mode=GL_MIRROR_CLAMP_TO_BORDER_EXT; | 2701 | mode=GL_MIRROR_CLAMP_TO_BORDER_EXT; |
2702 | else | 2702 | else |
2703 | #endif | 2703 | #endif |
2704 | mode=GL_CLAMP; | 2704 | mode=GL_CLAMP; |
2705 | break; | 2705 | break; |
2706 | } | 2706 | } |
2707 | return mode; | 2707 | return mode; |
2708 | } | 2708 | } |
2709 | 2709 | ||
2710 | 2710 | ||
2711 | void COpenGLDriver::setWrapMode(const SMaterial& material) | 2711 | void COpenGLDriver::setWrapMode(const SMaterial& material) |
2712 | { | 2712 | { |
2713 | // texture address mode | 2713 | // texture address mode |
2714 | // Has to be checked always because it depends on the textures | 2714 | // Has to be checked always because it depends on the textures |
2715 | for (u32 u=0; u<MaxTextureUnits; ++u) | 2715 | for (u32 u=0; u<MaxTextureUnits; ++u) |
2716 | { | 2716 | { |
2717 | if (!CurrentTexture[u]) | 2717 | if (!CurrentTexture[u]) |
2718 | continue; | 2718 | continue; |
2719 | if (MultiTextureExtension) | 2719 | if (MultiTextureExtension) |
2720 | extGlActiveTexture(GL_TEXTURE0_ARB + u); | 2720 | extGlActiveTexture(GL_TEXTURE0_ARB + u); |
2721 | else if (u>0) | 2721 | else if (u>0) |
2722 | break; // stop loop | 2722 | break; // stop loop |
2723 | 2723 | ||
2724 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getTextureWrapMode(material.TextureLayer[u].TextureWrapU)); | 2724 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getTextureWrapMode(material.TextureLayer[u].TextureWrapU)); |
2725 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getTextureWrapMode(material.TextureLayer[u].TextureWrapV)); | 2725 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getTextureWrapMode(material.TextureLayer[u].TextureWrapV)); |
2726 | } | 2726 | } |
2727 | } | 2727 | } |
2728 | 2728 | ||
2729 | 2729 | ||
2730 | //! Can be called by an IMaterialRenderer to make its work easier. | 2730 | //! Can be called by an IMaterialRenderer to make its work easier. |
2731 | void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, | 2731 | void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, |
2732 | bool resetAllRenderStates) | 2732 | bool resetAllRenderStates) |
2733 | { | 2733 | { |
2734 | if (resetAllRenderStates || | 2734 | if (resetAllRenderStates || |
2735 | lastmaterial.ColorMaterial != material.ColorMaterial) | 2735 | lastmaterial.ColorMaterial != material.ColorMaterial) |
2736 | { | 2736 | { |
2737 | switch (material.ColorMaterial) | 2737 | switch (material.ColorMaterial) |
2738 | { | 2738 | { |
2739 | case ECM_NONE: | 2739 | case ECM_NONE: |
2740 | glDisable(GL_COLOR_MATERIAL); | 2740 | glDisable(GL_COLOR_MATERIAL); |
2741 | break; | 2741 | break; |
2742 | case ECM_DIFFUSE: | 2742 | case ECM_DIFFUSE: |
2743 | glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); | 2743 | glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); |
2744 | break; | 2744 | break; |
2745 | case ECM_AMBIENT: | 2745 | case ECM_AMBIENT: |
2746 | glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT); | 2746 | glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT); |
2747 | break; | 2747 | break; |
2748 | case ECM_EMISSIVE: | 2748 | case ECM_EMISSIVE: |
2749 | glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION); | 2749 | glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION); |
2750 | break; | 2750 | break; |
2751 | case ECM_SPECULAR: | 2751 | case ECM_SPECULAR: |
2752 | glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR); | 2752 | glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR); |
2753 | break; | 2753 | break; |
2754 | case ECM_DIFFUSE_AND_AMBIENT: | 2754 | case ECM_DIFFUSE_AND_AMBIENT: |
2755 | glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); | 2755 | glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); |
2756 | break; | 2756 | break; |
2757 | } | 2757 | } |
2758 | if (material.ColorMaterial != ECM_NONE) | 2758 | if (material.ColorMaterial != ECM_NONE) |
2759 | glEnable(GL_COLOR_MATERIAL); | 2759 | glEnable(GL_COLOR_MATERIAL); |
2760 | } | 2760 | } |
2761 | 2761 | ||
2762 | if (resetAllRenderStates || | 2762 | if (resetAllRenderStates || |
2763 | lastmaterial.AmbientColor != material.AmbientColor || | 2763 | lastmaterial.AmbientColor != material.AmbientColor || |
2764 | lastmaterial.DiffuseColor != material.DiffuseColor || | 2764 | lastmaterial.DiffuseColor != material.DiffuseColor || |
2765 | lastmaterial.EmissiveColor != material.EmissiveColor || | 2765 | lastmaterial.EmissiveColor != material.EmissiveColor || |
2766 | lastmaterial.ColorMaterial != material.ColorMaterial) | 2766 | lastmaterial.ColorMaterial != material.ColorMaterial) |
2767 | { | 2767 | { |
2768 | GLfloat color[4]; | 2768 | GLfloat color[4]; |
2769 | 2769 | ||
2770 | const f32 inv = 1.0f / 255.0f; | 2770 | const f32 inv = 1.0f / 255.0f; |
2771 | 2771 | ||
2772 | if ((material.ColorMaterial != video::ECM_AMBIENT) && | 2772 | if ((material.ColorMaterial != video::ECM_AMBIENT) && |
2773 | (material.ColorMaterial != video::ECM_DIFFUSE_AND_AMBIENT)) | 2773 | (material.ColorMaterial != video::ECM_DIFFUSE_AND_AMBIENT)) |
2774 | { | 2774 | { |
2775 | color[0] = material.AmbientColor.getRed() * inv; | 2775 | color[0] = material.AmbientColor.getRed() * inv; |
2776 | color[1] = material.AmbientColor.getGreen() * inv; | 2776 | color[1] = material.AmbientColor.getGreen() * inv; |
2777 | color[2] = material.AmbientColor.getBlue() * inv; | 2777 | color[2] = material.AmbientColor.getBlue() * inv; |
2778 | color[3] = material.AmbientColor.getAlpha() * inv; | 2778 | color[3] = material.AmbientColor.getAlpha() * inv; |
2779 | glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color); | 2779 | glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color); |
2780 | } | 2780 | } |
2781 | 2781 | ||
2782 | if ((material.ColorMaterial != video::ECM_DIFFUSE) && | 2782 | if ((material.ColorMaterial != video::ECM_DIFFUSE) && |
2783 | (material.ColorMaterial != video::ECM_DIFFUSE_AND_AMBIENT)) | 2783 | (material.ColorMaterial != video::ECM_DIFFUSE_AND_AMBIENT)) |
2784 | { | 2784 | { |
2785 | color[0] = material.DiffuseColor.getRed() * inv; | 2785 | color[0] = material.DiffuseColor.getRed() * inv; |
2786 | color[1] = material.DiffuseColor.getGreen() * inv; | 2786 | color[1] = material.DiffuseColor.getGreen() * inv; |
2787 | color[2] = material.DiffuseColor.getBlue() * inv; | 2787 | color[2] = material.DiffuseColor.getBlue() * inv; |
2788 | color[3] = material.DiffuseColor.getAlpha() * inv; | 2788 | color[3] = material.DiffuseColor.getAlpha() * inv; |
2789 | glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color); | 2789 | glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color); |
2790 | } | 2790 | } |
2791 | 2791 | ||
2792 | if (material.ColorMaterial != video::ECM_EMISSIVE) | 2792 | if (material.ColorMaterial != video::ECM_EMISSIVE) |
2793 | { | 2793 | { |
2794 | color[0] = material.EmissiveColor.getRed() * inv; | 2794 | color[0] = material.EmissiveColor.getRed() * inv; |
2795 | color[1] = material.EmissiveColor.getGreen() * inv; | 2795 | color[1] = material.EmissiveColor.getGreen() * inv; |
2796 | color[2] = material.EmissiveColor.getBlue() * inv; | 2796 | color[2] = material.EmissiveColor.getBlue() * inv; |
2797 | color[3] = material.EmissiveColor.getAlpha() * inv; | 2797 | color[3] = material.EmissiveColor.getAlpha() * inv; |
2798 | glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color); | 2798 | glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color); |
2799 | } | 2799 | } |
2800 | } | 2800 | } |
2801 | 2801 | ||
2802 | if (resetAllRenderStates || | 2802 | if (resetAllRenderStates || |
2803 | lastmaterial.SpecularColor != material.SpecularColor || | 2803 | lastmaterial.SpecularColor != material.SpecularColor || |
2804 | lastmaterial.Shininess != material.Shininess || | 2804 | lastmaterial.Shininess != material.Shininess || |
2805 | lastmaterial.ColorMaterial != material.ColorMaterial) | 2805 | lastmaterial.ColorMaterial != material.ColorMaterial) |
2806 | { | 2806 | { |
2807 | GLfloat color[4]={0.f,0.f,0.f,1.f}; | 2807 | GLfloat color[4]={0.f,0.f,0.f,1.f}; |
2808 | const f32 inv = 1.0f / 255.0f; | 2808 | const f32 inv = 1.0f / 255.0f; |
2809 | 2809 | ||
2810 | glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, material.Shininess); | 2810 | glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, material.Shininess); |
2811 | // disable Specular colors if no shininess is set | 2811 | // disable Specular colors if no shininess is set |
2812 | if ((material.Shininess != 0.0f) && | 2812 | if ((material.Shininess != 0.0f) && |
2813 | (material.ColorMaterial != video::ECM_SPECULAR)) | 2813 | (material.ColorMaterial != video::ECM_SPECULAR)) |
2814 | { | 2814 | { |
2815 | #ifdef GL_EXT_separate_specular_color | 2815 | #ifdef GL_EXT_separate_specular_color |
2816 | if (FeatureAvailable[IRR_EXT_separate_specular_color]) | 2816 | if (FeatureAvailable[IRR_EXT_separate_specular_color]) |
2817 | glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); | 2817 | glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); |
2818 | #endif | 2818 | #endif |
2819 | color[0] = material.SpecularColor.getRed() * inv; | 2819 | color[0] = material.SpecularColor.getRed() * inv; |
2820 | color[1] = material.SpecularColor.getGreen() * inv; | 2820 | color[1] = material.SpecularColor.getGreen() * inv; |
2821 | color[2] = material.SpecularColor.getBlue() * inv; | 2821 | color[2] = material.SpecularColor.getBlue() * inv; |
2822 | color[3] = material.SpecularColor.getAlpha() * inv; | 2822 | color[3] = material.SpecularColor.getAlpha() * inv; |
2823 | } | 2823 | } |
2824 | #ifdef GL_EXT_separate_specular_color | 2824 | #ifdef GL_EXT_separate_specular_color |
2825 | else if (FeatureAvailable[IRR_EXT_separate_specular_color]) | 2825 | else if (FeatureAvailable[IRR_EXT_separate_specular_color]) |
2826 | glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); | 2826 | glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); |
2827 | #endif | 2827 | #endif |
2828 | glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color); | 2828 | glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color); |
2829 | } | 2829 | } |
2830 | 2830 | ||
2831 | // Texture filter | 2831 | // Texture filter |
2832 | // Has to be checked always because it depends on the textures | 2832 | // Has to be checked always because it depends on the textures |
2833 | // Filtering has to be set for each texture layer | 2833 | // Filtering has to be set for each texture layer |
2834 | for (u32 i=0; i<MaxTextureUnits; ++i) | 2834 | for (u32 i=0; i<MaxTextureUnits; ++i) |
2835 | { | 2835 | { |
2836 | if (!CurrentTexture[i]) | 2836 | if (!CurrentTexture[i]) |
2837 | continue; | 2837 | continue; |
2838 | if (MultiTextureExtension) | 2838 | if (MultiTextureExtension) |
2839 | extGlActiveTexture(GL_TEXTURE0_ARB + i); | 2839 | extGlActiveTexture(GL_TEXTURE0_ARB + i); |
2840 | else if (i>0) | 2840 | else if (i>0) |
2841 | break; | 2841 | break; |
2842 | 2842 | ||
2843 | #ifdef GL_EXT_texture_lod_bias | 2843 | #ifdef GL_EXT_texture_lod_bias |
2844 | if (FeatureAvailable[IRR_EXT_texture_lod_bias]) | 2844 | if (FeatureAvailable[IRR_EXT_texture_lod_bias]) |
2845 | { | 2845 | { |
2846 | if (material.TextureLayer[i].LODBias) | 2846 | if (material.TextureLayer[i].LODBias) |
2847 | { | 2847 | { |
2848 | const float tmp = core::clamp(material.TextureLayer[i].LODBias * 0.125f, -MaxTextureLODBias, MaxTextureLODBias); | 2848 | const float tmp = core::clamp(material.TextureLayer[i].LODBias * 0.125f, -MaxTextureLODBias, MaxTextureLODBias); |
2849 | glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, tmp); | 2849 | glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, tmp); |
2850 | } | 2850 | } |
2851 | else | 2851 | else |
2852 | glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0.f); | 2852 | glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0.f); |
2853 | } | 2853 | } |
2854 | #endif | 2854 | #endif |
2855 | 2855 | ||
2856 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, | 2856 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, |
2857 | (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST); | 2857 | (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST); |
2858 | 2858 | ||
2859 | if (material.UseMipMaps && CurrentTexture[i]->hasMipMaps()) | 2859 | if (material.UseMipMaps && CurrentTexture[i]->hasMipMaps()) |
2860 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, | 2860 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, |
2861 | material.TextureLayer[i].TrilinearFilter ? GL_LINEAR_MIPMAP_LINEAR : | 2861 | material.TextureLayer[i].TrilinearFilter ? GL_LINEAR_MIPMAP_LINEAR : |
2862 | material.TextureLayer[i].BilinearFilter ? GL_LINEAR_MIPMAP_NEAREST : | 2862 | material.TextureLayer[i].BilinearFilter ? GL_LINEAR_MIPMAP_NEAREST : |
2863 | GL_NEAREST_MIPMAP_NEAREST); | 2863 | GL_NEAREST_MIPMAP_NEAREST); |
2864 | else | 2864 | else |
2865 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, | 2865 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, |
2866 | (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST); | 2866 | (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST); |
2867 | 2867 | ||
2868 | #ifdef GL_EXT_texture_filter_anisotropic | 2868 | #ifdef GL_EXT_texture_filter_anisotropic |
2869 | if (FeatureAvailable[IRR_EXT_texture_filter_anisotropic]) | 2869 | if (FeatureAvailable[IRR_EXT_texture_filter_anisotropic]) |
2870 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, | 2870 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, |
2871 | material.TextureLayer[i].AnisotropicFilter>1 ? core::min_(MaxAnisotropy, material.TextureLayer[i].AnisotropicFilter) : 1); | 2871 | material.TextureLayer[i].AnisotropicFilter>1 ? core::min_(MaxAnisotropy, material.TextureLayer[i].AnisotropicFilter) : 1); |
2872 | #endif | 2872 | #endif |
2873 | } | 2873 | } |
2874 | 2874 | ||
2875 | // fillmode | 2875 | // fillmode |
2876 | if (resetAllRenderStates || (lastmaterial.Wireframe != material.Wireframe) || (lastmaterial.PointCloud != material.PointCloud)) | 2876 | if (resetAllRenderStates || (lastmaterial.Wireframe != material.Wireframe) || (lastmaterial.PointCloud != material.PointCloud)) |
2877 | glPolygonMode(GL_FRONT_AND_BACK, material.Wireframe ? GL_LINE : material.PointCloud? GL_POINT : GL_FILL); | 2877 | glPolygonMode(GL_FRONT_AND_BACK, material.Wireframe ? GL_LINE : material.PointCloud? GL_POINT : GL_FILL); |
2878 | 2878 | ||
2879 | // shademode | 2879 | // shademode |
2880 | if (resetAllRenderStates || (lastmaterial.GouraudShading != material.GouraudShading)) | 2880 | if (resetAllRenderStates || (lastmaterial.GouraudShading != material.GouraudShading)) |
2881 | { | 2881 | { |
2882 | if (material.GouraudShading) | 2882 | if (material.GouraudShading) |
2883 | glShadeModel(GL_SMOOTH); | 2883 | glShadeModel(GL_SMOOTH); |
2884 | else | 2884 | else |
2885 | glShadeModel(GL_FLAT); | 2885 | glShadeModel(GL_FLAT); |
2886 | } | 2886 | } |
2887 | 2887 | ||
2888 | // lighting | 2888 | // lighting |
2889 | if (resetAllRenderStates || (lastmaterial.Lighting != material.Lighting)) | 2889 | if (resetAllRenderStates || (lastmaterial.Lighting != material.Lighting)) |
2890 | { | 2890 | { |
2891 | if (material.Lighting) | 2891 | if (material.Lighting) |
2892 | glEnable(GL_LIGHTING); | 2892 | glEnable(GL_LIGHTING); |
2893 | else | 2893 | else |
2894 | glDisable(GL_LIGHTING); | 2894 | glDisable(GL_LIGHTING); |
2895 | } | 2895 | } |
2896 | 2896 | ||
2897 | // zbuffer | 2897 | // zbuffer |
2898 | if (resetAllRenderStates || lastmaterial.ZBuffer != material.ZBuffer) | 2898 | if (resetAllRenderStates || lastmaterial.ZBuffer != material.ZBuffer) |
2899 | { | 2899 | { |
2900 | switch (material.ZBuffer) | 2900 | switch (material.ZBuffer) |
2901 | { | 2901 | { |
2902 | case ECFN_NEVER: | 2902 | case ECFN_NEVER: |
2903 | glDisable(GL_DEPTH_TEST); | 2903 | glDisable(GL_DEPTH_TEST); |
2904 | break; | 2904 | break; |
2905 | case ECFN_LESSEQUAL: | 2905 | case ECFN_LESSEQUAL: |
2906 | glEnable(GL_DEPTH_TEST); | 2906 | glEnable(GL_DEPTH_TEST); |
2907 | glDepthFunc(GL_LEQUAL); | 2907 | glDepthFunc(GL_LEQUAL); |
2908 | break; | 2908 | break; |
2909 | case ECFN_EQUAL: | 2909 | case ECFN_EQUAL: |
2910 | glEnable(GL_DEPTH_TEST); | 2910 | glEnable(GL_DEPTH_TEST); |
2911 | glDepthFunc(GL_EQUAL); | 2911 | glDepthFunc(GL_EQUAL); |
2912 | break; | 2912 | break; |
2913 | case ECFN_LESS: | 2913 | case ECFN_LESS: |
2914 | glEnable(GL_DEPTH_TEST); | 2914 | glEnable(GL_DEPTH_TEST); |
2915 | glDepthFunc(GL_LESS); | 2915 | glDepthFunc(GL_LESS); |
2916 | break; | 2916 | break; |
2917 | case ECFN_NOTEQUAL: | 2917 | case ECFN_NOTEQUAL: |
2918 | glEnable(GL_DEPTH_TEST); | 2918 | glEnable(GL_DEPTH_TEST); |
2919 | glDepthFunc(GL_NOTEQUAL); | 2919 | glDepthFunc(GL_NOTEQUAL); |
2920 | break; | 2920 | break; |
2921 | case ECFN_GREATEREQUAL: | 2921 | case ECFN_GREATEREQUAL: |
2922 | glEnable(GL_DEPTH_TEST); | 2922 | glEnable(GL_DEPTH_TEST); |
2923 | glDepthFunc(GL_GEQUAL); | 2923 | glDepthFunc(GL_GEQUAL); |
2924 | break; | 2924 | break; |
2925 | case ECFN_GREATER: | 2925 | case ECFN_GREATER: |
2926 | glEnable(GL_DEPTH_TEST); | 2926 | glEnable(GL_DEPTH_TEST); |
2927 | glDepthFunc(GL_GREATER); | 2927 | glDepthFunc(GL_GREATER); |
2928 | break; | 2928 | break; |
2929 | case ECFN_ALWAYS: | 2929 | case ECFN_ALWAYS: |
2930 | glEnable(GL_DEPTH_TEST); | 2930 | glEnable(GL_DEPTH_TEST); |
2931 | glDepthFunc(GL_ALWAYS); | 2931 | glDepthFunc(GL_ALWAYS); |
2932 | break; | 2932 | break; |
2933 | } | 2933 | } |
2934 | } | 2934 | } |
2935 | 2935 | ||
2936 | // zwrite | 2936 | // zwrite |
2937 | // if (resetAllRenderStates || lastmaterial.ZWriteEnable != material.ZWriteEnable) | 2937 | // if (resetAllRenderStates || lastmaterial.ZWriteEnable != material.ZWriteEnable) |
2938 | { | 2938 | { |
2939 | if (material.ZWriteEnable && (AllowZWriteOnTransparent || !material.isTransparent())) | 2939 | if (material.ZWriteEnable && (AllowZWriteOnTransparent || !material.isTransparent())) |
2940 | { | 2940 | { |
2941 | glDepthMask(GL_TRUE); | 2941 | glDepthMask(GL_TRUE); |
2942 | } | 2942 | } |
2943 | else | 2943 | else |
2944 | glDepthMask(GL_FALSE); | 2944 | glDepthMask(GL_FALSE); |
2945 | } | 2945 | } |
2946 | 2946 | ||
2947 | // back face culling | 2947 | // back face culling |
2948 | if (resetAllRenderStates || (lastmaterial.FrontfaceCulling != material.FrontfaceCulling) || (lastmaterial.BackfaceCulling != material.BackfaceCulling)) | 2948 | if (resetAllRenderStates || (lastmaterial.FrontfaceCulling != material.FrontfaceCulling) || (lastmaterial.BackfaceCulling != material.BackfaceCulling)) |
2949 | { | 2949 | { |
2950 | if ((material.FrontfaceCulling) && (material.BackfaceCulling)) | 2950 | if ((material.FrontfaceCulling) && (material.BackfaceCulling)) |
2951 | { | 2951 | { |
2952 | glCullFace(GL_FRONT_AND_BACK); | 2952 | glCullFace(GL_FRONT_AND_BACK); |
2953 | glEnable(GL_CULL_FACE); | 2953 | glEnable(GL_CULL_FACE); |
2954 | } | 2954 | } |
2955 | else | 2955 | else |
2956 | if (material.BackfaceCulling) | 2956 | if (material.BackfaceCulling) |
2957 | { | 2957 | { |
2958 | glCullFace(GL_BACK); | 2958 | glCullFace(GL_BACK); |
2959 | glEnable(GL_CULL_FACE); | 2959 | glEnable(GL_CULL_FACE); |
2960 | } | 2960 | } |
2961 | else | 2961 | else |
2962 | if (material.FrontfaceCulling) | 2962 | if (material.FrontfaceCulling) |
2963 | { | 2963 | { |
2964 | glCullFace(GL_FRONT); | 2964 | glCullFace(GL_FRONT); |
2965 | glEnable(GL_CULL_FACE); | 2965 | glEnable(GL_CULL_FACE); |
2966 | } | 2966 | } |
2967 | else | 2967 | else |
2968 | glDisable(GL_CULL_FACE); | 2968 | glDisable(GL_CULL_FACE); |
2969 | } | 2969 | } |
2970 | 2970 | ||
2971 | // fog | 2971 | // fog |
2972 | if (resetAllRenderStates || lastmaterial.FogEnable != material.FogEnable) | 2972 | if (resetAllRenderStates || lastmaterial.FogEnable != material.FogEnable) |
2973 | { | 2973 | { |
2974 | if (material.FogEnable) | 2974 | if (material.FogEnable) |
2975 | glEnable(GL_FOG); | 2975 | glEnable(GL_FOG); |
2976 | else | 2976 | else |
2977 | glDisable(GL_FOG); | 2977 | glDisable(GL_FOG); |
2978 | } | 2978 | } |
2979 | 2979 | ||
2980 | // normalization | 2980 | // normalization |
2981 | if (resetAllRenderStates || lastmaterial.NormalizeNormals != material.NormalizeNormals) | 2981 | if (resetAllRenderStates || lastmaterial.NormalizeNormals != material.NormalizeNormals) |
2982 | { | 2982 | { |
2983 | if (material.NormalizeNormals) | 2983 | if (material.NormalizeNormals) |
2984 | glEnable(GL_NORMALIZE); | 2984 | glEnable(GL_NORMALIZE); |
2985 | else | 2985 | else |
2986 | glDisable(GL_NORMALIZE); | 2986 | glDisable(GL_NORMALIZE); |
2987 | } | 2987 | } |
2988 | 2988 | ||
2989 | // Color Mask | 2989 | // Color Mask |
2990 | if (resetAllRenderStates || lastmaterial.ColorMask != material.ColorMask) | 2990 | if (resetAllRenderStates || lastmaterial.ColorMask != material.ColorMask) |
2991 | { | 2991 | { |
2992 | glColorMask( | 2992 | glColorMask( |
2993 | (material.ColorMask & ECP_RED)?GL_TRUE:GL_FALSE, | 2993 | (material.ColorMask & ECP_RED)?GL_TRUE:GL_FALSE, |
2994 | (material.ColorMask & ECP_GREEN)?GL_TRUE:GL_FALSE, | 2994 | (material.ColorMask & ECP_GREEN)?GL_TRUE:GL_FALSE, |
2995 | (material.ColorMask & ECP_BLUE)?GL_TRUE:GL_FALSE, | 2995 | (material.ColorMask & ECP_BLUE)?GL_TRUE:GL_FALSE, |
2996 | (material.ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE); | 2996 | (material.ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE); |
2997 | } | 2997 | } |
2998 | 2998 | ||
2999 | if (queryFeature(EVDF_BLEND_OPERATIONS) && | 2999 | if (queryFeature(EVDF_BLEND_OPERATIONS) && |
3000 | (resetAllRenderStates|| lastmaterial.BlendOperation != material.BlendOperation)) | 3000 | (resetAllRenderStates|| lastmaterial.BlendOperation != material.BlendOperation)) |
3001 | { | 3001 | { |
3002 | if (material.BlendOperation==EBO_NONE) | 3002 | if (material.BlendOperation==EBO_NONE) |
3003 | glDisable(GL_BLEND); | 3003 | glDisable(GL_BLEND); |
3004 | else | 3004 | else |
3005 | { | 3005 | { |
3006 | glEnable(GL_BLEND); | 3006 | glEnable(GL_BLEND); |
3007 | #if defined(GL_EXT_blend_subtract) || defined(GL_EXT_blend_minmax) || defined(GL_EXT_blend_logic_op) || defined(GL_VERSION_1_2) | 3007 | #if defined(GL_EXT_blend_subtract) || defined(GL_EXT_blend_minmax) || defined(GL_EXT_blend_logic_op) || defined(GL_VERSION_1_2) |
3008 | switch (material.BlendOperation) | 3008 | switch (material.BlendOperation) |
3009 | { | 3009 | { |
3010 | case EBO_SUBTRACT: | 3010 | case EBO_SUBTRACT: |
3011 | #if defined(GL_EXT_blend_subtract) | 3011 | #if defined(GL_EXT_blend_subtract) |
3012 | if (FeatureAvailable[IRR_EXT_blend_subtract] || (Version>=120)) | 3012 | if (FeatureAvailable[IRR_EXT_blend_subtract] || (Version>=120)) |
3013 | extGlBlendEquation(GL_FUNC_SUBTRACT_EXT); | 3013 | extGlBlendEquation(GL_FUNC_SUBTRACT_EXT); |
3014 | #elif defined(GL_VERSION_1_2) | 3014 | #elif defined(GL_VERSION_1_2) |
3015 | if (Version>=120) | 3015 | if (Version>=120) |
3016 | extGlBlendEquation(GL_FUNC_SUBTRACT); | 3016 | extGlBlendEquation(GL_FUNC_SUBTRACT); |
3017 | #endif | 3017 | #endif |
3018 | break; | 3018 | break; |
3019 | case EBO_REVSUBTRACT: | 3019 | case EBO_REVSUBTRACT: |
3020 | #if defined(GL_EXT_blend_subtract) | 3020 | #if defined(GL_EXT_blend_subtract) |
3021 | if (FeatureAvailable[IRR_EXT_blend_subtract] || (Version>=120)) | 3021 | if (FeatureAvailable[IRR_EXT_blend_subtract] || (Version>=120)) |
3022 | extGlBlendEquation(GL_FUNC_REVERSE_SUBTRACT_EXT); | 3022 | extGlBlendEquation(GL_FUNC_REVERSE_SUBTRACT_EXT); |
3023 | #elif defined(GL_VERSION_1_2) | 3023 | #elif defined(GL_VERSION_1_2) |
3024 | if (Version>=120) | 3024 | if (Version>=120) |
3025 | extGlBlendEquation(GL_FUNC_REVERSE_SUBTRACT); | 3025 | extGlBlendEquation(GL_FUNC_REVERSE_SUBTRACT); |
3026 | #endif | 3026 | #endif |
3027 | break; | 3027 | break; |
3028 | case EBO_MIN: | 3028 | case EBO_MIN: |
3029 | #if defined(GL_EXT_blend_minmax) | 3029 | #if defined(GL_EXT_blend_minmax) |
3030 | if (FeatureAvailable[IRR_EXT_blend_minmax] || (Version>=120)) | 3030 | if (FeatureAvailable[IRR_EXT_blend_minmax] || (Version>=120)) |
3031 | extGlBlendEquation(GL_MIN_EXT); | 3031 | extGlBlendEquation(GL_MIN_EXT); |
3032 | #elif defined(GL_VERSION_1_2) | 3032 | #elif defined(GL_VERSION_1_2) |
3033 | if (Version>=120) | 3033 | if (Version>=120) |
3034 | extGlBlendEquation(GL_MIN); | 3034 | extGlBlendEquation(GL_MIN); |
3035 | #endif | 3035 | #endif |
3036 | break; | 3036 | break; |
3037 | case EBO_MAX: | 3037 | case EBO_MAX: |
3038 | #if defined(GL_EXT_blend_minmax) | 3038 | #if defined(GL_EXT_blend_minmax) |
3039 | if (FeatureAvailable[IRR_EXT_blend_minmax] || (Version>=120)) | 3039 | if (FeatureAvailable[IRR_EXT_blend_minmax] || (Version>=120)) |
3040 | extGlBlendEquation(GL_MAX_EXT); | 3040 | extGlBlendEquation(GL_MAX_EXT); |
3041 | #elif defined(GL_VERSION_1_2) | 3041 | #elif defined(GL_VERSION_1_2) |
3042 | if (Version>=120) | 3042 | if (Version>=120) |
3043 | extGlBlendEquation(GL_MAX); | 3043 | extGlBlendEquation(GL_MAX); |
3044 | #endif | 3044 | #endif |
3045 | break; | 3045 | break; |
3046 | case EBO_MIN_FACTOR: | 3046 | case EBO_MIN_FACTOR: |
3047 | #if defined(GL_AMD_blend_minmax_factor) | 3047 | #if defined(GL_AMD_blend_minmax_factor) |
3048 | if (FeatureAvailable[IRR_AMD_blend_minmax_factor]) | 3048 | if (FeatureAvailable[IRR_AMD_blend_minmax_factor]) |
3049 | extGlBlendEquation(GL_FACTOR_MIN_AMD); | 3049 | extGlBlendEquation(GL_FACTOR_MIN_AMD); |
3050 | #endif | 3050 | #endif |
3051 | // fallback in case of missing extension | 3051 | // fallback in case of missing extension |
3052 | #if defined(GL_VERSION_1_2) | 3052 | #if defined(GL_VERSION_1_2) |
3053 | #if defined(GL_AMD_blend_minmax_factor) | 3053 | #if defined(GL_AMD_blend_minmax_factor) |
3054 | else | 3054 | else |
3055 | #endif | 3055 | #endif |
3056 | if (Version>=120) | 3056 | if (Version>=120) |
3057 | extGlBlendEquation(GL_MIN); | 3057 | extGlBlendEquation(GL_MIN); |
3058 | #endif | 3058 | #endif |
3059 | break; | 3059 | break; |
3060 | case EBO_MAX_FACTOR: | 3060 | case EBO_MAX_FACTOR: |
3061 | #if defined(GL_AMD_blend_minmax_factor) | 3061 | #if defined(GL_AMD_blend_minmax_factor) |
3062 | if (FeatureAvailable[IRR_AMD_blend_minmax_factor]) | 3062 | if (FeatureAvailable[IRR_AMD_blend_minmax_factor]) |
3063 | extGlBlendEquation(GL_FACTOR_MAX_AMD); | 3063 | extGlBlendEquation(GL_FACTOR_MAX_AMD); |
3064 | #endif | 3064 | #endif |
3065 | // fallback in case of missing extension | 3065 | // fallback in case of missing extension |
3066 | #if defined(GL_VERSION_1_2) | 3066 | #if defined(GL_VERSION_1_2) |
3067 | #if defined(GL_AMD_blend_minmax_factor) | 3067 | #if defined(GL_AMD_blend_minmax_factor) |
3068 | else | 3068 | else |
3069 | #endif | 3069 | #endif |
3070 | if (Version>=120) | 3070 | if (Version>=120) |
3071 | extGlBlendEquation(GL_MAX); | 3071 | extGlBlendEquation(GL_MAX); |
3072 | #endif | 3072 | #endif |
3073 | break; | 3073 | break; |
3074 | case EBO_MIN_ALPHA: | 3074 | case EBO_MIN_ALPHA: |
3075 | #if defined(GL_SGIX_blend_alpha_minmax) | 3075 | #if defined(GL_SGIX_blend_alpha_minmax) |
3076 | if (FeatureAvailable[IRR_SGIX_blend_alpha_minmax]) | 3076 | if (FeatureAvailable[IRR_SGIX_blend_alpha_minmax]) |
3077 | extGlBlendEquation(GL_ALPHA_MIN_SGIX); | 3077 | extGlBlendEquation(GL_ALPHA_MIN_SGIX); |
3078 | // fallback in case of missing extension | 3078 | // fallback in case of missing extension |
3079 | else | 3079 | else |
3080 | if (FeatureAvailable[IRR_EXT_blend_minmax]) | 3080 | if (FeatureAvailable[IRR_EXT_blend_minmax]) |
3081 | extGlBlendEquation(GL_MIN_EXT); | 3081 | extGlBlendEquation(GL_MIN_EXT); |
3082 | #endif | 3082 | #endif |
3083 | break; | 3083 | break; |
3084 | case EBO_MAX_ALPHA: | 3084 | case EBO_MAX_ALPHA: |
3085 | #if defined(GL_SGIX_blend_alpha_minmax) | 3085 | #if defined(GL_SGIX_blend_alpha_minmax) |
3086 | if (FeatureAvailable[IRR_SGIX_blend_alpha_minmax]) | 3086 | if (FeatureAvailable[IRR_SGIX_blend_alpha_minmax]) |
3087 | extGlBlendEquation(GL_ALPHA_MAX_SGIX); | 3087 | extGlBlendEquation(GL_ALPHA_MAX_SGIX); |
3088 | // fallback in case of missing extension | 3088 | // fallback in case of missing extension |
3089 | else | 3089 | else |
3090 | if (FeatureAvailable[IRR_EXT_blend_minmax]) | 3090 | if (FeatureAvailable[IRR_EXT_blend_minmax]) |
3091 | extGlBlendEquation(GL_MAX_EXT); | 3091 | extGlBlendEquation(GL_MAX_EXT); |
3092 | #endif | 3092 | #endif |
3093 | break; | 3093 | break; |
3094 | default: | 3094 | default: |
3095 | #if defined(GL_EXT_blend_subtract) || defined(GL_EXT_blend_minmax) || defined(GL_EXT_blend_logic_op) | 3095 | #if defined(GL_EXT_blend_subtract) || defined(GL_EXT_blend_minmax) || defined(GL_EXT_blend_logic_op) |
3096 | extGlBlendEquation(GL_FUNC_ADD_EXT); | 3096 | extGlBlendEquation(GL_FUNC_ADD_EXT); |
3097 | #elif defined(GL_VERSION_1_2) | 3097 | #elif defined(GL_VERSION_1_2) |
3098 | extGlBlendEquation(GL_FUNC_ADD); | 3098 | extGlBlendEquation(GL_FUNC_ADD); |
3099 | #endif | 3099 | #endif |
3100 | break; | 3100 | break; |
3101 | } | 3101 | } |
3102 | #endif | 3102 | #endif |
3103 | } | 3103 | } |
3104 | } | 3104 | } |
3105 | 3105 | ||
3106 | // Polygon Offset | 3106 | // Polygon Offset |
3107 | if (queryFeature(EVDF_POLYGON_OFFSET) && (resetAllRenderStates || | 3107 | if (queryFeature(EVDF_POLYGON_OFFSET) && (resetAllRenderStates || |
3108 | lastmaterial.PolygonOffsetDirection != material.PolygonOffsetDirection || | 3108 | lastmaterial.PolygonOffsetDirection != material.PolygonOffsetDirection || |
3109 | lastmaterial.PolygonOffsetFactor != material.PolygonOffsetFactor)) | 3109 | lastmaterial.PolygonOffsetFactor != material.PolygonOffsetFactor)) |
3110 | { | 3110 | { |
3111 | glDisable(lastmaterial.Wireframe?GL_POLYGON_OFFSET_LINE:lastmaterial.PointCloud?GL_POLYGON_OFFSET_POINT:GL_POLYGON_OFFSET_FILL); | 3111 | glDisable(lastmaterial.Wireframe?GL_POLYGON_OFFSET_LINE:lastmaterial.PointCloud?GL_POLYGON_OFFSET_POINT:GL_POLYGON_OFFSET_FILL); |
3112 | if (material.PolygonOffsetFactor) | 3112 | if (material.PolygonOffsetFactor) |
3113 | { | 3113 | { |
3114 | glDisable(material.Wireframe?GL_POLYGON_OFFSET_LINE:material.PointCloud?GL_POLYGON_OFFSET_POINT:GL_POLYGON_OFFSET_FILL); | 3114 | glDisable(material.Wireframe?GL_POLYGON_OFFSET_LINE:material.PointCloud?GL_POLYGON_OFFSET_POINT:GL_POLYGON_OFFSET_FILL); |
3115 | glEnable(material.Wireframe?GL_POLYGON_OFFSET_LINE:material.PointCloud?GL_POLYGON_OFFSET_POINT:GL_POLYGON_OFFSET_FILL); | 3115 | glEnable(material.Wireframe?GL_POLYGON_OFFSET_LINE:material.PointCloud?GL_POLYGON_OFFSET_POINT:GL_POLYGON_OFFSET_FILL); |
3116 | } | 3116 | } |
3117 | if (material.PolygonOffsetDirection==EPO_BACK) | 3117 | if (material.PolygonOffsetDirection==EPO_BACK) |
3118 | glPolygonOffset(1.0f, (GLfloat)material.PolygonOffsetFactor); | 3118 | glPolygonOffset(1.0f, (GLfloat)material.PolygonOffsetFactor); |
3119 | else | 3119 | else |
3120 | glPolygonOffset(-1.0f, (GLfloat)-material.PolygonOffsetFactor); | 3120 | glPolygonOffset(-1.0f, (GLfloat)-material.PolygonOffsetFactor); |
3121 | } | 3121 | } |
3122 | 3122 | ||
3123 | // thickness | 3123 | // thickness |
3124 | if (resetAllRenderStates || lastmaterial.Thickness != material.Thickness) | 3124 | if (resetAllRenderStates || lastmaterial.Thickness != material.Thickness) |
3125 | { | 3125 | { |
3126 | if (AntiAlias) | 3126 | if (AntiAlias) |
3127 | { | 3127 | { |
3128 | // glPointSize(core::clamp(static_cast<GLfloat>(material.Thickness), DimSmoothedPoint[0], DimSmoothedPoint[1])); | 3128 | // glPointSize(core::clamp(static_cast<GLfloat>(material.Thickness), DimSmoothedPoint[0], DimSmoothedPoint[1])); |
3129 | // we don't use point smoothing | 3129 | // we don't use point smoothing |
3130 | glPointSize(core::clamp(static_cast<GLfloat>(material.Thickness), DimAliasedPoint[0], DimAliasedPoint[1])); | 3130 | glPointSize(core::clamp(static_cast<GLfloat>(material.Thickness), DimAliasedPoint[0], DimAliasedPoint[1])); |
3131 | glLineWidth(core::clamp(static_cast<GLfloat>(material.Thickness), DimSmoothedLine[0], DimSmoothedLine[1])); | 3131 | glLineWidth(core::clamp(static_cast<GLfloat>(material.Thickness), DimSmoothedLine[0], DimSmoothedLine[1])); |
3132 | } | 3132 | } |
3133 | else | 3133 | else |
3134 | { | 3134 | { |
3135 | glPointSize(core::clamp(static_cast<GLfloat>(material.Thickness), DimAliasedPoint[0], DimAliasedPoint[1])); | 3135 | glPointSize(core::clamp(static_cast<GLfloat>(material.Thickness), DimAliasedPoint[0], DimAliasedPoint[1])); |
3136 | glLineWidth(core::clamp(static_cast<GLfloat>(material.Thickness), DimAliasedLine[0], DimAliasedLine[1])); | 3136 | glLineWidth(core::clamp(static_cast<GLfloat>(material.Thickness), DimAliasedLine[0], DimAliasedLine[1])); |
3137 | } | 3137 | } |
3138 | } | 3138 | } |
3139 | 3139 | ||
3140 | // Anti aliasing | 3140 | // Anti aliasing |
3141 | if (resetAllRenderStates || lastmaterial.AntiAliasing != material.AntiAliasing) | 3141 | if (resetAllRenderStates || lastmaterial.AntiAliasing != material.AntiAliasing) |
3142 | { | 3142 | { |
3143 | if (FeatureAvailable[IRR_ARB_multisample]) | 3143 | if (FeatureAvailable[IRR_ARB_multisample]) |
3144 | { | 3144 | { |
3145 | if (material.AntiAliasing & EAAM_ALPHA_TO_COVERAGE) | 3145 | if (material.AntiAliasing & EAAM_ALPHA_TO_COVERAGE) |
3146 | glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); | 3146 | glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); |
3147 | else if (lastmaterial.AntiAliasing & EAAM_ALPHA_TO_COVERAGE) | 3147 | else if (lastmaterial.AntiAliasing & EAAM_ALPHA_TO_COVERAGE) |
3148 | glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); | 3148 | glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); |
3149 | 3149 | ||
3150 | if ((AntiAlias >= 2) && (material.AntiAliasing & (EAAM_SIMPLE|EAAM_QUALITY))) | 3150 | if ((AntiAlias >= 2) && (material.AntiAliasing & (EAAM_SIMPLE|EAAM_QUALITY))) |
3151 | { | 3151 | { |
3152 | glEnable(GL_MULTISAMPLE_ARB); | 3152 | glEnable(GL_MULTISAMPLE_ARB); |
3153 | #ifdef GL_NV_multisample_filter_hint | 3153 | #ifdef GL_NV_multisample_filter_hint |
3154 | if (FeatureAvailable[IRR_NV_multisample_filter_hint]) | 3154 | if (FeatureAvailable[IRR_NV_multisample_filter_hint]) |
3155 | { | 3155 | { |
3156 | if ((material.AntiAliasing & EAAM_QUALITY) == EAAM_QUALITY) | 3156 | if ((material.AntiAliasing & EAAM_QUALITY) == EAAM_QUALITY) |
3157 | glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); | 3157 | glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); |
3158 | else | 3158 | else |
3159 | glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); | 3159 | glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); |
3160 | } | 3160 | } |
3161 | #endif | 3161 | #endif |
3162 | } | 3162 | } |
3163 | else | 3163 | else |
3164 | glDisable(GL_MULTISAMPLE_ARB); | 3164 | glDisable(GL_MULTISAMPLE_ARB); |
3165 | } | 3165 | } |
3166 | if ((material.AntiAliasing & EAAM_LINE_SMOOTH) != (lastmaterial.AntiAliasing & EAAM_LINE_SMOOTH)) | 3166 | if ((material.AntiAliasing & EAAM_LINE_SMOOTH) != (lastmaterial.AntiAliasing & EAAM_LINE_SMOOTH)) |
3167 | { | 3167 | { |
3168 | if (material.AntiAliasing & EAAM_LINE_SMOOTH) | 3168 | if (material.AntiAliasing & EAAM_LINE_SMOOTH) |
3169 | glEnable(GL_LINE_SMOOTH); | 3169 | glEnable(GL_LINE_SMOOTH); |
3170 | else if (lastmaterial.AntiAliasing & EAAM_LINE_SMOOTH) | 3170 | else if (lastmaterial.AntiAliasing & EAAM_LINE_SMOOTH) |
3171 | glDisable(GL_LINE_SMOOTH); | 3171 | glDisable(GL_LINE_SMOOTH); |
3172 | } | 3172 | } |
3173 | if ((material.AntiAliasing & EAAM_POINT_SMOOTH) != (lastmaterial.AntiAliasing & EAAM_POINT_SMOOTH)) | 3173 | if ((material.AntiAliasing & EAAM_POINT_SMOOTH) != (lastmaterial.AntiAliasing & EAAM_POINT_SMOOTH)) |
3174 | { | 3174 | { |
3175 | if (material.AntiAliasing & EAAM_POINT_SMOOTH) | 3175 | if (material.AntiAliasing & EAAM_POINT_SMOOTH) |
3176 | // often in software, and thus very slow | 3176 | // often in software, and thus very slow |
3177 | glEnable(GL_POINT_SMOOTH); | 3177 | glEnable(GL_POINT_SMOOTH); |
3178 | else if (lastmaterial.AntiAliasing & EAAM_POINT_SMOOTH) | 3178 | else if (lastmaterial.AntiAliasing & EAAM_POINT_SMOOTH) |
3179 | glDisable(GL_POINT_SMOOTH); | 3179 | glDisable(GL_POINT_SMOOTH); |
3180 | } | 3180 | } |
3181 | } | 3181 | } |
3182 | 3182 | ||
3183 | setWrapMode(material); | 3183 | setWrapMode(material); |
3184 | 3184 | ||
3185 | // be sure to leave in texture stage 0 | 3185 | // be sure to leave in texture stage 0 |
3186 | if (MultiTextureExtension) | 3186 | if (MultiTextureExtension) |
3187 | extGlActiveTexture(GL_TEXTURE0_ARB); | 3187 | extGlActiveTexture(GL_TEXTURE0_ARB); |
3188 | } | 3188 | } |
3189 | 3189 | ||
3190 | 3190 | ||
3191 | //! Enable the 2d override material | 3191 | //! Enable the 2d override material |
3192 | void COpenGLDriver::enableMaterial2D(bool enable) | 3192 | void COpenGLDriver::enableMaterial2D(bool enable) |
3193 | { | 3193 | { |
3194 | if (!enable) | 3194 | if (!enable) |
3195 | CurrentRenderMode = ERM_NONE; | 3195 | CurrentRenderMode = ERM_NONE; |
3196 | CNullDriver::enableMaterial2D(enable); | 3196 | CNullDriver::enableMaterial2D(enable); |
3197 | } | 3197 | } |
3198 | 3198 | ||
3199 | 3199 | ||
3200 | //! sets the needed renderstates | 3200 | //! sets the needed renderstates |
3201 | void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel) | 3201 | void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel) |
3202 | { | 3202 | { |
3203 | if (CurrentRenderMode != ERM_2D || Transformation3DChanged) | 3203 | if (CurrentRenderMode != ERM_2D || Transformation3DChanged) |
3204 | { | 3204 | { |
3205 | // unset last 3d material | 3205 | // unset last 3d material |
3206 | if (CurrentRenderMode == ERM_3D) | 3206 | if (CurrentRenderMode == ERM_3D) |
3207 | { | 3207 | { |
3208 | if (static_cast<u32>(LastMaterial.MaterialType) < MaterialRenderers.size()) | 3208 | if (static_cast<u32>(LastMaterial.MaterialType) < MaterialRenderers.size()) |
3209 | MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); | 3209 | MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); |
3210 | } | 3210 | } |
3211 | if (Transformation3DChanged) | 3211 | if (Transformation3DChanged) |
3212 | { | 3212 | { |
3213 | glMatrixMode(GL_PROJECTION); | 3213 | glMatrixMode(GL_PROJECTION); |
3214 | 3214 | ||
3215 | const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize(); | 3215 | const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize(); |
3216 | core::matrix4 m(core::matrix4::EM4CONST_NOTHING); | 3216 | core::matrix4 m(core::matrix4::EM4CONST_NOTHING); |
3217 | m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0f, 1.0f); | 3217 | m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0f, 1.0f); |
3218 | m.setTranslation(core::vector3df(-1,1,0)); | 3218 | m.setTranslation(core::vector3df(-1,1,0)); |
3219 | glLoadMatrixf(m.pointer()); | 3219 | glLoadMatrixf(m.pointer()); |
3220 | 3220 | ||
3221 | glMatrixMode(GL_MODELVIEW); | 3221 | glMatrixMode(GL_MODELVIEW); |
3222 | glLoadIdentity(); | 3222 | glLoadIdentity(); |
3223 | glTranslatef(0.375f, 0.375f, 0.0f); | 3223 | glTranslatef(0.375f, 0.375f, 0.0f); |
3224 | 3224 | ||
3225 | // Make sure we set first texture matrix | 3225 | // Make sure we set first texture matrix |
3226 | if (MultiTextureExtension) | 3226 | if (MultiTextureExtension) |
3227 | extGlActiveTexture(GL_TEXTURE0_ARB); | 3227 | extGlActiveTexture(GL_TEXTURE0_ARB); |
3228 | 3228 | ||
3229 | Transformation3DChanged = false; | 3229 | Transformation3DChanged = false; |
3230 | } | 3230 | } |
3231 | if (!OverrideMaterial2DEnabled) | 3231 | if (!OverrideMaterial2DEnabled) |
3232 | { | 3232 | { |
3233 | setBasicRenderStates(InitMaterial2D, LastMaterial, true); | 3233 | setBasicRenderStates(InitMaterial2D, LastMaterial, true); |
3234 | LastMaterial = InitMaterial2D; | 3234 | LastMaterial = InitMaterial2D; |
3235 | } | 3235 | } |
3236 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 3236 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
3237 | #ifdef GL_EXT_clip_volume_hint | 3237 | #ifdef GL_EXT_clip_volume_hint |
3238 | if (FeatureAvailable[IRR_EXT_clip_volume_hint]) | 3238 | if (FeatureAvailable[IRR_EXT_clip_volume_hint]) |
3239 | glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_FASTEST); | 3239 | glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_FASTEST); |
3240 | #endif | 3240 | #endif |
3241 | 3241 | ||
3242 | } | 3242 | } |
3243 | if (OverrideMaterial2DEnabled) | 3243 | if (OverrideMaterial2DEnabled) |
3244 | { | 3244 | { |
3245 | OverrideMaterial2D.Lighting=false; | 3245 | OverrideMaterial2D.Lighting=false; |
3246 | setBasicRenderStates(OverrideMaterial2D, LastMaterial, false); | 3246 | setBasicRenderStates(OverrideMaterial2D, LastMaterial, false); |
3247 | LastMaterial = OverrideMaterial2D; | 3247 | LastMaterial = OverrideMaterial2D; |
3248 | } | 3248 | } |
3249 | 3249 | ||
3250 | // no alphaChannel without texture | 3250 | // no alphaChannel without texture |
3251 | alphaChannel &= texture; | 3251 | alphaChannel &= texture; |
3252 | 3252 | ||
3253 | if (alphaChannel || alpha) | 3253 | if (alphaChannel || alpha) |
3254 | { | 3254 | { |
3255 | glEnable(GL_BLEND); | 3255 | glEnable(GL_BLEND); |
3256 | glEnable(GL_ALPHA_TEST); | 3256 | glEnable(GL_ALPHA_TEST); |
3257 | glAlphaFunc(GL_GREATER, 0.f); | 3257 | glAlphaFunc(GL_GREATER, 0.f); |
3258 | } | 3258 | } |
3259 | else | 3259 | else |
3260 | { | 3260 | { |
3261 | glDisable(GL_BLEND); | 3261 | glDisable(GL_BLEND); |
3262 | glDisable(GL_ALPHA_TEST); | 3262 | glDisable(GL_ALPHA_TEST); |
3263 | } | 3263 | } |
3264 | 3264 | ||
3265 | if (texture) | 3265 | if (texture) |
3266 | { | 3266 | { |
3267 | if (!OverrideMaterial2DEnabled) | 3267 | if (!OverrideMaterial2DEnabled) |
3268 | { | 3268 | { |
3269 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 3269 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
3270 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 3270 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
3271 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); | 3271 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); |
3272 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); | 3272 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); |
3273 | } | 3273 | } |
3274 | Material.setTexture(0, const_cast<video::ITexture*>(CurrentTexture[0])); | 3274 | Material.setTexture(0, const_cast<video::ITexture*>(CurrentTexture[0])); |
3275 | setTransform(ETS_TEXTURE_0, core::IdentityMatrix); | 3275 | setTransform(ETS_TEXTURE_0, core::IdentityMatrix); |
3276 | // Due to the transformation change, the previous line would call a reset each frame | 3276 | // Due to the transformation change, the previous line would call a reset each frame |
3277 | // but we can safely reset the variable as it was false before | 3277 | // but we can safely reset the variable as it was false before |
3278 | Transformation3DChanged=false; | 3278 | Transformation3DChanged=false; |
3279 | 3279 | ||
3280 | if (alphaChannel) | 3280 | if (alphaChannel) |
3281 | { | 3281 | { |
3282 | // if alpha and alpha texture just modulate, otherwise use only the alpha channel | 3282 | // if alpha and alpha texture just modulate, otherwise use only the alpha channel |
3283 | if (alpha) | 3283 | if (alpha) |
3284 | { | 3284 | { |
3285 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | 3285 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); |
3286 | } | 3286 | } |
3287 | else | 3287 | else |
3288 | { | 3288 | { |
3289 | #if defined(GL_ARB_texture_env_combine) || defined(GL_EXT_texture_env_combine) | 3289 | #if defined(GL_ARB_texture_env_combine) || defined(GL_EXT_texture_env_combine) |
3290 | if (FeatureAvailable[IRR_ARB_texture_env_combine]||FeatureAvailable[IRR_EXT_texture_env_combine]) | 3290 | if (FeatureAvailable[IRR_ARB_texture_env_combine]||FeatureAvailable[IRR_EXT_texture_env_combine]) |
3291 | { | 3291 | { |
3292 | #ifdef GL_ARB_texture_env_combine | 3292 | #ifdef GL_ARB_texture_env_combine |
3293 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); | 3293 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); |
3294 | glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); | 3294 | glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); |
3295 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); | 3295 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); |
3296 | // rgb always modulates | 3296 | // rgb always modulates |
3297 | glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); | 3297 | glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); |
3298 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); | 3298 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); |
3299 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB); | 3299 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB); |
3300 | #else | 3300 | #else |
3301 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); | 3301 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); |
3302 | glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); | 3302 | glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); |
3303 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); | 3303 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); |
3304 | // rgb always modulates | 3304 | // rgb always modulates |
3305 | glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); | 3305 | glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); |
3306 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); | 3306 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); |
3307 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); | 3307 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); |
3308 | #endif | 3308 | #endif |
3309 | } | 3309 | } |
3310 | else | 3310 | else |
3311 | #endif | 3311 | #endif |
3312 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | 3312 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); |
3313 | } | 3313 | } |
3314 | } | 3314 | } |
3315 | else | 3315 | else |
3316 | { | 3316 | { |
3317 | if (alpha) | 3317 | if (alpha) |
3318 | { | 3318 | { |
3319 | #if defined(GL_ARB_texture_env_combine) || defined(GL_EXT_texture_env_combine) | 3319 | #if defined(GL_ARB_texture_env_combine) || defined(GL_EXT_texture_env_combine) |
3320 | if (FeatureAvailable[IRR_ARB_texture_env_combine]||FeatureAvailable[IRR_EXT_texture_env_combine]) | 3320 | if (FeatureAvailable[IRR_ARB_texture_env_combine]||FeatureAvailable[IRR_EXT_texture_env_combine]) |
3321 | { | 3321 | { |
3322 | #ifdef GL_ARB_texture_env_combine | 3322 | #ifdef GL_ARB_texture_env_combine |
3323 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); | 3323 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); |
3324 | glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); | 3324 | glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); |
3325 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); | 3325 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); |
3326 | // rgb always modulates | 3326 | // rgb always modulates |
3327 | glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); | 3327 | glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); |
3328 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); | 3328 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); |
3329 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB); | 3329 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB); |
3330 | #else | 3330 | #else |
3331 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); | 3331 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); |
3332 | glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); | 3332 | glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); |
3333 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); | 3333 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); |
3334 | // rgb always modulates | 3334 | // rgb always modulates |
3335 | glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); | 3335 | glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); |
3336 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); | 3336 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); |
3337 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); | 3337 | glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); |
3338 | #endif | 3338 | #endif |
3339 | } | 3339 | } |
3340 | else | 3340 | else |
3341 | #endif | 3341 | #endif |
3342 | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | 3342 | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); |
3343 | } | 3343 | } |
3344 | else | 3344 | else |
3345 | { | 3345 | { |
3346 | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | 3346 | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); |
3347 | } | 3347 | } |
3348 | } | 3348 | } |
3349 | } | 3349 | } |
3350 | 3350 | ||
3351 | CurrentRenderMode = ERM_2D; | 3351 | CurrentRenderMode = ERM_2D; |
3352 | } | 3352 | } |
3353 | 3353 | ||
3354 | 3354 | ||
3355 | //! \return Returns the name of the video driver. | 3355 | //! \return Returns the name of the video driver. |
3356 | const wchar_t* COpenGLDriver::getName() const | 3356 | const wchar_t* COpenGLDriver::getName() const |
3357 | { | 3357 | { |
3358 | return Name.c_str(); | 3358 | return Name.c_str(); |
3359 | } | 3359 | } |
3360 | 3360 | ||
3361 | 3361 | ||
3362 | //! deletes all dynamic lights there are | 3362 | //! deletes all dynamic lights there are |
3363 | void COpenGLDriver::deleteAllDynamicLights() | 3363 | void COpenGLDriver::deleteAllDynamicLights() |
3364 | { | 3364 | { |
3365 | for (s32 i=0; i<MaxLights; ++i) | 3365 | for (s32 i=0; i<MaxLights; ++i) |
3366 | glDisable(GL_LIGHT0 + i); | 3366 | glDisable(GL_LIGHT0 + i); |
3367 | 3367 | ||
3368 | RequestedLights.clear(); | 3368 | RequestedLights.clear(); |
3369 | 3369 | ||
3370 | CNullDriver::deleteAllDynamicLights(); | 3370 | CNullDriver::deleteAllDynamicLights(); |
3371 | } | 3371 | } |
3372 | 3372 | ||
3373 | 3373 | ||
3374 | //! adds a dynamic light | 3374 | //! adds a dynamic light |
3375 | s32 COpenGLDriver::addDynamicLight(const SLight& light) | 3375 | s32 COpenGLDriver::addDynamicLight(const SLight& light) |
3376 | { | 3376 | { |
3377 | CNullDriver::addDynamicLight(light); | 3377 | CNullDriver::addDynamicLight(light); |
3378 | 3378 | ||
3379 | RequestedLights.push_back(RequestedLight(light)); | 3379 | RequestedLights.push_back(RequestedLight(light)); |
3380 | 3380 | ||
3381 | u32 newLightIndex = RequestedLights.size() - 1; | 3381 | u32 newLightIndex = RequestedLights.size() - 1; |
3382 | 3382 | ||
3383 | // Try and assign a hardware light just now, but don't worry if I can't | 3383 | // Try and assign a hardware light just now, but don't worry if I can't |
3384 | assignHardwareLight(newLightIndex); | 3384 | assignHardwareLight(newLightIndex); |
3385 | 3385 | ||
3386 | return (s32)newLightIndex; | 3386 | return (s32)newLightIndex; |
3387 | } | 3387 | } |
3388 | 3388 | ||
3389 | 3389 | ||
3390 | void COpenGLDriver::assignHardwareLight(u32 lightIndex) | 3390 | void COpenGLDriver::assignHardwareLight(u32 lightIndex) |
3391 | { | 3391 | { |
3392 | setTransform(ETS_WORLD, core::matrix4()); | 3392 | setTransform(ETS_WORLD, core::matrix4()); |
3393 | 3393 | ||
3394 | s32 lidx; | 3394 | s32 lidx; |
3395 | for (lidx=GL_LIGHT0; lidx < GL_LIGHT0 + MaxLights; ++lidx) | 3395 | for (lidx=GL_LIGHT0; lidx < GL_LIGHT0 + MaxLights; ++lidx) |
3396 | { | 3396 | { |
3397 | if(!glIsEnabled(lidx)) | 3397 | if(!glIsEnabled(lidx)) |
3398 | { | 3398 | { |
3399 | RequestedLights[lightIndex].HardwareLightIndex = lidx; | 3399 | RequestedLights[lightIndex].HardwareLightIndex = lidx; |
3400 | break; | 3400 | break; |
3401 | } | 3401 | } |
3402 | } | 3402 | } |
3403 | 3403 | ||
3404 | if(lidx == GL_LIGHT0 + MaxLights) // There's no room for it just now | 3404 | if(lidx == GL_LIGHT0 + MaxLights) // There's no room for it just now |
3405 | return; | 3405 | return; |
3406 | 3406 | ||
3407 | GLfloat data[4]; | 3407 | GLfloat data[4]; |
3408 | const SLight & light = RequestedLights[lightIndex].LightData; | 3408 | const SLight & light = RequestedLights[lightIndex].LightData; |
3409 | 3409 | ||
3410 | switch (light.Type) | 3410 | switch (light.Type) |
3411 | { | 3411 | { |
3412 | case video::ELT_SPOT: | 3412 | case video::ELT_SPOT: |
3413 | data[0] = light.Direction.X; | 3413 | data[0] = light.Direction.X; |
3414 | data[1] = light.Direction.Y; | 3414 | data[1] = light.Direction.Y; |
3415 | data[2] = light.Direction.Z; | 3415 | data[2] = light.Direction.Z; |
3416 | data[3] = 0.0f; | 3416 | data[3] = 0.0f; |
3417 | glLightfv(lidx, GL_SPOT_DIRECTION, data); | 3417 | glLightfv(lidx, GL_SPOT_DIRECTION, data); |
3418 | 3418 | ||
3419 | // set position | 3419 | // set position |
3420 | data[0] = light.Position.X; | 3420 | data[0] = light.Position.X; |
3421 | data[1] = light.Position.Y; | 3421 | data[1] = light.Position.Y; |
3422 | data[2] = light.Position.Z; | 3422 | data[2] = light.Position.Z; |
3423 | data[3] = 1.0f; // 1.0f for positional light | 3423 | data[3] = 1.0f; // 1.0f for positional light |
3424 | glLightfv(lidx, GL_POSITION, data); | 3424 | glLightfv(lidx, GL_POSITION, data); |
3425 | 3425 | ||
3426 | glLightf(lidx, GL_SPOT_EXPONENT, light.Falloff); | 3426 | glLightf(lidx, GL_SPOT_EXPONENT, light.Falloff); |
3427 | glLightf(lidx, GL_SPOT_CUTOFF, light.OuterCone); | 3427 | glLightf(lidx, GL_SPOT_CUTOFF, light.OuterCone); |
3428 | break; | 3428 | break; |
3429 | case video::ELT_POINT: | 3429 | case video::ELT_POINT: |
3430 | // set position | 3430 | // set position |
3431 | data[0] = light.Position.X; | 3431 | data[0] = light.Position.X; |
3432 | data[1] = light.Position.Y; | 3432 | data[1] = light.Position.Y; |
3433 | data[2] = light.Position.Z; | 3433 | data[2] = light.Position.Z; |
3434 | data[3] = 1.0f; // 1.0f for positional light | 3434 | data[3] = 1.0f; // 1.0f for positional light |
3435 | glLightfv(lidx, GL_POSITION, data); | 3435 | glLightfv(lidx, GL_POSITION, data); |
3436 | 3436 | ||
3437 | glLightf(lidx, GL_SPOT_EXPONENT, 0.0f); | 3437 | glLightf(lidx, GL_SPOT_EXPONENT, 0.0f); |
3438 | glLightf(lidx, GL_SPOT_CUTOFF, 180.0f); | 3438 | glLightf(lidx, GL_SPOT_CUTOFF, 180.0f); |
3439 | break; | 3439 | break; |
3440 | case video::ELT_DIRECTIONAL: | 3440 | case video::ELT_DIRECTIONAL: |
3441 | // set direction | 3441 | // set direction |
3442 | data[0] = -light.Direction.X; | 3442 | data[0] = -light.Direction.X; |
3443 | data[1] = -light.Direction.Y; | 3443 | data[1] = -light.Direction.Y; |
3444 | data[2] = -light.Direction.Z; | 3444 | data[2] = -light.Direction.Z; |
3445 | data[3] = 0.0f; // 0.0f for directional light | 3445 | data[3] = 0.0f; // 0.0f for directional light |
3446 | glLightfv(lidx, GL_POSITION, data); | 3446 | glLightfv(lidx, GL_POSITION, data); |
3447 | 3447 | ||
3448 | glLightf(lidx, GL_SPOT_EXPONENT, 0.0f); | 3448 | glLightf(lidx, GL_SPOT_EXPONENT, 0.0f); |
3449 | glLightf(lidx, GL_SPOT_CUTOFF, 180.0f); | 3449 | glLightf(lidx, GL_SPOT_CUTOFF, 180.0f); |
3450 | break; | 3450 | break; |
3451 | default: | 3451 | default: |
3452 | break; | 3452 | break; |
3453 | } | 3453 | } |
3454 | 3454 | ||
3455 | // set diffuse color | 3455 | // set diffuse color |
3456 | data[0] = light.DiffuseColor.r; | 3456 | data[0] = light.DiffuseColor.r; |
3457 | data[1] = light.DiffuseColor.g; | 3457 | data[1] = light.DiffuseColor.g; |
3458 | data[2] = light.DiffuseColor.b; | 3458 | data[2] = light.DiffuseColor.b; |
3459 | data[3] = light.DiffuseColor.a; | 3459 | data[3] = light.DiffuseColor.a; |
3460 | glLightfv(lidx, GL_DIFFUSE, data); | 3460 | glLightfv(lidx, GL_DIFFUSE, data); |
3461 | 3461 | ||
3462 | // set specular color | 3462 | // set specular color |
3463 | data[0] = light.SpecularColor.r; | 3463 | data[0] = light.SpecularColor.r; |
3464 | data[1] = light.SpecularColor.g; | 3464 | data[1] = light.SpecularColor.g; |
3465 | data[2] = light.SpecularColor.b; | 3465 | data[2] = light.SpecularColor.b; |
3466 | data[3] = light.SpecularColor.a; | 3466 | data[3] = light.SpecularColor.a; |
3467 | glLightfv(lidx, GL_SPECULAR, data); | 3467 | glLightfv(lidx, GL_SPECULAR, data); |
3468 | 3468 | ||
3469 | // set ambient color | 3469 | // set ambient color |
3470 | data[0] = light.AmbientColor.r; | 3470 | data[0] = light.AmbientColor.r; |
3471 | data[1] = light.AmbientColor.g; | 3471 | data[1] = light.AmbientColor.g; |
3472 | data[2] = light.AmbientColor.b; | 3472 | data[2] = light.AmbientColor.b; |
3473 | data[3] = light.AmbientColor.a; | 3473 | data[3] = light.AmbientColor.a; |
3474 | glLightfv(lidx, GL_AMBIENT, data); | 3474 | glLightfv(lidx, GL_AMBIENT, data); |
3475 | 3475 | ||
3476 | // 1.0f / (constant + linear * d + quadratic*(d*d); | 3476 | // 1.0f / (constant + linear * d + quadratic*(d*d); |
3477 | 3477 | ||
3478 | // set attenuation | 3478 | // set attenuation |
3479 | glLightf(lidx, GL_CONSTANT_ATTENUATION, light.Attenuation.X); | 3479 | glLightf(lidx, GL_CONSTANT_ATTENUATION, light.Attenuation.X); |
3480 | glLightf(lidx, GL_LINEAR_ATTENUATION, light.Attenuation.Y); | 3480 | glLightf(lidx, GL_LINEAR_ATTENUATION, light.Attenuation.Y); |
3481 | glLightf(lidx, GL_QUADRATIC_ATTENUATION, light.Attenuation.Z); | 3481 | glLightf(lidx, GL_QUADRATIC_ATTENUATION, light.Attenuation.Z); |
3482 | 3482 | ||
3483 | glEnable(lidx); | 3483 | glEnable(lidx); |
3484 | } | 3484 | } |
3485 | 3485 | ||
3486 | 3486 | ||
3487 | //! Turns a dynamic light on or off | 3487 | //! Turns a dynamic light on or off |
3488 | //! \param lightIndex: the index returned by addDynamicLight | 3488 | //! \param lightIndex: the index returned by addDynamicLight |
3489 | //! \param turnOn: true to turn the light on, false to turn it off | 3489 | //! \param turnOn: true to turn the light on, false to turn it off |
3490 | void COpenGLDriver::turnLightOn(s32 lightIndex, bool turnOn) | 3490 | void COpenGLDriver::turnLightOn(s32 lightIndex, bool turnOn) |
3491 | { | 3491 | { |
3492 | if(lightIndex < 0 || lightIndex >= (s32)RequestedLights.size()) | 3492 | if(lightIndex < 0 || lightIndex >= (s32)RequestedLights.size()) |
3493 | return; | 3493 | return; |
3494 | 3494 | ||
3495 | RequestedLight & requestedLight = RequestedLights[lightIndex]; | 3495 | RequestedLight & requestedLight = RequestedLights[lightIndex]; |
3496 | 3496 | ||
3497 | requestedLight.DesireToBeOn = turnOn; | 3497 | requestedLight.DesireToBeOn = turnOn; |
3498 | 3498 | ||
3499 | if(turnOn) | 3499 | if(turnOn) |
3500 | { | 3500 | { |
3501 | if(-1 == requestedLight.HardwareLightIndex) | 3501 | if(-1 == requestedLight.HardwareLightIndex) |
3502 | assignHardwareLight(lightIndex); | 3502 | assignHardwareLight(lightIndex); |
3503 | } | 3503 | } |
3504 | else | 3504 | else |
3505 | { | 3505 | { |
3506 | if(-1 != requestedLight.HardwareLightIndex) | 3506 | if(-1 != requestedLight.HardwareLightIndex) |
3507 | { | 3507 | { |
3508 | // It's currently assigned, so free up the hardware light | 3508 | // It's currently assigned, so free up the hardware light |
3509 | glDisable(requestedLight.HardwareLightIndex); | 3509 | glDisable(requestedLight.HardwareLightIndex); |
3510 | requestedLight.HardwareLightIndex = -1; | 3510 | requestedLight.HardwareLightIndex = -1; |
3511 | 3511 | ||
3512 | // Now let the first light that's waiting on a free hardware light grab it | 3512 | // Now let the first light that's waiting on a free hardware light grab it |
3513 | for(u32 requested = 0; requested < RequestedLights.size(); ++requested) | 3513 | for(u32 requested = 0; requested < RequestedLights.size(); ++requested) |
3514 | if(RequestedLights[requested].DesireToBeOn | 3514 | if(RequestedLights[requested].DesireToBeOn |
3515 | && | 3515 | && |
3516 | -1 == RequestedLights[requested].HardwareLightIndex) | 3516 | -1 == RequestedLights[requested].HardwareLightIndex) |
3517 | { | 3517 | { |
3518 | assignHardwareLight(requested); | 3518 | assignHardwareLight(requested); |
3519 | break; | 3519 | break; |
3520 | } | 3520 | } |
3521 | } | 3521 | } |
3522 | } | 3522 | } |
3523 | } | 3523 | } |
3524 | 3524 | ||
3525 | 3525 | ||
3526 | //! returns the maximal amount of dynamic lights the device can handle | 3526 | //! returns the maximal amount of dynamic lights the device can handle |
3527 | u32 COpenGLDriver::getMaximalDynamicLightAmount() const | 3527 | u32 COpenGLDriver::getMaximalDynamicLightAmount() const |
3528 | { | 3528 | { |
3529 | return MaxLights; | 3529 | return MaxLights; |
3530 | } | 3530 | } |
3531 | 3531 | ||
3532 | 3532 | ||
3533 | //! Sets the dynamic ambient light color. The default color is | 3533 | //! Sets the dynamic ambient light color. The default color is |
3534 | //! (0,0,0,0) which means it is dark. | 3534 | //! (0,0,0,0) which means it is dark. |
3535 | //! \param color: New color of the ambient light. | 3535 | //! \param color: New color of the ambient light. |
3536 | void COpenGLDriver::setAmbientLight(const SColorf& color) | 3536 | void COpenGLDriver::setAmbientLight(const SColorf& color) |
3537 | { | 3537 | { |
3538 | GLfloat data[4] = {color.r, color.g, color.b, color.a}; | 3538 | GLfloat data[4] = {color.r, color.g, color.b, color.a}; |
3539 | glLightModelfv(GL_LIGHT_MODEL_AMBIENT, data); | 3539 | glLightModelfv(GL_LIGHT_MODEL_AMBIENT, data); |
3540 | } | 3540 | } |
3541 | 3541 | ||
3542 | 3542 | ||
3543 | // this code was sent in by Oliver Klems, thank you! (I modified the glViewport | 3543 | // this code was sent in by Oliver Klems, thank you! (I modified the glViewport |
3544 | // method just a bit. | 3544 | // method just a bit. |
3545 | void COpenGLDriver::setViewPort(const core::rect<s32>& area) | 3545 | void COpenGLDriver::setViewPort(const core::rect<s32>& area) |
3546 | { | 3546 | { |
3547 | if (area == ViewPort) | 3547 | if (area == ViewPort) |
3548 | return; | 3548 | return; |
3549 | core::rect<s32> vp = area; | 3549 | core::rect<s32> vp = area; |
3550 | core::rect<s32> rendert(0,0, getCurrentRenderTargetSize().Width, getCurrentRenderTargetSize().Height); | 3550 | core::rect<s32> rendert(0,0, getCurrentRenderTargetSize().Width, getCurrentRenderTargetSize().Height); |
3551 | vp.clipAgainst(rendert); | 3551 | vp.clipAgainst(rendert); |
3552 | 3552 | ||
3553 | if (vp.getHeight()>0 && vp.getWidth()>0) | 3553 | if (vp.getHeight()>0 && vp.getWidth()>0) |
3554 | { | 3554 | { |
3555 | glViewport(vp.UpperLeftCorner.X, | 3555 | glViewport(vp.UpperLeftCorner.X, |
3556 | getCurrentRenderTargetSize().Height - vp.UpperLeftCorner.Y - vp.getHeight(), | 3556 | getCurrentRenderTargetSize().Height - vp.UpperLeftCorner.Y - vp.getHeight(), |
3557 | vp.getWidth(), vp.getHeight()); | 3557 | vp.getWidth(), vp.getHeight()); |
3558 | 3558 | ||
3559 | ViewPort = vp; | 3559 | ViewPort = vp; |
3560 | } | 3560 | } |
3561 | } | 3561 | } |
3562 | 3562 | ||
3563 | 3563 | ||
3564 | //! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do | 3564 | //! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do |
3565 | //! this: First, draw all geometry. Then use this method, to draw the shadow | 3565 | //! this: First, draw all geometry. Then use this method, to draw the shadow |
3566 | //! volume. Next use IVideoDriver::drawStencilShadow() to visualize the shadow. | 3566 | //! volume. Next use IVideoDriver::drawStencilShadow() to visualize the shadow. |
3567 | void COpenGLDriver::drawStencilShadowVolume(const core::array<core::vector3df>& triangles, bool zfail, u32 debugDataVisible) | 3567 | void COpenGLDriver::drawStencilShadowVolume(const core::array<core::vector3df>& triangles, bool zfail, u32 debugDataVisible) |
3568 | { | 3568 | { |
3569 | const u32 count=triangles.size(); | 3569 | const u32 count=triangles.size(); |
3570 | if (!StencilBuffer || !count) | 3570 | if (!StencilBuffer || !count) |
3571 | return; | 3571 | return; |
3572 | 3572 | ||
3573 | // unset last 3d material | 3573 | // unset last 3d material |
3574 | if (CurrentRenderMode == ERM_3D && | 3574 | if (CurrentRenderMode == ERM_3D && |
3575 | static_cast<u32>(Material.MaterialType) < MaterialRenderers.size()) | 3575 | static_cast<u32>(Material.MaterialType) < MaterialRenderers.size()) |
3576 | { | 3576 | { |
3577 | MaterialRenderers[Material.MaterialType].Renderer->OnUnsetMaterial(); | 3577 | MaterialRenderers[Material.MaterialType].Renderer->OnUnsetMaterial(); |
3578 | ResetRenderStates = true; | 3578 | ResetRenderStates = true; |
3579 | } | 3579 | } |
3580 | 3580 | ||
3581 | // store current OpenGL state | 3581 | // store current OpenGL state |
3582 | glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | | 3582 | glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | |
3583 | GL_POLYGON_BIT | GL_STENCIL_BUFFER_BIT); | 3583 | GL_POLYGON_BIT | GL_STENCIL_BUFFER_BIT); |
3584 | 3584 | ||
3585 | glDisable(GL_LIGHTING); | 3585 | glDisable(GL_LIGHTING); |
3586 | glDisable(GL_FOG); | 3586 | glDisable(GL_FOG); |
3587 | glDepthFunc(GL_LESS); | 3587 | glDepthFunc(GL_LESS); |
3588 | glDepthMask(GL_FALSE); // no depth buffer writing | 3588 | glDepthMask(GL_FALSE); // no depth buffer writing |
3589 | if (debugDataVisible & scene::EDS_MESH_WIRE_OVERLAY) | 3589 | if (debugDataVisible & scene::EDS_MESH_WIRE_OVERLAY) |
3590 | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | 3590 | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); |
3591 | if (!(debugDataVisible & (scene::EDS_SKELETON|scene::EDS_MESH_WIRE_OVERLAY))) | 3591 | if (!(debugDataVisible & (scene::EDS_SKELETON|scene::EDS_MESH_WIRE_OVERLAY))) |
3592 | { | 3592 | { |
3593 | glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // no color buffer drawing | 3593 | glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // no color buffer drawing |
3594 | glEnable(GL_STENCIL_TEST); | 3594 | glEnable(GL_STENCIL_TEST); |
3595 | } | 3595 | } |
3596 | 3596 | ||
3597 | glEnableClientState(GL_VERTEX_ARRAY); | 3597 | glEnableClientState(GL_VERTEX_ARRAY); |
3598 | glVertexPointer(3,GL_FLOAT,sizeof(core::vector3df),triangles.const_pointer()); | 3598 | glVertexPointer(3,GL_FLOAT,sizeof(core::vector3df),triangles.const_pointer()); |
3599 | glStencilMask(~0); | 3599 | glStencilMask(~0); |
3600 | glStencilFunc(GL_ALWAYS, 0, ~0); | 3600 | glStencilFunc(GL_ALWAYS, 0, ~0); |
3601 | 3601 | ||
3602 | GLenum incr = GL_INCR; | 3602 | GLenum incr = GL_INCR; |
3603 | GLenum decr = GL_DECR; | 3603 | GLenum decr = GL_DECR; |
3604 | #ifdef GL_EXT_stencil_wrap | 3604 | #ifdef GL_EXT_stencil_wrap |
3605 | if (FeatureAvailable[IRR_EXT_stencil_wrap]) | 3605 | if (FeatureAvailable[IRR_EXT_stencil_wrap]) |
3606 | { | 3606 | { |
3607 | incr = GL_INCR_WRAP_EXT; | 3607 | incr = GL_INCR_WRAP_EXT; |
3608 | decr = GL_DECR_WRAP_EXT; | 3608 | decr = GL_DECR_WRAP_EXT; |
3609 | } | 3609 | } |
3610 | #endif | 3610 | #endif |
3611 | #ifdef GL_NV_depth_clamp | 3611 | #ifdef GL_NV_depth_clamp |
3612 | if (FeatureAvailable[IRR_NV_depth_clamp]) | 3612 | if (FeatureAvailable[IRR_NV_depth_clamp]) |
3613 | glEnable(GL_DEPTH_CLAMP_NV); | 3613 | glEnable(GL_DEPTH_CLAMP_NV); |
3614 | #endif | 3614 | #endif |
3615 | 3615 | ||
3616 | // The first parts are not correctly working, yet. | 3616 | // The first parts are not correctly working, yet. |
3617 | #if 0 | 3617 | #if 0 |
3618 | #ifdef GL_EXT_stencil_two_side | 3618 | #ifdef GL_EXT_stencil_two_side |
3619 | if (FeatureAvailable[IRR_EXT_stencil_two_side]) | 3619 | if (FeatureAvailable[IRR_EXT_stencil_two_side]) |
3620 | { | 3620 | { |
3621 | glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT); | 3621 | glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT); |
3622 | glDisable(GL_CULL_FACE); | 3622 | glDisable(GL_CULL_FACE); |
3623 | if (zfail) | 3623 | if (zfail) |
3624 | { | 3624 | { |
3625 | extGlActiveStencilFace(GL_BACK); | 3625 | extGlActiveStencilFace(GL_BACK); |
3626 | glStencilOp(GL_KEEP, incr, GL_KEEP); | 3626 | glStencilOp(GL_KEEP, incr, GL_KEEP); |
3627 | glStencilMask(~0); | 3627 | glStencilMask(~0); |
3628 | glStencilFunc(GL_ALWAYS, 0, ~0); | 3628 | glStencilFunc(GL_ALWAYS, 0, ~0); |
3629 | 3629 | ||
3630 | extGlActiveStencilFace(GL_FRONT); | 3630 | extGlActiveStencilFace(GL_FRONT); |
3631 | glStencilOp(GL_KEEP, decr, GL_KEEP); | 3631 | glStencilOp(GL_KEEP, decr, GL_KEEP); |
3632 | } | 3632 | } |
3633 | else // zpass | 3633 | else // zpass |
3634 | { | 3634 | { |
3635 | extGlActiveStencilFace(GL_BACK); | 3635 | extGlActiveStencilFace(GL_BACK); |
3636 | glStencilOp(GL_KEEP, GL_KEEP, decr); | 3636 | glStencilOp(GL_KEEP, GL_KEEP, decr); |
3637 | glStencilMask(~0); | 3637 | glStencilMask(~0); |
3638 | glStencilFunc(GL_ALWAYS, 0, ~0); | 3638 | glStencilFunc(GL_ALWAYS, 0, ~0); |
3639 | 3639 | ||
3640 | extGlActiveStencilFace(GL_FRONT); | 3640 | extGlActiveStencilFace(GL_FRONT); |
3641 | glStencilOp(GL_KEEP, GL_KEEP, incr); | 3641 | glStencilOp(GL_KEEP, GL_KEEP, incr); |
3642 | } | 3642 | } |
3643 | glStencilMask(~0); | 3643 | glStencilMask(~0); |
3644 | glStencilFunc(GL_ALWAYS, 0, ~0); | 3644 | glStencilFunc(GL_ALWAYS, 0, ~0); |
3645 | glDrawArrays(GL_TRIANGLES,0,count); | 3645 | glDrawArrays(GL_TRIANGLES,0,count); |
3646 | glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); | 3646 | glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); |
3647 | } | 3647 | } |
3648 | else | 3648 | else |
3649 | #endif | 3649 | #endif |
3650 | if (FeatureAvailable[IRR_ATI_separate_stencil]) | 3650 | if (FeatureAvailable[IRR_ATI_separate_stencil]) |
3651 | { | 3651 | { |
3652 | glDisable(GL_CULL_FACE); | 3652 | glDisable(GL_CULL_FACE); |
3653 | if (zfail) | 3653 | if (zfail) |
3654 | { | 3654 | { |
3655 | extGlStencilOpSeparate(GL_BACK, GL_KEEP, incr, GL_KEEP); | 3655 | extGlStencilOpSeparate(GL_BACK, GL_KEEP, incr, GL_KEEP); |
3656 | extGlStencilOpSeparate(GL_FRONT, GL_KEEP, decr, GL_KEEP); | 3656 | extGlStencilOpSeparate(GL_FRONT, GL_KEEP, decr, GL_KEEP); |
3657 | } | 3657 | } |
3658 | else // zpass | 3658 | else // zpass |
3659 | { | 3659 | { |
3660 | extGlStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, decr); | 3660 | extGlStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, decr); |
3661 | extGlStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, incr); | 3661 | extGlStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, incr); |
3662 | } | 3662 | } |
3663 | extGlStencilFuncSeparate(GL_ALWAYS, GL_ALWAYS, 0, ~0); | 3663 | extGlStencilFuncSeparate(GL_ALWAYS, GL_ALWAYS, 0, ~0); |
3664 | glStencilMask(~0); | 3664 | glStencilMask(~0); |
3665 | glDrawArrays(GL_TRIANGLES,0,count); | 3665 | glDrawArrays(GL_TRIANGLES,0,count); |
3666 | } | 3666 | } |
3667 | else | 3667 | else |
3668 | #endif | 3668 | #endif |
3669 | { | 3669 | { |
3670 | glEnable(GL_CULL_FACE); | 3670 | glEnable(GL_CULL_FACE); |
3671 | if (zfail) | 3671 | if (zfail) |
3672 | { | 3672 | { |
3673 | glCullFace(GL_FRONT); | 3673 | glCullFace(GL_FRONT); |
3674 | glStencilOp(GL_KEEP, incr, GL_KEEP); | 3674 | glStencilOp(GL_KEEP, incr, GL_KEEP); |
3675 | glDrawArrays(GL_TRIANGLES,0,count); | 3675 | glDrawArrays(GL_TRIANGLES,0,count); |
3676 | 3676 | ||
3677 | glCullFace(GL_BACK); | 3677 | glCullFace(GL_BACK); |
3678 | glStencilOp(GL_KEEP, decr, GL_KEEP); | 3678 | glStencilOp(GL_KEEP, decr, GL_KEEP); |
3679 | glDrawArrays(GL_TRIANGLES,0,count); | 3679 | glDrawArrays(GL_TRIANGLES,0,count); |
3680 | } | 3680 | } |
3681 | else // zpass | 3681 | else // zpass |
3682 | { | 3682 | { |
3683 | glCullFace(GL_BACK); | 3683 | glCullFace(GL_BACK); |
3684 | glStencilOp(GL_KEEP, GL_KEEP, incr); | 3684 | glStencilOp(GL_KEEP, GL_KEEP, incr); |
3685 | glDrawArrays(GL_TRIANGLES,0,count); | 3685 | glDrawArrays(GL_TRIANGLES,0,count); |
3686 | 3686 | ||
3687 | glCullFace(GL_FRONT); | 3687 | glCullFace(GL_FRONT); |
3688 | glStencilOp(GL_KEEP, GL_KEEP, decr); | 3688 | glStencilOp(GL_KEEP, GL_KEEP, decr); |
3689 | glDrawArrays(GL_TRIANGLES,0,count); | 3689 | glDrawArrays(GL_TRIANGLES,0,count); |
3690 | } | 3690 | } |
3691 | } | 3691 | } |
3692 | #ifdef GL_NV_depth_clamp | 3692 | #ifdef GL_NV_depth_clamp |
3693 | if (FeatureAvailable[IRR_NV_depth_clamp]) | 3693 | if (FeatureAvailable[IRR_NV_depth_clamp]) |
3694 | glDisable(GL_DEPTH_CLAMP_NV); | 3694 | glDisable(GL_DEPTH_CLAMP_NV); |
3695 | #endif | 3695 | #endif |
3696 | 3696 | ||
3697 | glDisable(GL_POLYGON_OFFSET_FILL); | 3697 | glDisable(GL_POLYGON_OFFSET_FILL); |
3698 | glDisableClientState(GL_VERTEX_ARRAY); //not stored on stack | 3698 | glDisableClientState(GL_VERTEX_ARRAY); //not stored on stack |
3699 | glPopAttrib(); | 3699 | glPopAttrib(); |
3700 | } | 3700 | } |
3701 | 3701 | ||
3702 | //! Fills the stencil shadow with color. After the shadow volume has been drawn | 3702 | //! Fills the stencil shadow with color. After the shadow volume has been drawn |
3703 | //! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this | 3703 | //! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this |
3704 | //! to draw the color of the shadow. | 3704 | //! to draw the color of the shadow. |
3705 | void COpenGLDriver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftUpEdge, | 3705 | void COpenGLDriver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftUpEdge, |
3706 | video::SColor rightUpEdge, video::SColor leftDownEdge, video::SColor rightDownEdge) | 3706 | video::SColor rightUpEdge, video::SColor leftDownEdge, video::SColor rightDownEdge) |
3707 | { | 3707 | { |
3708 | if (!StencilBuffer) | 3708 | if (!StencilBuffer) |
3709 | return; | 3709 | return; |
3710 | 3710 | ||
3711 | disableTextures(); | 3711 | disableTextures(); |
3712 | 3712 | ||
3713 | // store attributes | 3713 | // store attributes |
3714 | glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT | GL_STENCIL_BUFFER_BIT | GL_LIGHTING_BIT); | 3714 | glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT | GL_STENCIL_BUFFER_BIT | GL_LIGHTING_BIT); |
3715 | 3715 | ||
3716 | glDisable(GL_LIGHTING); | 3716 | glDisable(GL_LIGHTING); |
3717 | glDisable(GL_FOG); | 3717 | glDisable(GL_FOG); |
3718 | glDepthMask(GL_FALSE); | 3718 | glDepthMask(GL_FALSE); |
3719 | 3719 | ||
3720 | glShadeModel(GL_FLAT); | 3720 | glShadeModel(GL_FLAT); |
3721 | glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | 3721 | glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
3722 | 3722 | ||
3723 | glEnable(GL_BLEND); | 3723 | glEnable(GL_BLEND); |
3724 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 3724 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
3725 | 3725 | ||
3726 | glEnable(GL_STENCIL_TEST); | 3726 | glEnable(GL_STENCIL_TEST); |
3727 | glStencilFunc(GL_NOTEQUAL, 0, ~0); | 3727 | glStencilFunc(GL_NOTEQUAL, 0, ~0); |
3728 | glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); | 3728 | glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); |
3729 | 3729 | ||
3730 | // draw a shadow rectangle covering the entire screen using stencil buffer | 3730 | // draw a shadow rectangle covering the entire screen using stencil buffer |
3731 | glMatrixMode(GL_MODELVIEW); | 3731 | glMatrixMode(GL_MODELVIEW); |
3732 | glPushMatrix(); | 3732 | glPushMatrix(); |
3733 | glLoadIdentity(); | 3733 | glLoadIdentity(); |
3734 | glMatrixMode(GL_PROJECTION); | 3734 | glMatrixMode(GL_PROJECTION); |
3735 | glPushMatrix(); | 3735 | glPushMatrix(); |
3736 | glLoadIdentity(); | 3736 | glLoadIdentity(); |
3737 | 3737 | ||
3738 | glBegin(GL_QUADS); | 3738 | glBegin(GL_QUADS); |
3739 | 3739 | ||
3740 | glColor4ub(leftDownEdge.getRed(), leftDownEdge.getGreen(), leftDownEdge.getBlue(), leftDownEdge.getAlpha()); | 3740 | glColor4ub(leftDownEdge.getRed(), leftDownEdge.getGreen(), leftDownEdge.getBlue(), leftDownEdge.getAlpha()); |
3741 | glVertex3f(-1.f,-1.f,-0.9f); | 3741 | glVertex3f(-1.f,-1.f,-0.9f); |
3742 | 3742 | ||
3743 | glColor4ub(leftUpEdge.getRed(), leftUpEdge.getGreen(), leftUpEdge.getBlue(), leftUpEdge.getAlpha()); | 3743 | glColor4ub(leftUpEdge.getRed(), leftUpEdge.getGreen(), leftUpEdge.getBlue(), leftUpEdge.getAlpha()); |
3744 | glVertex3f(-1.f, 1.f,-0.9f); | 3744 | glVertex3f(-1.f, 1.f,-0.9f); |
3745 | 3745 | ||
3746 | glColor4ub(rightUpEdge.getRed(), rightUpEdge.getGreen(), rightUpEdge.getBlue(), rightUpEdge.getAlpha()); | 3746 | glColor4ub(rightUpEdge.getRed(), rightUpEdge.getGreen(), rightUpEdge.getBlue(), rightUpEdge.getAlpha()); |
3747 | glVertex3f(1.f, 1.f,-0.9f); | 3747 | glVertex3f(1.f, 1.f,-0.9f); |
3748 | 3748 | ||
3749 | glColor4ub(rightDownEdge.getRed(), rightDownEdge.getGreen(), rightDownEdge.getBlue(), rightDownEdge.getAlpha()); | 3749 | glColor4ub(rightDownEdge.getRed(), rightDownEdge.getGreen(), rightDownEdge.getBlue(), rightDownEdge.getAlpha()); |
3750 | glVertex3f(1.f,-1.f,-0.9f); | 3750 | glVertex3f(1.f,-1.f,-0.9f); |
3751 | 3751 | ||
3752 | glEnd(); | 3752 | glEnd(); |
3753 | 3753 | ||
3754 | clearBuffers(false, false, clearStencilBuffer, 0x0); | 3754 | clearBuffers(false, false, clearStencilBuffer, 0x0); |
3755 | 3755 | ||
3756 | // restore settings | 3756 | // restore settings |
3757 | glPopMatrix(); | 3757 | glPopMatrix(); |
3758 | glMatrixMode(GL_MODELVIEW); | 3758 | glMatrixMode(GL_MODELVIEW); |
3759 | glPopMatrix(); | 3759 | glPopMatrix(); |
3760 | glPopAttrib(); | 3760 | glPopAttrib(); |
3761 | } | 3761 | } |
3762 | 3762 | ||
3763 | 3763 | ||
3764 | //! Sets the fog mode. | 3764 | //! Sets the fog mode. |
3765 | void COpenGLDriver::setFog(SColor c, E_FOG_TYPE fogType, f32 start, | 3765 | void COpenGLDriver::setFog(SColor c, E_FOG_TYPE fogType, f32 start, |
3766 | f32 end, f32 density, bool pixelFog, bool rangeFog) | 3766 | f32 end, f32 density, bool pixelFog, bool rangeFog) |
3767 | { | 3767 | { |
3768 | CNullDriver::setFog(c, fogType, start, end, density, pixelFog, rangeFog); | 3768 | CNullDriver::setFog(c, fogType, start, end, density, pixelFog, rangeFog); |
3769 | 3769 | ||
3770 | glFogf(GL_FOG_MODE, GLfloat((fogType==EFT_FOG_LINEAR)? GL_LINEAR : (fogType==EFT_FOG_EXP)?GL_EXP:GL_EXP2)); | 3770 | glFogf(GL_FOG_MODE, GLfloat((fogType==EFT_FOG_LINEAR)? GL_LINEAR : (fogType==EFT_FOG_EXP)?GL_EXP:GL_EXP2)); |
3771 | 3771 | ||
3772 | #ifdef GL_EXT_fog_coord | 3772 | #ifdef GL_EXT_fog_coord |
3773 | if (FeatureAvailable[IRR_EXT_fog_coord]) | 3773 | if (FeatureAvailable[IRR_EXT_fog_coord]) |
3774 | glFogi(GL_FOG_COORDINATE_SOURCE, GL_FRAGMENT_DEPTH); | 3774 | glFogi(GL_FOG_COORDINATE_SOURCE, GL_FRAGMENT_DEPTH); |
3775 | #endif | 3775 | #endif |
3776 | #ifdef GL_NV_fog_distance | 3776 | #ifdef GL_NV_fog_distance |
3777 | if (FeatureAvailable[IRR_NV_fog_distance]) | 3777 | if (FeatureAvailable[IRR_NV_fog_distance]) |
3778 | { | 3778 | { |
3779 | if (rangeFog) | 3779 | if (rangeFog) |
3780 | glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV); | 3780 | glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV); |
3781 | else | 3781 | else |
3782 | glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV); | 3782 | glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV); |
3783 | } | 3783 | } |
3784 | #endif | 3784 | #endif |
3785 | 3785 | ||
3786 | if (fogType==EFT_FOG_LINEAR) | 3786 | if (fogType==EFT_FOG_LINEAR) |
3787 | { | 3787 | { |
3788 | glFogf(GL_FOG_START, start); | 3788 | glFogf(GL_FOG_START, start); |
3789 | glFogf(GL_FOG_END, end); | 3789 | glFogf(GL_FOG_END, end); |
3790 | } | 3790 | } |
3791 | else | 3791 | else |
3792 | glFogf(GL_FOG_DENSITY, density); | 3792 | glFogf(GL_FOG_DENSITY, density); |
3793 | 3793 | ||
3794 | if (pixelFog) | 3794 | if (pixelFog) |
3795 | glHint(GL_FOG_HINT, GL_NICEST); | 3795 | glHint(GL_FOG_HINT, GL_NICEST); |
3796 | else | 3796 | else |
3797 | glHint(GL_FOG_HINT, GL_FASTEST); | 3797 | glHint(GL_FOG_HINT, GL_FASTEST); |
3798 | 3798 | ||
3799 | SColorf color(c); | 3799 | SColorf color(c); |
3800 | GLfloat data[4] = {color.r, color.g, color.b, color.a}; | 3800 | GLfloat data[4] = {color.r, color.g, color.b, color.a}; |
3801 | glFogfv(GL_FOG_COLOR, data); | 3801 | glFogfv(GL_FOG_COLOR, data); |
3802 | } | 3802 | } |
3803 | 3803 | ||
3804 | 3804 | ||
3805 | //! Draws a 3d line. | 3805 | //! Draws a 3d line. |
3806 | void COpenGLDriver::draw3DLine(const core::vector3df& start, | 3806 | void COpenGLDriver::draw3DLine(const core::vector3df& start, |
3807 | const core::vector3df& end, SColor color) | 3807 | const core::vector3df& end, SColor color) |
3808 | { | 3808 | { |
3809 | setRenderStates3DMode(); | 3809 | setRenderStates3DMode(); |
3810 | 3810 | ||
3811 | glBegin(GL_LINES); | 3811 | glBegin(GL_LINES); |
3812 | glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); | 3812 | glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); |
3813 | glVertex3f(start.X, start.Y, start.Z); | 3813 | glVertex3f(start.X, start.Y, start.Z); |
3814 | 3814 | ||
3815 | glVertex3f(end.X, end.Y, end.Z); | 3815 | glVertex3f(end.X, end.Y, end.Z); |
3816 | glEnd(); | 3816 | glEnd(); |
3817 | } | 3817 | } |
3818 | 3818 | ||
3819 | 3819 | ||
3820 | //! Removes a texture from the texture cache and deletes it, freeing lot of memory. | 3820 | //! Removes a texture from the texture cache and deletes it, freeing lot of memory. |
3821 | void COpenGLDriver::removeTexture(ITexture* texture) | 3821 | void COpenGLDriver::removeTexture(ITexture* texture) |
3822 | { | 3822 | { |
3823 | if (!texture) | 3823 | if (!texture) |
3824 | return; | 3824 | return; |
3825 | 3825 | ||
3826 | CNullDriver::removeTexture(texture); | 3826 | CNullDriver::removeTexture(texture); |
3827 | // Remove this texture from CurrentTexture as well | 3827 | // Remove this texture from CurrentTexture as well |
3828 | CurrentTexture.remove(texture); | 3828 | CurrentTexture.remove(texture); |
3829 | } | 3829 | } |
3830 | 3830 | ||
3831 | 3831 | ||
3832 | //! Only used by the internal engine. Used to notify the driver that | 3832 | //! Only used by the internal engine. Used to notify the driver that |
3833 | //! the window was resized. | 3833 | //! the window was resized. |
3834 | void COpenGLDriver::OnResize(const core::dimension2d<u32>& size) | 3834 | void COpenGLDriver::OnResize(const core::dimension2d<u32>& size) |
3835 | { | 3835 | { |
3836 | CNullDriver::OnResize(size); | 3836 | CNullDriver::OnResize(size); |
3837 | glViewport(0, 0, size.Width, size.Height); | 3837 | glViewport(0, 0, size.Width, size.Height); |
3838 | Transformation3DChanged = true; | 3838 | Transformation3DChanged = true; |
3839 | } | 3839 | } |
3840 | 3840 | ||
3841 | 3841 | ||
3842 | //! Returns type of video driver | 3842 | //! Returns type of video driver |
3843 | E_DRIVER_TYPE COpenGLDriver::getDriverType() const | 3843 | E_DRIVER_TYPE COpenGLDriver::getDriverType() const |
3844 | { | 3844 | { |
3845 | return EDT_OPENGL; | 3845 | return EDT_OPENGL; |
3846 | } | 3846 | } |
3847 | 3847 | ||
3848 | 3848 | ||
3849 | //! returns color format | 3849 | //! returns color format |
3850 | ECOLOR_FORMAT COpenGLDriver::getColorFormat() const | 3850 | ECOLOR_FORMAT COpenGLDriver::getColorFormat() const |
3851 | { | 3851 | { |
3852 | return ColorFormat; | 3852 | return ColorFormat; |
3853 | } | 3853 | } |
3854 | 3854 | ||
3855 | 3855 | ||
3856 | //! Sets a vertex shader constant. | 3856 | //! Sets a vertex shader constant. |
3857 | void COpenGLDriver::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) | 3857 | void COpenGLDriver::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) |
3858 | { | 3858 | { |
3859 | #ifdef GL_ARB_vertex_program | 3859 | #ifdef GL_ARB_vertex_program |
3860 | for (s32 i=0; i<constantAmount; ++i) | 3860 | for (s32 i=0; i<constantAmount; ++i) |
3861 | extGlProgramLocalParameter4fv(GL_VERTEX_PROGRAM_ARB, startRegister+i, &data[i*4]); | 3861 | extGlProgramLocalParameter4fv(GL_VERTEX_PROGRAM_ARB, startRegister+i, &data[i*4]); |
3862 | #endif | 3862 | #endif |
3863 | } | 3863 | } |
3864 | 3864 | ||
3865 | //! Sets a pixel shader constant. | 3865 | //! Sets a pixel shader constant. |
3866 | void COpenGLDriver::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) | 3866 | void COpenGLDriver::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) |
3867 | { | 3867 | { |
3868 | #ifdef GL_ARB_fragment_program | 3868 | #ifdef GL_ARB_fragment_program |
3869 | for (s32 i=0; i<constantAmount; ++i) | 3869 | for (s32 i=0; i<constantAmount; ++i) |
3870 | extGlProgramLocalParameter4fv(GL_FRAGMENT_PROGRAM_ARB, startRegister+i, &data[i*4]); | 3870 | extGlProgramLocalParameter4fv(GL_FRAGMENT_PROGRAM_ARB, startRegister+i, &data[i*4]); |
3871 | #endif | 3871 | #endif |
3872 | } | 3872 | } |
3873 | 3873 | ||
3874 | //! Sets a constant for the vertex shader based on a name. | 3874 | //! Sets a constant for the vertex shader based on a name. |
3875 | bool COpenGLDriver::setVertexShaderConstant(const c8* name, const f32* floats, int count) | 3875 | bool COpenGLDriver::setVertexShaderConstant(const c8* name, const f32* floats, int count) |
3876 | { | 3876 | { |
3877 | //pass this along, as in GLSL the same routine is used for both vertex and fragment shaders | 3877 | //pass this along, as in GLSL the same routine is used for both vertex and fragment shaders |
3878 | return setPixelShaderConstant(name, floats, count); | 3878 | return setPixelShaderConstant(name, floats, count); |
3879 | } | 3879 | } |
3880 | 3880 | ||
3881 | //! Bool interface for the above. | 3881 | //! Bool interface for the above. |
3882 | bool COpenGLDriver::setVertexShaderConstant(const c8* name, const bool* bools, int count) | 3882 | bool COpenGLDriver::setVertexShaderConstant(const c8* name, const bool* bools, int count) |
3883 | { | 3883 | { |
3884 | return setPixelShaderConstant(name, bools, count); | 3884 | return setPixelShaderConstant(name, bools, count); |
3885 | } | 3885 | } |
3886 | 3886 | ||
3887 | //! Int interface for the above. | 3887 | //! Int interface for the above. |
3888 | bool COpenGLDriver::setVertexShaderConstant(const c8* name, const s32* ints, int count) | 3888 | bool COpenGLDriver::setVertexShaderConstant(const c8* name, const s32* ints, int count) |
3889 | { | 3889 | { |
3890 | return setPixelShaderConstant(name, ints, count); | 3890 | return setPixelShaderConstant(name, ints, count); |
3891 | } | 3891 | } |
3892 | 3892 | ||
3893 | //! Sets a constant for the pixel shader based on a name. | 3893 | //! Sets a constant for the pixel shader based on a name. |
3894 | bool COpenGLDriver::setPixelShaderConstant(const c8* name, const f32* floats, int count) | 3894 | bool COpenGLDriver::setPixelShaderConstant(const c8* name, const f32* floats, int count) |
3895 | { | 3895 | { |
3896 | os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant()."); | 3896 | os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant()."); |
3897 | return false; | 3897 | return false; |
3898 | } | 3898 | } |
3899 | 3899 | ||
3900 | //! Bool interface for the above. | 3900 | //! Bool interface for the above. |
3901 | bool COpenGLDriver::setPixelShaderConstant(const c8* name, const bool* bools, int count) | 3901 | bool COpenGLDriver::setPixelShaderConstant(const c8* name, const bool* bools, int count) |
3902 | { | 3902 | { |
3903 | os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant()."); | 3903 | os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant()."); |
3904 | return false; | 3904 | return false; |
3905 | } | 3905 | } |
3906 | 3906 | ||
3907 | //! Int interface for the above. | 3907 | //! Int interface for the above. |
3908 | bool COpenGLDriver::setPixelShaderConstant(const c8* name, const s32* ints, int count) | 3908 | bool COpenGLDriver::setPixelShaderConstant(const c8* name, const s32* ints, int count) |
3909 | { | 3909 | { |
3910 | os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant()."); | 3910 | os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant()."); |
3911 | return false; | 3911 | return false; |
3912 | } | 3912 | } |
3913 | 3913 | ||
3914 | 3914 | ||
3915 | //! Adds a new material renderer to the VideoDriver, using pixel and/or | 3915 | //! Adds a new material renderer to the VideoDriver, using pixel and/or |
3916 | //! vertex shaders to render geometry. | 3916 | //! vertex shaders to render geometry. |
3917 | s32 COpenGLDriver::addShaderMaterial(const c8* vertexShaderProgram, | 3917 | s32 COpenGLDriver::addShaderMaterial(const c8* vertexShaderProgram, |
3918 | const c8* pixelShaderProgram, | 3918 | const c8* pixelShaderProgram, |
3919 | IShaderConstantSetCallBack* callback, | 3919 | IShaderConstantSetCallBack* callback, |
3920 | E_MATERIAL_TYPE baseMaterial, s32 userData) | 3920 | E_MATERIAL_TYPE baseMaterial, s32 userData) |
3921 | { | 3921 | { |
3922 | s32 nr = -1; | 3922 | s32 nr = -1; |
3923 | COpenGLShaderMaterialRenderer* r = new COpenGLShaderMaterialRenderer( | 3923 | COpenGLShaderMaterialRenderer* r = new COpenGLShaderMaterialRenderer( |
3924 | this, nr, vertexShaderProgram, pixelShaderProgram, | 3924 | this, nr, vertexShaderProgram, pixelShaderProgram, |
3925 | callback, getMaterialRenderer(baseMaterial), userData); | 3925 | callback, getMaterialRenderer(baseMaterial), userData); |
3926 | 3926 | ||
3927 | r->drop(); | 3927 | r->drop(); |
3928 | return nr; | 3928 | return nr; |
3929 | } | 3929 | } |
3930 | 3930 | ||
3931 | 3931 | ||
3932 | //! Adds a new material renderer to the VideoDriver, using GLSL to render geometry. | 3932 | //! Adds a new material renderer to the VideoDriver, using GLSL to render geometry. |
3933 | s32 COpenGLDriver::addHighLevelShaderMaterial( | 3933 | s32 COpenGLDriver::addHighLevelShaderMaterial( |
3934 | const c8* vertexShaderProgram, | 3934 | const c8* vertexShaderProgram, |
3935 | const c8* vertexShaderEntryPointName, | 3935 | const c8* vertexShaderEntryPointName, |
3936 | E_VERTEX_SHADER_TYPE vsCompileTarget, | 3936 | E_VERTEX_SHADER_TYPE vsCompileTarget, |
3937 | const c8* pixelShaderProgram, | 3937 | const c8* pixelShaderProgram, |
3938 | const c8* pixelShaderEntryPointName, | 3938 | const c8* pixelShaderEntryPointName, |
3939 | E_PIXEL_SHADER_TYPE psCompileTarget, | 3939 | E_PIXEL_SHADER_TYPE psCompileTarget, |
3940 | const c8* geometryShaderProgram, | 3940 | const c8* geometryShaderProgram, |
3941 | const c8* geometryShaderEntryPointName, | 3941 | const c8* geometryShaderEntryPointName, |
3942 | E_GEOMETRY_SHADER_TYPE gsCompileTarget, | 3942 | E_GEOMETRY_SHADER_TYPE gsCompileTarget, |
3943 | scene::E_PRIMITIVE_TYPE inType, | 3943 | scene::E_PRIMITIVE_TYPE inType, |
3944 | scene::E_PRIMITIVE_TYPE outType, | 3944 | scene::E_PRIMITIVE_TYPE outType, |
3945 | u32 verticesOut, | 3945 | u32 verticesOut, |
3946 | IShaderConstantSetCallBack* callback, | 3946 | IShaderConstantSetCallBack* callback, |
3947 | E_MATERIAL_TYPE baseMaterial, | 3947 | E_MATERIAL_TYPE baseMaterial, |
3948 | s32 userData, E_GPU_SHADING_LANGUAGE shadingLang) | 3948 | s32 userData, E_GPU_SHADING_LANGUAGE shadingLang) |
3949 | { | 3949 | { |
3950 | s32 nr = -1; | 3950 | s32 nr = -1; |
3951 | 3951 | ||
3952 | #ifdef _IRR_COMPILE_WITH_CG_ | 3952 | #ifdef _IRR_COMPILE_WITH_CG_ |
3953 | if (shadingLang == EGSL_CG) | 3953 | if (shadingLang == EGSL_CG) |
3954 | { | 3954 | { |
3955 | COpenGLCgMaterialRenderer* r = new COpenGLCgMaterialRenderer( | 3955 | COpenGLCgMaterialRenderer* r = new COpenGLCgMaterialRenderer( |
3956 | this, nr, | 3956 | this, nr, |
3957 | vertexShaderProgram, vertexShaderEntryPointName, vsCompileTarget, | 3957 | vertexShaderProgram, vertexShaderEntryPointName, vsCompileTarget, |
3958 | pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget, | 3958 | pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget, |
3959 | geometryShaderProgram, geometryShaderEntryPointName, gsCompileTarget, | 3959 | geometryShaderProgram, geometryShaderEntryPointName, gsCompileTarget, |
3960 | inType, outType, verticesOut, | 3960 | inType, outType, verticesOut, |
3961 | callback,getMaterialRenderer(baseMaterial), userData); | 3961 | callback,getMaterialRenderer(baseMaterial), userData); |
3962 | 3962 | ||
3963 | r->drop(); | 3963 | r->drop(); |
3964 | } | 3964 | } |
3965 | else | 3965 | else |
3966 | #endif | 3966 | #endif |
3967 | { | 3967 | { |
3968 | COpenGLSLMaterialRenderer* r = new COpenGLSLMaterialRenderer( | 3968 | COpenGLSLMaterialRenderer* r = new COpenGLSLMaterialRenderer( |
3969 | this, nr, | 3969 | this, nr, |
3970 | vertexShaderProgram, vertexShaderEntryPointName, vsCompileTarget, | 3970 | vertexShaderProgram, vertexShaderEntryPointName, vsCompileTarget, |
3971 | pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget, | 3971 | pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget, |
3972 | geometryShaderProgram, geometryShaderEntryPointName, gsCompileTarget, | 3972 | geometryShaderProgram, geometryShaderEntryPointName, gsCompileTarget, |
3973 | inType, outType, verticesOut, | 3973 | inType, outType, verticesOut, |
3974 | callback,getMaterialRenderer(baseMaterial), userData); | 3974 | callback,getMaterialRenderer(baseMaterial), userData); |
3975 | 3975 | ||
3976 | r->drop(); | 3976 | r->drop(); |
3977 | } | 3977 | } |
3978 | 3978 | ||
3979 | return nr; | 3979 | return nr; |
3980 | } | 3980 | } |
3981 | 3981 | ||
3982 | 3982 | ||
3983 | //! Returns a pointer to the IVideoDriver interface. (Implementation for | 3983 | //! Returns a pointer to the IVideoDriver interface. (Implementation for |
3984 | //! IMaterialRendererServices) | 3984 | //! IMaterialRendererServices) |
3985 | IVideoDriver* COpenGLDriver::getVideoDriver() | 3985 | IVideoDriver* COpenGLDriver::getVideoDriver() |
3986 | { | 3986 | { |
3987 | return this; | 3987 | return this; |
3988 | } | 3988 | } |
3989 | 3989 | ||
3990 | 3990 | ||
3991 | ITexture* COpenGLDriver::addRenderTargetTexture(const core::dimension2d<u32>& size, | 3991 | ITexture* COpenGLDriver::addRenderTargetTexture(const core::dimension2d<u32>& size, |
3992 | const io::path& name, | 3992 | const io::path& name, |
3993 | const ECOLOR_FORMAT format) | 3993 | const ECOLOR_FORMAT format) |
3994 | { | 3994 | { |
3995 | //disable mip-mapping | 3995 | //disable mip-mapping |
3996 | bool generateMipLevels = getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); | 3996 | bool generateMipLevels = getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); |
3997 | setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false); | 3997 | setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false); |
3998 | 3998 | ||
3999 | video::ITexture* rtt = 0; | 3999 | video::ITexture* rtt = 0; |
4000 | #if defined(GL_EXT_framebuffer_object) | 4000 | #if defined(GL_EXT_framebuffer_object) |
4001 | // if driver supports FrameBufferObjects, use them | 4001 | // if driver supports FrameBufferObjects, use them |
4002 | if (queryFeature(EVDF_FRAMEBUFFER_OBJECT)) | 4002 | if (queryFeature(EVDF_FRAMEBUFFER_OBJECT)) |
4003 | { | 4003 | { |
4004 | rtt = new COpenGLFBOTexture(size, name, this, format); | 4004 | rtt = new COpenGLFBOTexture(size, name, this, format); |
4005 | if (rtt) | 4005 | if (rtt) |
4006 | { | 4006 | { |
4007 | bool success = false; | 4007 | bool success = false; |
4008 | addTexture(rtt); | 4008 | addTexture(rtt); |
4009 | ITexture* tex = createDepthTexture(rtt); | 4009 | ITexture* tex = createDepthTexture(rtt); |
4010 | if (tex) | 4010 | if (tex) |
4011 | { | 4011 | { |
4012 | success = static_cast<video::COpenGLFBODepthTexture*>(tex)->attach(rtt); | 4012 | success = static_cast<video::COpenGLFBODepthTexture*>(tex)->attach(rtt); |
4013 | if ( !success ) | 4013 | if ( !success ) |
4014 | { | 4014 | { |
4015 | removeDepthTexture(tex); | 4015 | removeDepthTexture(tex); |
4016 | } | 4016 | } |
4017 | tex->drop(); | 4017 | tex->drop(); |
4018 | } | 4018 | } |
4019 | rtt->drop(); | 4019 | rtt->drop(); |
4020 | if (!success) | 4020 | if (!success) |
4021 | { | 4021 | { |
4022 | removeTexture(rtt); | 4022 | removeTexture(rtt); |
4023 | rtt=0; | 4023 | rtt=0; |
4024 | } | 4024 | } |
4025 | } | 4025 | } |
4026 | } | 4026 | } |
4027 | else | 4027 | else |
4028 | #endif | 4028 | #endif |
4029 | { | 4029 | { |
4030 | // the simple texture is only possible for size <= screensize | 4030 | // the simple texture is only possible for size <= screensize |
4031 | // we try to find an optimal size with the original constraints | 4031 | // we try to find an optimal size with the original constraints |
4032 | core::dimension2du destSize(core::min_(size.Width,ScreenSize.Width), core::min_(size.Height,ScreenSize.Height)); | 4032 | core::dimension2du destSize(core::min_(size.Width,ScreenSize.Width), core::min_(size.Height,ScreenSize.Height)); |
4033 | destSize = destSize.getOptimalSize((size==size.getOptimalSize()), false, false); | 4033 | destSize = destSize.getOptimalSize((size==size.getOptimalSize()), false, false); |
4034 | rtt = addTexture(destSize, name, ECF_A8R8G8B8); | 4034 | rtt = addTexture(destSize, name, ECF_A8R8G8B8); |
4035 | if (rtt) | 4035 | if (rtt) |
4036 | { | 4036 | { |
4037 | static_cast<video::COpenGLTexture*>(rtt)->setIsRenderTarget(true); | 4037 | static_cast<video::COpenGLTexture*>(rtt)->setIsRenderTarget(true); |
4038 | } | 4038 | } |
4039 | } | 4039 | } |
4040 | 4040 | ||
4041 | //restore mip-mapping | 4041 | //restore mip-mapping |
4042 | setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, generateMipLevels); | 4042 | setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, generateMipLevels); |
4043 | 4043 | ||
4044 | return rtt; | 4044 | return rtt; |
4045 | } | 4045 | } |
4046 | 4046 | ||
4047 | 4047 | ||
4048 | //! Returns the maximum amount of primitives (mostly vertices) which | 4048 | //! Returns the maximum amount of primitives (mostly vertices) which |
4049 | //! the device is able to render with one drawIndexedTriangleList | 4049 | //! the device is able to render with one drawIndexedTriangleList |
4050 | //! call. | 4050 | //! call. |
4051 | u32 COpenGLDriver::getMaximalPrimitiveCount() const | 4051 | u32 COpenGLDriver::getMaximalPrimitiveCount() const |
4052 | { | 4052 | { |
4053 | return 0x7fffffff; | 4053 | return 0x7fffffff; |
4054 | } | 4054 | } |
4055 | 4055 | ||
4056 | 4056 | ||
4057 | //! set or reset render target | 4057 | //! set or reset render target |
4058 | bool COpenGLDriver::setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget, | 4058 | bool COpenGLDriver::setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget, |
4059 | bool clearZBuffer, SColor color) | 4059 | bool clearZBuffer, SColor color) |
4060 | { | 4060 | { |
4061 | if (target != CurrentTarget) | 4061 | if (target != CurrentTarget) |
4062 | setRenderTarget(0, false, false, 0x0); | 4062 | setRenderTarget(0, false, false, 0x0); |
4063 | 4063 | ||
4064 | if (ERT_RENDER_TEXTURE == target) | 4064 | if (ERT_RENDER_TEXTURE == target) |
4065 | { | 4065 | { |
4066 | os::Printer::log("For render textures call setRenderTarget with the actual texture as first parameter.", ELL_ERROR); | 4066 | os::Printer::log("For render textures call setRenderTarget with the actual texture as first parameter.", ELL_ERROR); |
4067 | return false; | 4067 | return false; |
4068 | } | 4068 | } |
4069 | if (ERT_MULTI_RENDER_TEXTURES == target) | 4069 | if (ERT_MULTI_RENDER_TEXTURES == target) |
4070 | { | 4070 | { |
4071 | os::Printer::log("For multiple render textures call setRenderTarget with the texture array as first parameter.", ELL_ERROR); | 4071 | os::Printer::log("For multiple render textures call setRenderTarget with the texture array as first parameter.", ELL_ERROR); |
4072 | return false; | 4072 | return false; |
4073 | } | 4073 | } |
4074 | 4074 | ||
4075 | if (Params.Stereobuffer && (ERT_STEREO_RIGHT_BUFFER == target)) | 4075 | if (Params.Stereobuffer && (ERT_STEREO_RIGHT_BUFFER == target)) |
4076 | { | 4076 | { |
4077 | if (Params.Doublebuffer) | 4077 | if (Params.Doublebuffer) |
4078 | glDrawBuffer(GL_BACK_RIGHT); | 4078 | glDrawBuffer(GL_BACK_RIGHT); |
4079 | else | 4079 | else |
4080 | glDrawBuffer(GL_FRONT_RIGHT); | 4080 | glDrawBuffer(GL_FRONT_RIGHT); |
4081 | } | 4081 | } |
4082 | else if (Params.Stereobuffer && ERT_STEREO_BOTH_BUFFERS == target) | 4082 | else if (Params.Stereobuffer && ERT_STEREO_BOTH_BUFFERS == target) |
4083 | { | 4083 | { |
4084 | if (Params.Doublebuffer) | 4084 | if (Params.Doublebuffer) |
4085 | glDrawBuffer(GL_BACK); | 4085 | glDrawBuffer(GL_BACK); |
4086 | else | 4086 | else |
4087 | glDrawBuffer(GL_FRONT); | 4087 | glDrawBuffer(GL_FRONT); |
4088 | } | 4088 | } |
4089 | else if ((target >= ERT_AUX_BUFFER0) && (target-ERT_AUX_BUFFER0 < MaxAuxBuffers)) | 4089 | else if ((target >= ERT_AUX_BUFFER0) && (target-ERT_AUX_BUFFER0 < MaxAuxBuffers)) |
4090 | { | 4090 | { |
4091 | glDrawBuffer(GL_AUX0+target-ERT_AUX_BUFFER0); | 4091 | glDrawBuffer(GL_AUX0+target-ERT_AUX_BUFFER0); |
4092 | } | 4092 | } |
4093 | else | 4093 | else |
4094 | { | 4094 | { |
4095 | if (Params.Doublebuffer) | 4095 | if (Params.Doublebuffer) |
4096 | glDrawBuffer(GL_BACK_LEFT); | 4096 | glDrawBuffer(GL_BACK_LEFT); |
4097 | else | 4097 | else |
4098 | glDrawBuffer(GL_FRONT_LEFT); | 4098 | glDrawBuffer(GL_FRONT_LEFT); |
4099 | // exit with false, but also with working color buffer | 4099 | // exit with false, but also with working color buffer |
4100 | if (target != ERT_FRAME_BUFFER) | 4100 | if (target != ERT_FRAME_BUFFER) |
4101 | return false; | 4101 | return false; |
4102 | } | 4102 | } |
4103 | CurrentTarget=target; | 4103 | CurrentTarget=target; |
4104 | clearBuffers(clearTarget, clearZBuffer, false, color); | 4104 | clearBuffers(clearTarget, clearZBuffer, false, color); |
4105 | return true; | 4105 | return true; |
4106 | } | 4106 | } |
4107 | 4107 | ||
4108 | 4108 | ||
4109 | //! set or reset render target | 4109 | //! set or reset render target |
4110 | bool COpenGLDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer, | 4110 | bool COpenGLDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer, |
4111 | bool clearZBuffer, SColor color) | 4111 | bool clearZBuffer, SColor color) |
4112 | { | 4112 | { |
4113 | // check for right driver type | 4113 | // check for right driver type |
4114 | 4114 | ||
4115 | if (texture && texture->getDriverType() != EDT_OPENGL) | 4115 | if (texture && texture->getDriverType() != EDT_OPENGL) |
4116 | { | 4116 | { |
4117 | os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); | 4117 | os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); |
4118 | return false; | 4118 | return false; |
4119 | } | 4119 | } |
4120 | 4120 | ||
4121 | #if defined(GL_EXT_framebuffer_object) | 4121 | #if defined(GL_EXT_framebuffer_object) |
4122 | if (CurrentTarget==ERT_MULTI_RENDER_TEXTURES) | 4122 | if (CurrentTarget==ERT_MULTI_RENDER_TEXTURES) |
4123 | { | 4123 | { |
4124 | for (u32 i=0; i<MRTargets.size(); ++i) | 4124 | for (u32 i=0; i<MRTargets.size(); ++i) |
4125 | { | 4125 | { |
4126 | if (MRTargets[i].TargetType==ERT_RENDER_TEXTURE) | 4126 | if (MRTargets[i].TargetType==ERT_RENDER_TEXTURE) |
4127 | { | 4127 | { |
4128 | for (++i; i<MRTargets.size(); ++i) | 4128 | for (++i; i<MRTargets.size(); ++i) |
4129 | if (MRTargets[i].TargetType==ERT_RENDER_TEXTURE) | 4129 | if (MRTargets[i].TargetType==ERT_RENDER_TEXTURE) |
4130 | extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_TEXTURE_2D, 0, 0); | 4130 | extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_TEXTURE_2D, 0, 0); |
4131 | } | 4131 | } |
4132 | } | 4132 | } |
4133 | MRTargets.clear(); | 4133 | MRTargets.clear(); |
4134 | } | 4134 | } |
4135 | #endif | 4135 | #endif |
4136 | 4136 | ||
4137 | // check if we should set the previous RT back | 4137 | // check if we should set the previous RT back |
4138 | if ((RenderTargetTexture != texture) || | 4138 | if ((RenderTargetTexture != texture) || |
4139 | (CurrentTarget==ERT_MULTI_RENDER_TEXTURES)) | 4139 | (CurrentTarget==ERT_MULTI_RENDER_TEXTURES)) |
4140 | { | 4140 | { |
4141 | setActiveTexture(0, 0); | 4141 | setActiveTexture(0, 0); |
4142 | ResetRenderStates=true; | 4142 | ResetRenderStates=true; |
4143 | if (RenderTargetTexture!=0) | 4143 | if (RenderTargetTexture!=0) |
4144 | { | 4144 | { |
4145 | RenderTargetTexture->unbindRTT(); | 4145 | RenderTargetTexture->unbindRTT(); |
4146 | } | 4146 | } |
4147 | 4147 | ||
4148 | if (texture) | 4148 | if (texture) |
4149 | { | 4149 | { |
4150 | // we want to set a new target. so do this. | 4150 | // we want to set a new target. so do this. |
4151 | glViewport(0, 0, texture->getSize().Width, texture->getSize().Height); | 4151 | glViewport(0, 0, texture->getSize().Width, texture->getSize().Height); |
4152 | RenderTargetTexture = static_cast<COpenGLTexture*>(texture); | 4152 | RenderTargetTexture = static_cast<COpenGLTexture*>(texture); |
4153 | // calls glDrawBuffer as well | 4153 | // calls glDrawBuffer as well |
4154 | RenderTargetTexture->bindRTT(); | 4154 | RenderTargetTexture->bindRTT(); |
4155 | CurrentRendertargetSize = texture->getSize(); | 4155 | CurrentRendertargetSize = texture->getSize(); |
4156 | CurrentTarget=ERT_RENDER_TEXTURE; | 4156 | CurrentTarget=ERT_RENDER_TEXTURE; |
4157 | } | 4157 | } |
4158 | else | 4158 | else |
4159 | { | 4159 | { |
4160 | glViewport(0,0,ScreenSize.Width,ScreenSize.Height); | 4160 | glViewport(0,0,ScreenSize.Width,ScreenSize.Height); |
4161 | RenderTargetTexture = 0; | 4161 | RenderTargetTexture = 0; |
4162 | CurrentRendertargetSize = core::dimension2d<u32>(0,0); | 4162 | CurrentRendertargetSize = core::dimension2d<u32>(0,0); |
4163 | CurrentTarget=ERT_FRAME_BUFFER; | 4163 | CurrentTarget=ERT_FRAME_BUFFER; |
4164 | glDrawBuffer(Params.Doublebuffer?GL_BACK_LEFT:GL_FRONT_LEFT); | 4164 | glDrawBuffer(Params.Doublebuffer?GL_BACK_LEFT:GL_FRONT_LEFT); |
4165 | } | 4165 | } |
4166 | // we need to update the matrices due to the rendersize change. | 4166 | // we need to update the matrices due to the rendersize change. |
4167 | Transformation3DChanged=true; | 4167 | Transformation3DChanged=true; |
4168 | } | 4168 | } |
4169 | 4169 | ||
4170 | clearBuffers(clearBackBuffer, clearZBuffer, false, color); | 4170 | clearBuffers(clearBackBuffer, clearZBuffer, false, color); |
4171 | 4171 | ||
4172 | return true; | 4172 | return true; |
4173 | } | 4173 | } |
4174 | 4174 | ||
4175 | 4175 | ||
4176 | //! Sets multiple render targets | 4176 | //! Sets multiple render targets |
4177 | bool COpenGLDriver::setRenderTarget(const core::array<video::IRenderTarget>& targets, | 4177 | bool COpenGLDriver::setRenderTarget(const core::array<video::IRenderTarget>& targets, |
4178 | bool clearBackBuffer, bool clearZBuffer, SColor color) | 4178 | bool clearBackBuffer, bool clearZBuffer, SColor color) |
4179 | { | 4179 | { |
4180 | // if simply disabling the MRT via array call | 4180 | // if simply disabling the MRT via array call |
4181 | if (targets.size()==0) | 4181 | if (targets.size()==0) |
4182 | return setRenderTarget(0, clearBackBuffer, clearZBuffer, color); | 4182 | return setRenderTarget(0, clearBackBuffer, clearZBuffer, color); |
4183 | // if disabling old MRT, but enabling new one as well | 4183 | // if disabling old MRT, but enabling new one as well |
4184 | if ((MRTargets.size()!=0) && (targets != MRTargets)) | 4184 | if ((MRTargets.size()!=0) && (targets != MRTargets)) |
4185 | setRenderTarget(0, clearBackBuffer, clearZBuffer, color); | 4185 | setRenderTarget(0, clearBackBuffer, clearZBuffer, color); |
4186 | // if no change, simply clear buffers | 4186 | // if no change, simply clear buffers |
4187 | else if (targets == MRTargets) | 4187 | else if (targets == MRTargets) |
4188 | { | 4188 | { |
4189 | clearBuffers(clearBackBuffer, clearZBuffer, false, color); | 4189 | clearBuffers(clearBackBuffer, clearZBuffer, false, color); |
4190 | return true; | 4190 | return true; |
4191 | } | 4191 | } |
4192 | 4192 | ||
4193 | // copy to storage for correct disabling | 4193 | // copy to storage for correct disabling |
4194 | MRTargets=targets; | 4194 | MRTargets=targets; |
4195 | 4195 | ||
4196 | u32 maxMultipleRTTs = core::min_(static_cast<u32>(MaxMultipleRenderTargets), targets.size()); | 4196 | u32 maxMultipleRTTs = core::min_(static_cast<u32>(MaxMultipleRenderTargets), targets.size()); |
4197 | 4197 | ||
4198 | // determine common size | 4198 | // determine common size |
4199 | core::dimension2du rttSize = CurrentRendertargetSize; | 4199 | core::dimension2du rttSize = CurrentRendertargetSize; |
4200 | if (targets[0].TargetType==ERT_RENDER_TEXTURE) | 4200 | if (targets[0].TargetType==ERT_RENDER_TEXTURE) |
4201 | { | 4201 | { |
4202 | if (!targets[0].RenderTexture) | 4202 | if (!targets[0].RenderTexture) |
4203 | { | 4203 | { |
4204 | os::Printer::log("Missing render texture for MRT.", ELL_ERROR); | 4204 | os::Printer::log("Missing render texture for MRT.", ELL_ERROR); |
4205 | return false; | 4205 | return false; |
4206 | } | 4206 | } |
4207 | rttSize=targets[0].RenderTexture->getSize(); | 4207 | rttSize=targets[0].RenderTexture->getSize(); |
4208 | } | 4208 | } |
4209 | 4209 | ||
4210 | for (u32 i = 0; i < maxMultipleRTTs; ++i) | 4210 | for (u32 i = 0; i < maxMultipleRTTs; ++i) |
4211 | { | 4211 | { |
4212 | // check for right driver type | 4212 | // check for right driver type |
4213 | if (targets[i].TargetType==ERT_RENDER_TEXTURE) | 4213 | if (targets[i].TargetType==ERT_RENDER_TEXTURE) |
4214 | { | 4214 | { |
4215 | if (!targets[i].RenderTexture) | 4215 | if (!targets[i].RenderTexture) |
4216 | { | 4216 | { |
4217 | maxMultipleRTTs=i; | 4217 | maxMultipleRTTs=i; |
4218 | os::Printer::log("Missing render texture for MRT.", ELL_WARNING); | 4218 | os::Printer::log("Missing render texture for MRT.", ELL_WARNING); |
4219 | break; | 4219 | break; |
4220 | } | 4220 | } |
4221 | if (targets[i].RenderTexture->getDriverType() != EDT_OPENGL) | 4221 | if (targets[i].RenderTexture->getDriverType() != EDT_OPENGL) |
4222 | { | 4222 | { |
4223 | maxMultipleRTTs=i; | 4223 | maxMultipleRTTs=i; |
4224 | os::Printer::log("Tried to set a texture not owned by this driver.", ELL_WARNING); | 4224 | os::Printer::log("Tried to set a texture not owned by this driver.", ELL_WARNING); |
4225 | break; | 4225 | break; |
4226 | } | 4226 | } |
4227 | 4227 | ||
4228 | // check for valid render target | 4228 | // check for valid render target |
4229 | if (!targets[i].RenderTexture->isRenderTarget() || !static_cast<COpenGLTexture*>(targets[i].RenderTexture)->isFrameBufferObject()) | 4229 | if (!targets[i].RenderTexture->isRenderTarget() || !static_cast<COpenGLTexture*>(targets[i].RenderTexture)->isFrameBufferObject()) |
4230 | { | 4230 | { |
4231 | maxMultipleRTTs=i; | 4231 | maxMultipleRTTs=i; |
4232 | os::Printer::log("Tried to set a non FBO-RTT as render target.", ELL_WARNING); | 4232 | os::Printer::log("Tried to set a non FBO-RTT as render target.", ELL_WARNING); |
4233 | break; | 4233 | break; |
4234 | } | 4234 | } |
4235 | 4235 | ||
4236 | // check for valid size | 4236 | // check for valid size |
4237 | if (rttSize != targets[i].RenderTexture->getSize()) | 4237 | if (rttSize != targets[i].RenderTexture->getSize()) |
4238 | { | 4238 | { |
4239 | maxMultipleRTTs=i; | 4239 | maxMultipleRTTs=i; |
4240 | os::Printer::log("Render target texture has wrong size.", ELL_WARNING); | 4240 | os::Printer::log("Render target texture has wrong size.", ELL_WARNING); |
4241 | break; | 4241 | break; |
4242 | } | 4242 | } |
4243 | } | 4243 | } |
4244 | } | 4244 | } |
4245 | if (maxMultipleRTTs==0) | 4245 | if (maxMultipleRTTs==0) |
4246 | { | 4246 | { |
4247 | os::Printer::log("No valid MRTs.", ELL_ERROR); | 4247 | os::Printer::log("No valid MRTs.", ELL_ERROR); |
4248 | return false; | 4248 | return false; |
4249 | } | 4249 | } |
4250 | 4250 | ||
4251 | // init FBO, if any | 4251 | // init FBO, if any |
4252 | for (u32 i=0; i<maxMultipleRTTs; ++i) | 4252 | for (u32 i=0; i<maxMultipleRTTs; ++i) |
4253 | { | 4253 | { |
4254 | if (targets[i].TargetType==ERT_RENDER_TEXTURE) | 4254 | if (targets[i].TargetType==ERT_RENDER_TEXTURE) |
4255 | { | 4255 | { |
4256 | setRenderTarget(targets[i].RenderTexture, false, false, 0x0); | 4256 | setRenderTarget(targets[i].RenderTexture, false, false, 0x0); |
4257 | break; // bind only first RTT | 4257 | break; // bind only first RTT |
4258 | } | 4258 | } |
4259 | } | 4259 | } |
4260 | // init other main buffer, if necessary | 4260 | // init other main buffer, if necessary |
4261 | if (targets[0].TargetType!=ERT_RENDER_TEXTURE) | 4261 | if (targets[0].TargetType!=ERT_RENDER_TEXTURE) |
4262 | setRenderTarget(targets[0].TargetType, false, false, 0x0); | 4262 | setRenderTarget(targets[0].TargetType, false, false, 0x0); |
4263 | 4263 | ||
4264 | // attach other textures and store buffers into array | 4264 | // attach other textures and store buffers into array |
4265 | if (maxMultipleRTTs > 1) | 4265 | if (maxMultipleRTTs > 1) |
4266 | { | 4266 | { |
4267 | CurrentTarget=ERT_MULTI_RENDER_TEXTURES; | 4267 | CurrentTarget=ERT_MULTI_RENDER_TEXTURES; |
4268 | core::array<GLenum> MRTs; | 4268 | core::array<GLenum> MRTs; |
4269 | MRTs.set_used(maxMultipleRTTs); | 4269 | MRTs.set_used(maxMultipleRTTs); |
4270 | for(u32 i = 0; i < maxMultipleRTTs; i++) | 4270 | for(u32 i = 0; i < maxMultipleRTTs; i++) |
4271 | { | 4271 | { |
4272 | if (FeatureAvailable[IRR_EXT_draw_buffers2]) | 4272 | if (FeatureAvailable[IRR_EXT_draw_buffers2]) |
4273 | { | 4273 | { |
4274 | extGlColorMaskIndexed(i, | 4274 | extGlColorMaskIndexed(i, |
4275 | (targets[i].ColorMask & ECP_RED)?GL_TRUE:GL_FALSE, | 4275 | (targets[i].ColorMask & ECP_RED)?GL_TRUE:GL_FALSE, |
4276 | (targets[i].ColorMask & ECP_GREEN)?GL_TRUE:GL_FALSE, | 4276 | (targets[i].ColorMask & ECP_GREEN)?GL_TRUE:GL_FALSE, |
4277 | (targets[i].ColorMask & ECP_BLUE)?GL_TRUE:GL_FALSE, | 4277 | (targets[i].ColorMask & ECP_BLUE)?GL_TRUE:GL_FALSE, |
4278 | (targets[i].ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE); | 4278 | (targets[i].ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE); |
4279 | if (targets[i].BlendOp==EBO_NONE) | 4279 | if (targets[i].BlendOp==EBO_NONE) |
4280 | extGlDisableIndexed(GL_BLEND, i); | 4280 | extGlDisableIndexed(GL_BLEND, i); |
4281 | else | 4281 | else |
4282 | extGlEnableIndexed(GL_BLEND, i); | 4282 | extGlEnableIndexed(GL_BLEND, i); |
4283 | } | 4283 | } |
4284 | #if defined(GL_AMD_draw_buffers_blend) || defined(GL_ARB_draw_buffers_blend) | 4284 | #if defined(GL_AMD_draw_buffers_blend) || defined(GL_ARB_draw_buffers_blend) |
4285 | if (FeatureAvailable[IRR_AMD_draw_buffers_blend] || FeatureAvailable[IRR_ARB_draw_buffers_blend]) | 4285 | if (FeatureAvailable[IRR_AMD_draw_buffers_blend] || FeatureAvailable[IRR_ARB_draw_buffers_blend]) |
4286 | { | 4286 | { |
4287 | extGlBlendFuncIndexed(i, getGLBlend(targets[i].BlendFuncSrc), getGLBlend(targets[i].BlendFuncDst)); | 4287 | extGlBlendFuncIndexed(i, getGLBlend(targets[i].BlendFuncSrc), getGLBlend(targets[i].BlendFuncDst)); |
4288 | switch(targets[i].BlendOp) | 4288 | switch(targets[i].BlendOp) |
4289 | { | 4289 | { |
4290 | case EBO_SUBTRACT: | 4290 | case EBO_SUBTRACT: |
4291 | extGlBlendEquationIndexed(i, GL_FUNC_SUBTRACT); | 4291 | extGlBlendEquationIndexed(i, GL_FUNC_SUBTRACT); |
4292 | break; | 4292 | break; |
4293 | case EBO_REVSUBTRACT: | 4293 | case EBO_REVSUBTRACT: |
4294 | extGlBlendEquationIndexed(i, GL_FUNC_REVERSE_SUBTRACT); | 4294 | extGlBlendEquationIndexed(i, GL_FUNC_REVERSE_SUBTRACT); |
4295 | break; | 4295 | break; |
4296 | case EBO_MIN: | 4296 | case EBO_MIN: |
4297 | extGlBlendEquationIndexed(i, GL_MIN); | 4297 | extGlBlendEquationIndexed(i, GL_MIN); |
4298 | break; | 4298 | break; |
4299 | case EBO_MAX: | 4299 | case EBO_MAX: |
4300 | extGlBlendEquationIndexed(i, GL_MAX); | 4300 | extGlBlendEquationIndexed(i, GL_MAX); |
4301 | break; | 4301 | break; |
4302 | case EBO_MIN_FACTOR: | 4302 | case EBO_MIN_FACTOR: |
4303 | case EBO_MIN_ALPHA: | 4303 | case EBO_MIN_ALPHA: |
4304 | #if defined(GL_AMD_blend_minmax_factor) | 4304 | #if defined(GL_AMD_blend_minmax_factor) |
4305 | if (FeatureAvailable[IRR_AMD_blend_minmax_factor]) | 4305 | if (FeatureAvailable[IRR_AMD_blend_minmax_factor]) |
4306 | extGlBlendEquationIndexed(i, GL_FACTOR_MIN_AMD); | 4306 | extGlBlendEquationIndexed(i, GL_FACTOR_MIN_AMD); |
4307 | // fallback in case of missing extension | 4307 | // fallback in case of missing extension |
4308 | else | 4308 | else |
4309 | #endif | 4309 | #endif |
4310 | extGlBlendEquation(GL_MIN); | 4310 | extGlBlendEquation(GL_MIN); |
4311 | break; | 4311 | break; |
4312 | case EBO_MAX_FACTOR: | 4312 | case EBO_MAX_FACTOR: |
4313 | case EBO_MAX_ALPHA: | 4313 | case EBO_MAX_ALPHA: |
4314 | #if defined(GL_AMD_blend_minmax_factor) | 4314 | #if defined(GL_AMD_blend_minmax_factor) |
4315 | if (FeatureAvailable[IRR_AMD_blend_minmax_factor]) | 4315 | if (FeatureAvailable[IRR_AMD_blend_minmax_factor]) |
4316 | extGlBlendEquationIndexed(i, GL_FACTOR_MAX_AMD); | 4316 | extGlBlendEquationIndexed(i, GL_FACTOR_MAX_AMD); |
4317 | // fallback in case of missing extension | 4317 | // fallback in case of missing extension |
4318 | else | 4318 | else |
4319 | #endif | 4319 | #endif |
4320 | extGlBlendEquation(GL_MAX); | 4320 | extGlBlendEquation(GL_MAX); |
4321 | break; | 4321 | break; |
4322 | default: | 4322 | default: |
4323 | extGlBlendEquationIndexed(i, GL_FUNC_ADD); | 4323 | extGlBlendEquationIndexed(i, GL_FUNC_ADD); |
4324 | break; | 4324 | break; |
4325 | } | 4325 | } |
4326 | } | 4326 | } |
4327 | #endif | 4327 | #endif |
4328 | if (targets[i].TargetType==ERT_RENDER_TEXTURE) | 4328 | if (targets[i].TargetType==ERT_RENDER_TEXTURE) |
4329 | { | 4329 | { |
4330 | GLenum attachment = GL_NONE; | 4330 | GLenum attachment = GL_NONE; |
4331 | #ifdef GL_EXT_framebuffer_object | 4331 | #ifdef GL_EXT_framebuffer_object |
4332 | // attach texture to FrameBuffer Object on Color [i] | 4332 | // attach texture to FrameBuffer Object on Color [i] |
4333 | attachment = GL_COLOR_ATTACHMENT0_EXT+i; | 4333 | attachment = GL_COLOR_ATTACHMENT0_EXT+i; |
4334 | if ((i != 0) && (targets[i].RenderTexture != RenderTargetTexture)) | 4334 | if ((i != 0) && (targets[i].RenderTexture != RenderTargetTexture)) |
4335 | extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_2D, static_cast<COpenGLTexture*>(targets[i].RenderTexture)->getOpenGLTextureName(), 0); | 4335 | extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_2D, static_cast<COpenGLTexture*>(targets[i].RenderTexture)->getOpenGLTextureName(), 0); |
4336 | #endif | 4336 | #endif |
4337 | MRTs[i]=attachment; | 4337 | MRTs[i]=attachment; |
4338 | } | 4338 | } |
4339 | else | 4339 | else |
4340 | { | 4340 | { |
4341 | switch(targets[i].TargetType) | 4341 | switch(targets[i].TargetType) |
4342 | { | 4342 | { |
4343 | case ERT_FRAME_BUFFER: | 4343 | case ERT_FRAME_BUFFER: |
4344 | MRTs[i]=GL_BACK_LEFT; | 4344 | MRTs[i]=GL_BACK_LEFT; |
4345 | break; | 4345 | break; |
4346 | case ERT_STEREO_BOTH_BUFFERS: | 4346 | case ERT_STEREO_BOTH_BUFFERS: |
4347 | MRTs[i]=GL_BACK; | 4347 | MRTs[i]=GL_BACK; |
4348 | break; | 4348 | break; |
4349 | case ERT_STEREO_RIGHT_BUFFER: | 4349 | case ERT_STEREO_RIGHT_BUFFER: |
4350 | MRTs[i]=GL_BACK_RIGHT; | 4350 | MRTs[i]=GL_BACK_RIGHT; |
4351 | break; | 4351 | break; |
4352 | case ERT_STEREO_LEFT_BUFFER: | 4352 | case ERT_STEREO_LEFT_BUFFER: |
4353 | MRTs[i]=GL_BACK_LEFT; | 4353 | MRTs[i]=GL_BACK_LEFT; |
4354 | break; | 4354 | break; |
4355 | default: | 4355 | default: |
4356 | MRTs[i]=GL_AUX0+(targets[i].TargetType-ERT_AUX_BUFFER0); | 4356 | MRTs[i]=GL_AUX0+(targets[i].TargetType-ERT_AUX_BUFFER0); |
4357 | break; | 4357 | break; |
4358 | } | 4358 | } |
4359 | } | 4359 | } |
4360 | } | 4360 | } |
4361 | 4361 | ||
4362 | extGlDrawBuffers(maxMultipleRTTs, MRTs.const_pointer()); | 4362 | extGlDrawBuffers(maxMultipleRTTs, MRTs.const_pointer()); |
4363 | } | 4363 | } |
4364 | 4364 | ||
4365 | clearBuffers(clearBackBuffer, clearZBuffer, false, color); | 4365 | clearBuffers(clearBackBuffer, clearZBuffer, false, color); |
4366 | return true; | 4366 | return true; |
4367 | } | 4367 | } |
4368 | 4368 | ||
4369 | 4369 | ||
4370 | // returns the current size of the screen or rendertarget | 4370 | // returns the current size of the screen or rendertarget |
4371 | const core::dimension2d<u32>& COpenGLDriver::getCurrentRenderTargetSize() const | 4371 | const core::dimension2d<u32>& COpenGLDriver::getCurrentRenderTargetSize() const |
4372 | { | 4372 | { |
4373 | if (CurrentRendertargetSize.Width == 0) | 4373 | if (CurrentRendertargetSize.Width == 0) |
4374 | return ScreenSize; | 4374 | return ScreenSize; |
4375 | else | 4375 | else |
4376 | return CurrentRendertargetSize; | 4376 | return CurrentRendertargetSize; |
4377 | } | 4377 | } |
4378 | 4378 | ||
4379 | 4379 | ||
4380 | //! Clears the ZBuffer. | 4380 | //! Clears the ZBuffer. |
4381 | void COpenGLDriver::clearZBuffer() | 4381 | void COpenGLDriver::clearZBuffer() |
4382 | { | 4382 | { |
4383 | clearBuffers(false, true, false, 0x0); | 4383 | clearBuffers(false, true, false, 0x0); |
4384 | } | 4384 | } |
4385 | 4385 | ||
4386 | 4386 | ||
4387 | //! Returns an image created from the last rendered frame. | 4387 | //! Returns an image created from the last rendered frame. |
4388 | IImage* COpenGLDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target) | 4388 | IImage* COpenGLDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target) |
4389 | { | 4389 | { |
4390 | if (target==video::ERT_MULTI_RENDER_TEXTURES || target==video::ERT_RENDER_TEXTURE || target==video::ERT_STEREO_BOTH_BUFFERS) | 4390 | if (target==video::ERT_MULTI_RENDER_TEXTURES || target==video::ERT_RENDER_TEXTURE || target==video::ERT_STEREO_BOTH_BUFFERS) |
4391 | return 0; | 4391 | return 0; |
4392 | 4392 | ||
4393 | // allows to read pixels in top-to-bottom order | 4393 | // allows to read pixels in top-to-bottom order |
4394 | #ifdef GL_MESA_pack_invert | 4394 | #ifdef GL_MESA_pack_invert |
4395 | if (FeatureAvailable[IRR_MESA_pack_invert]) | 4395 | if (FeatureAvailable[IRR_MESA_pack_invert]) |
4396 | glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE); | 4396 | glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE); |
4397 | #endif | 4397 | #endif |
4398 | 4398 | ||
4399 | if (format==video::ECF_UNKNOWN) | 4399 | if (format==video::ECF_UNKNOWN) |
4400 | format=getColorFormat(); | 4400 | format=getColorFormat(); |
4401 | GLenum fmt; | 4401 | GLenum fmt; |
4402 | GLenum type; | 4402 | GLenum type; |
4403 | switch (format) | 4403 | switch (format) |
4404 | { | 4404 | { |
4405 | case ECF_A1R5G5B5: | 4405 | case ECF_A1R5G5B5: |
4406 | fmt = GL_BGRA; | 4406 | fmt = GL_BGRA; |
4407 | type = GL_UNSIGNED_SHORT_1_5_5_5_REV; | 4407 | type = GL_UNSIGNED_SHORT_1_5_5_5_REV; |
4408 | break; | 4408 | break; |
4409 | case ECF_R5G6B5: | 4409 | case ECF_R5G6B5: |
4410 | fmt = GL_RGB; | 4410 | fmt = GL_RGB; |
4411 | type = GL_UNSIGNED_SHORT_5_6_5; | 4411 | type = GL_UNSIGNED_SHORT_5_6_5; |
4412 | break; | 4412 | break; |
4413 | case ECF_R8G8B8: | 4413 | case ECF_R8G8B8: |
4414 | fmt = GL_RGB; | 4414 | fmt = GL_RGB; |
4415 | type = GL_UNSIGNED_BYTE; | 4415 | type = GL_UNSIGNED_BYTE; |
4416 | break; | 4416 | break; |
4417 | case ECF_A8R8G8B8: | 4417 | case ECF_A8R8G8B8: |
4418 | fmt = GL_BGRA; | 4418 | fmt = GL_BGRA; |
4419 | if (Version > 101) | 4419 | if (Version > 101) |
4420 | type = GL_UNSIGNED_INT_8_8_8_8_REV; | 4420 | type = GL_UNSIGNED_INT_8_8_8_8_REV; |
4421 | else | 4421 | else |
4422 | type = GL_UNSIGNED_BYTE; | 4422 | type = GL_UNSIGNED_BYTE; |
4423 | break; | 4423 | break; |
4424 | case ECF_R16F: | 4424 | case ECF_R16F: |
4425 | if (FeatureAvailable[IRR_ARB_texture_rg]) | 4425 | if (FeatureAvailable[IRR_ARB_texture_rg]) |
4426 | fmt = GL_RED; | 4426 | fmt = GL_RED; |
4427 | else | 4427 | else |
4428 | fmt = GL_LUMINANCE; | 4428 | fmt = GL_LUMINANCE; |
4429 | #ifdef GL_ARB_half_float_pixel | 4429 | #ifdef GL_ARB_half_float_pixel |
4430 | if (FeatureAvailable[IRR_ARB_half_float_pixel]) | 4430 | if (FeatureAvailable[IRR_ARB_half_float_pixel]) |
4431 | type = GL_HALF_FLOAT_ARB; | 4431 | type = GL_HALF_FLOAT_ARB; |
4432 | else | 4432 | else |
4433 | #endif | 4433 | #endif |
4434 | { | 4434 | { |
4435 | type = GL_FLOAT; | 4435 | type = GL_FLOAT; |
4436 | format = ECF_R32F; | 4436 | format = ECF_R32F; |
4437 | } | 4437 | } |
4438 | break; | 4438 | break; |
4439 | case ECF_G16R16F: | 4439 | case ECF_G16R16F: |
4440 | #ifdef GL_ARB_texture_rg | 4440 | #ifdef GL_ARB_texture_rg |
4441 | if (FeatureAvailable[IRR_ARB_texture_rg]) | 4441 | if (FeatureAvailable[IRR_ARB_texture_rg]) |
4442 | fmt = GL_RG; | 4442 | fmt = GL_RG; |
4443 | else | 4443 | else |
4444 | #endif | 4444 | #endif |
4445 | fmt = GL_LUMINANCE_ALPHA; | 4445 | fmt = GL_LUMINANCE_ALPHA; |
4446 | #ifdef GL_ARB_half_float_pixel | 4446 | #ifdef GL_ARB_half_float_pixel |
4447 | if (FeatureAvailable[IRR_ARB_half_float_pixel]) | 4447 | if (FeatureAvailable[IRR_ARB_half_float_pixel]) |
4448 | type = GL_HALF_FLOAT_ARB; | 4448 | type = GL_HALF_FLOAT_ARB; |
4449 | else | 4449 | else |
4450 | #endif | 4450 | #endif |
4451 | { | 4451 | { |
4452 | type = GL_FLOAT; | 4452 | type = GL_FLOAT; |
4453 | format = ECF_G32R32F; | 4453 | format = ECF_G32R32F; |
4454 | } | 4454 | } |
4455 | break; | 4455 | break; |
4456 | case ECF_A16B16G16R16F: | 4456 | case ECF_A16B16G16R16F: |
4457 | fmt = GL_BGRA; | 4457 | fmt = GL_BGRA; |
4458 | #ifdef GL_ARB_half_float_pixel | 4458 | #ifdef GL_ARB_half_float_pixel |
4459 | if (FeatureAvailable[IRR_ARB_half_float_pixel]) | 4459 | if (FeatureAvailable[IRR_ARB_half_float_pixel]) |
4460 | type = GL_HALF_FLOAT_ARB; | 4460 | type = GL_HALF_FLOAT_ARB; |
4461 | else | 4461 | else |
4462 | #endif | 4462 | #endif |
4463 | { | 4463 | { |
4464 | type = GL_FLOAT; | 4464 | type = GL_FLOAT; |
4465 | format = ECF_A32B32G32R32F; | 4465 | format = ECF_A32B32G32R32F; |
4466 | } | 4466 | } |
4467 | break; | 4467 | break; |
4468 | case ECF_R32F: | 4468 | case ECF_R32F: |
4469 | if (FeatureAvailable[IRR_ARB_texture_rg]) | 4469 | if (FeatureAvailable[IRR_ARB_texture_rg]) |
4470 | fmt = GL_RED; | 4470 | fmt = GL_RED; |
4471 | else | 4471 | else |
4472 | fmt = GL_LUMINANCE; | 4472 | fmt = GL_LUMINANCE; |
4473 | type = GL_FLOAT; | 4473 | type = GL_FLOAT; |
4474 | break; | 4474 | break; |
4475 | case ECF_G32R32F: | 4475 | case ECF_G32R32F: |
4476 | #ifdef GL_ARB_texture_rg | 4476 | #ifdef GL_ARB_texture_rg |
4477 | if (FeatureAvailable[IRR_ARB_texture_rg]) | 4477 | if (FeatureAvailable[IRR_ARB_texture_rg]) |
4478 | fmt = GL_RG; | 4478 | fmt = GL_RG; |
4479 | else | 4479 | else |
4480 | #endif | 4480 | #endif |
4481 | fmt = GL_LUMINANCE_ALPHA; | 4481 | fmt = GL_LUMINANCE_ALPHA; |
4482 | type = GL_FLOAT; | 4482 | type = GL_FLOAT; |
4483 | break; | 4483 | break; |
4484 | case ECF_A32B32G32R32F: | 4484 | case ECF_A32B32G32R32F: |
4485 | fmt = GL_BGRA; | 4485 | fmt = GL_BGRA; |
4486 | type = GL_FLOAT; | 4486 | type = GL_FLOAT; |
4487 | break; | 4487 | break; |
4488 | default: | 4488 | default: |
4489 | fmt = GL_BGRA; | 4489 | fmt = GL_BGRA; |
4490 | type = GL_UNSIGNED_BYTE; | 4490 | type = GL_UNSIGNED_BYTE; |
4491 | break; | 4491 | break; |
4492 | } | 4492 | } |
4493 | IImage* newImage = createImage(format, ScreenSize); | 4493 | IImage* newImage = createImage(format, ScreenSize); |
4494 | 4494 | ||
4495 | u8* pixels = 0; | 4495 | u8* pixels = 0; |
4496 | if (newImage) | 4496 | if (newImage) |
4497 | pixels = static_cast<u8*>(newImage->lock()); | 4497 | pixels = static_cast<u8*>(newImage->lock()); |
4498 | if (pixels) | 4498 | if (pixels) |
4499 | { | 4499 | { |
4500 | GLenum tgt=GL_FRONT; | 4500 | GLenum tgt=GL_FRONT; |
4501 | switch (target) | 4501 | switch (target) |
4502 | { | 4502 | { |
4503 | case video::ERT_FRAME_BUFFER: | 4503 | case video::ERT_FRAME_BUFFER: |
4504 | break; | 4504 | break; |
4505 | case video::ERT_STEREO_LEFT_BUFFER: | 4505 | case video::ERT_STEREO_LEFT_BUFFER: |
4506 | tgt=GL_FRONT_LEFT; | 4506 | tgt=GL_FRONT_LEFT; |
4507 | break; | 4507 | break; |
4508 | case video::ERT_STEREO_RIGHT_BUFFER: | 4508 | case video::ERT_STEREO_RIGHT_BUFFER: |
4509 | tgt=GL_FRONT_RIGHT; | 4509 | tgt=GL_FRONT_RIGHT; |
4510 | break; | 4510 | break; |
4511 | default: | 4511 | default: |
4512 | tgt=GL_AUX0+(target-video::ERT_AUX_BUFFER0); | 4512 | tgt=GL_AUX0+(target-video::ERT_AUX_BUFFER0); |
4513 | break; | 4513 | break; |
4514 | } | 4514 | } |
4515 | glReadBuffer(tgt); | 4515 | glReadBuffer(tgt); |
4516 | glReadPixels(0, 0, ScreenSize.Width, ScreenSize.Height, fmt, type, pixels); | 4516 | glReadPixels(0, 0, ScreenSize.Width, ScreenSize.Height, fmt, type, pixels); |
4517 | testGLError(); | 4517 | testGLError(); |
4518 | glReadBuffer(GL_BACK); | 4518 | glReadBuffer(GL_BACK); |
4519 | } | 4519 | } |
4520 | 4520 | ||
4521 | #ifdef GL_MESA_pack_invert | 4521 | #ifdef GL_MESA_pack_invert |
4522 | if (FeatureAvailable[IRR_MESA_pack_invert]) | 4522 | if (FeatureAvailable[IRR_MESA_pack_invert]) |
4523 | glPixelStorei(GL_PACK_INVERT_MESA, GL_FALSE); | 4523 | glPixelStorei(GL_PACK_INVERT_MESA, GL_FALSE); |
4524 | else | 4524 | else |
4525 | #endif | 4525 | #endif |
4526 | if (pixels) | 4526 | if (pixels) |
4527 | { | 4527 | { |
4528 | // opengl images are horizontally flipped, so we have to fix that here. | 4528 | // opengl images are horizontally flipped, so we have to fix that here. |
4529 | const s32 pitch=newImage->getPitch(); | 4529 | const s32 pitch=newImage->getPitch(); |
4530 | u8* p2 = pixels + (ScreenSize.Height - 1) * pitch; | 4530 | u8* p2 = pixels + (ScreenSize.Height - 1) * pitch; |
4531 | u8* tmpBuffer = new u8[pitch]; | 4531 | u8* tmpBuffer = new u8[pitch]; |
4532 | for (u32 i=0; i < ScreenSize.Height; i += 2) | 4532 | for (u32 i=0; i < ScreenSize.Height; i += 2) |
4533 | { | 4533 | { |
4534 | memcpy(tmpBuffer, pixels, pitch); | 4534 | memcpy(tmpBuffer, pixels, pitch); |
4535 | // for (u32 j=0; j<pitch; ++j) | 4535 | // for (u32 j=0; j<pitch; ++j) |
4536 | // { | 4536 | // { |
4537 | // pixels[j]=(u8)(p2[j]*255.f); | 4537 | // pixels[j]=(u8)(p2[j]*255.f); |
4538 | // } | 4538 | // } |
4539 | memcpy(pixels, p2, pitch); | 4539 | memcpy(pixels, p2, pitch); |
4540 | // for (u32 j=0; j<pitch; ++j) | 4540 | // for (u32 j=0; j<pitch; ++j) |
4541 | // { | 4541 | // { |
4542 | // p2[j]=(u8)(tmpBuffer[j]*255.f); | 4542 | // p2[j]=(u8)(tmpBuffer[j]*255.f); |
4543 | // } | 4543 | // } |
4544 | memcpy(p2, tmpBuffer, pitch); | 4544 | memcpy(p2, tmpBuffer, pitch); |
4545 | pixels += pitch; | 4545 | pixels += pitch; |
4546 | p2 -= pitch; | 4546 | p2 -= pitch; |
4547 | } | 4547 | } |
4548 | delete [] tmpBuffer; | 4548 | delete [] tmpBuffer; |
4549 | } | 4549 | } |
4550 | 4550 | ||
4551 | if (newImage) | 4551 | if (newImage) |
4552 | { | 4552 | { |
4553 | newImage->unlock(); | 4553 | newImage->unlock(); |
4554 | if (testGLError() || !pixels) | 4554 | if (testGLError() || !pixels) |
4555 | { | 4555 | { |
4556 | newImage->drop(); | 4556 | newImage->drop(); |
4557 | return 0; | 4557 | return 0; |
4558 | } | 4558 | } |
4559 | } | 4559 | } |
4560 | return newImage; | 4560 | return newImage; |
4561 | } | 4561 | } |
4562 | 4562 | ||
4563 | 4563 | ||
4564 | //! get depth texture for the given render target texture | 4564 | //! get depth texture for the given render target texture |
4565 | ITexture* COpenGLDriver::createDepthTexture(ITexture* texture, bool shared) | 4565 | ITexture* COpenGLDriver::createDepthTexture(ITexture* texture, bool shared) |
4566 | { | 4566 | { |
4567 | if ((texture->getDriverType() != EDT_OPENGL) || (!texture->isRenderTarget())) | 4567 | if ((texture->getDriverType() != EDT_OPENGL) || (!texture->isRenderTarget())) |
4568 | return 0; | 4568 | return 0; |
4569 | COpenGLTexture* tex = static_cast<COpenGLTexture*>(texture); | 4569 | COpenGLTexture* tex = static_cast<COpenGLTexture*>(texture); |
4570 | 4570 | ||
4571 | if (!tex->isFrameBufferObject()) | 4571 | if (!tex->isFrameBufferObject()) |
4572 | return 0; | 4572 | return 0; |
4573 | 4573 | ||
4574 | if (shared) | 4574 | if (shared) |
4575 | { | 4575 | { |
4576 | for (u32 i=0; i<DepthTextures.size(); ++i) | 4576 | for (u32 i=0; i<DepthTextures.size(); ++i) |
4577 | { | 4577 | { |
4578 | if (DepthTextures[i]->getSize()==texture->getSize()) | 4578 | if (DepthTextures[i]->getSize()==texture->getSize()) |
4579 | { | 4579 | { |
4580 | DepthTextures[i]->grab(); | 4580 | DepthTextures[i]->grab(); |
4581 | return DepthTextures[i]; | 4581 | return DepthTextures[i]; |
4582 | } | 4582 | } |
4583 | } | 4583 | } |
4584 | DepthTextures.push_back(new COpenGLFBODepthTexture(texture->getSize(), "depth1", this)); | 4584 | DepthTextures.push_back(new COpenGLFBODepthTexture(texture->getSize(), "depth1", this)); |
4585 | return DepthTextures.getLast(); | 4585 | return DepthTextures.getLast(); |
4586 | } | 4586 | } |
4587 | return (new COpenGLFBODepthTexture(texture->getSize(), "depth1", this)); | 4587 | return (new COpenGLFBODepthTexture(texture->getSize(), "depth1", this)); |
4588 | } | 4588 | } |
4589 | 4589 | ||
4590 | 4590 | ||
4591 | void COpenGLDriver::removeDepthTexture(ITexture* texture) | 4591 | void COpenGLDriver::removeDepthTexture(ITexture* texture) |
4592 | { | 4592 | { |
4593 | for (u32 i=0; i<DepthTextures.size(); ++i) | 4593 | for (u32 i=0; i<DepthTextures.size(); ++i) |
4594 | { | 4594 | { |
4595 | if (texture==DepthTextures[i]) | 4595 | if (texture==DepthTextures[i]) |
4596 | { | 4596 | { |
4597 | DepthTextures.erase(i); | 4597 | DepthTextures.erase(i); |
4598 | return; | 4598 | return; |
4599 | } | 4599 | } |
4600 | } | 4600 | } |
4601 | } | 4601 | } |
4602 | 4602 | ||
4603 | 4603 | ||
4604 | //! Set/unset a clipping plane. | 4604 | //! Set/unset a clipping plane. |
4605 | bool COpenGLDriver::setClipPlane(u32 index, const core::plane3df& plane, bool enable) | 4605 | bool COpenGLDriver::setClipPlane(u32 index, const core::plane3df& plane, bool enable) |
4606 | { | 4606 | { |
4607 | if (index >= MaxUserClipPlanes) | 4607 | if (index >= MaxUserClipPlanes) |
4608 | return false; | 4608 | return false; |
4609 | 4609 | ||
4610 | UserClipPlanes[index].Plane=plane; | 4610 | UserClipPlanes[index].Plane=plane; |
4611 | enableClipPlane(index, enable); | 4611 | enableClipPlane(index, enable); |
4612 | return true; | 4612 | return true; |
4613 | } | 4613 | } |
4614 | 4614 | ||
4615 | 4615 | ||
4616 | void COpenGLDriver::uploadClipPlane(u32 index) | 4616 | void COpenGLDriver::uploadClipPlane(u32 index) |
4617 | { | 4617 | { |
4618 | // opengl needs an array of doubles for the plane equation | 4618 | // opengl needs an array of doubles for the plane equation |
4619 | GLdouble clip_plane[4]; | 4619 | GLdouble clip_plane[4]; |
4620 | clip_plane[0] = UserClipPlanes[index].Plane.Normal.X; | 4620 | clip_plane[0] = UserClipPlanes[index].Plane.Normal.X; |
4621 | clip_plane[1] = UserClipPlanes[index].Plane.Normal.Y; | 4621 | clip_plane[1] = UserClipPlanes[index].Plane.Normal.Y; |
4622 | clip_plane[2] = UserClipPlanes[index].Plane.Normal.Z; | 4622 | clip_plane[2] = UserClipPlanes[index].Plane.Normal.Z; |
4623 | clip_plane[3] = UserClipPlanes[index].Plane.D; | 4623 | clip_plane[3] = UserClipPlanes[index].Plane.D; |
4624 | glClipPlane(GL_CLIP_PLANE0 + index, clip_plane); | 4624 | glClipPlane(GL_CLIP_PLANE0 + index, clip_plane); |
4625 | } | 4625 | } |
4626 | 4626 | ||
4627 | 4627 | ||
4628 | //! Enable/disable a clipping plane. | 4628 | //! Enable/disable a clipping plane. |
4629 | void COpenGLDriver::enableClipPlane(u32 index, bool enable) | 4629 | void COpenGLDriver::enableClipPlane(u32 index, bool enable) |
4630 | { | 4630 | { |
4631 | if (index >= MaxUserClipPlanes) | 4631 | if (index >= MaxUserClipPlanes) |
4632 | return; | 4632 | return; |
4633 | if (enable) | 4633 | if (enable) |
4634 | { | 4634 | { |
4635 | if (!UserClipPlanes[index].Enabled) | 4635 | if (!UserClipPlanes[index].Enabled) |
4636 | { | 4636 | { |
4637 | uploadClipPlane(index); | 4637 | uploadClipPlane(index); |
4638 | glEnable(GL_CLIP_PLANE0 + index); | 4638 | glEnable(GL_CLIP_PLANE0 + index); |
4639 | } | 4639 | } |
4640 | } | 4640 | } |
4641 | else | 4641 | else |
4642 | glDisable(GL_CLIP_PLANE0 + index); | 4642 | glDisable(GL_CLIP_PLANE0 + index); |
4643 | 4643 | ||
4644 | UserClipPlanes[index].Enabled=enable; | 4644 | UserClipPlanes[index].Enabled=enable; |
4645 | } | 4645 | } |
4646 | 4646 | ||
4647 | 4647 | ||
4648 | core::dimension2du COpenGLDriver::getMaxTextureSize() const | 4648 | core::dimension2du COpenGLDriver::getMaxTextureSize() const |
4649 | { | 4649 | { |
4650 | return core::dimension2du(MaxTextureSize, MaxTextureSize); | 4650 | return core::dimension2du(MaxTextureSize, MaxTextureSize); |
4651 | } | 4651 | } |
4652 | 4652 | ||
4653 | 4653 | ||
4654 | //! Convert E_PRIMITIVE_TYPE to OpenGL equivalent | 4654 | //! Convert E_PRIMITIVE_TYPE to OpenGL equivalent |
4655 | GLenum COpenGLDriver::primitiveTypeToGL(scene::E_PRIMITIVE_TYPE type) const | 4655 | GLenum COpenGLDriver::primitiveTypeToGL(scene::E_PRIMITIVE_TYPE type) const |
4656 | { | 4656 | { |
4657 | switch (type) | 4657 | switch (type) |
4658 | { | 4658 | { |
4659 | case scene::EPT_POINTS: | 4659 | case scene::EPT_POINTS: |
4660 | return GL_POINTS; | 4660 | return GL_POINTS; |
4661 | case scene::EPT_LINE_STRIP: | 4661 | case scene::EPT_LINE_STRIP: |
4662 | return GL_LINE_STRIP; | 4662 | return GL_LINE_STRIP; |
4663 | case scene::EPT_LINE_LOOP: | 4663 | case scene::EPT_LINE_LOOP: |
4664 | return GL_LINE_LOOP; | 4664 | return GL_LINE_LOOP; |
4665 | case scene::EPT_LINES: | 4665 | case scene::EPT_LINES: |
4666 | return GL_LINES; | 4666 | return GL_LINES; |
4667 | case scene::EPT_TRIANGLE_STRIP: | 4667 | case scene::EPT_TRIANGLE_STRIP: |
4668 | return GL_TRIANGLE_STRIP; | 4668 | return GL_TRIANGLE_STRIP; |
4669 | case scene::EPT_TRIANGLE_FAN: | 4669 | case scene::EPT_TRIANGLE_FAN: |
4670 | return GL_TRIANGLE_FAN; | 4670 | return GL_TRIANGLE_FAN; |
4671 | case scene::EPT_TRIANGLES: | 4671 | case scene::EPT_TRIANGLES: |
4672 | return GL_TRIANGLES; | 4672 | return GL_TRIANGLES; |
4673 | case scene::EPT_QUAD_STRIP: | 4673 | case scene::EPT_QUAD_STRIP: |
4674 | return GL_QUAD_STRIP; | 4674 | return GL_QUAD_STRIP; |
4675 | case scene::EPT_QUADS: | 4675 | case scene::EPT_QUADS: |
4676 | return GL_QUADS; | 4676 | return GL_QUADS; |
4677 | case scene::EPT_POLYGON: | 4677 | case scene::EPT_POLYGON: |
4678 | return GL_POLYGON; | 4678 | return GL_POLYGON; |
4679 | case scene::EPT_POINT_SPRITES: | 4679 | case scene::EPT_POINT_SPRITES: |
4680 | #ifdef GL_ARB_point_sprite | 4680 | #ifdef GL_ARB_point_sprite |
4681 | return GL_POINT_SPRITE_ARB; | 4681 | return GL_POINT_SPRITE_ARB; |
4682 | #else | 4682 | #else |
4683 | return GL_POINTS; | 4683 | return GL_POINTS; |
4684 | #endif | 4684 | #endif |
4685 | } | 4685 | } |
4686 | return GL_TRIANGLES; | 4686 | return GL_TRIANGLES; |
4687 | } | 4687 | } |
4688 | 4688 | ||
4689 | 4689 | ||
4690 | GLenum COpenGLDriver::getGLBlend(E_BLEND_FACTOR factor) const | 4690 | GLenum COpenGLDriver::getGLBlend(E_BLEND_FACTOR factor) const |
4691 | { | 4691 | { |
4692 | GLenum r = 0; | 4692 | GLenum r = 0; |
4693 | switch (factor) | 4693 | switch (factor) |
4694 | { | 4694 | { |
4695 | case EBF_ZERO: r = GL_ZERO; break; | 4695 | case EBF_ZERO: r = GL_ZERO; break; |
4696 | case EBF_ONE: r = GL_ONE; break; | 4696 | case EBF_ONE: r = GL_ONE; break; |
4697 | case EBF_DST_COLOR: r = GL_DST_COLOR; break; | 4697 | case EBF_DST_COLOR: r = GL_DST_COLOR; break; |
4698 | case EBF_ONE_MINUS_DST_COLOR: r = GL_ONE_MINUS_DST_COLOR; break; | 4698 | case EBF_ONE_MINUS_DST_COLOR: r = GL_ONE_MINUS_DST_COLOR; break; |
4699 | case EBF_SRC_COLOR: r = GL_SRC_COLOR; break; | 4699 | case EBF_SRC_COLOR: r = GL_SRC_COLOR; break; |
4700 | case EBF_ONE_MINUS_SRC_COLOR: r = GL_ONE_MINUS_SRC_COLOR; break; | 4700 | case EBF_ONE_MINUS_SRC_COLOR: r = GL_ONE_MINUS_SRC_COLOR; break; |
4701 | case EBF_SRC_ALPHA: r = GL_SRC_ALPHA; break; | 4701 | case EBF_SRC_ALPHA: r = GL_SRC_ALPHA; break; |
4702 | case EBF_ONE_MINUS_SRC_ALPHA: r = GL_ONE_MINUS_SRC_ALPHA; break; | 4702 | case EBF_ONE_MINUS_SRC_ALPHA: r = GL_ONE_MINUS_SRC_ALPHA; break; |
4703 | case EBF_DST_ALPHA: r = GL_DST_ALPHA; break; | 4703 | case EBF_DST_ALPHA: r = GL_DST_ALPHA; break; |
4704 | case EBF_ONE_MINUS_DST_ALPHA: r = GL_ONE_MINUS_DST_ALPHA; break; | 4704 | case EBF_ONE_MINUS_DST_ALPHA: r = GL_ONE_MINUS_DST_ALPHA; break; |
4705 | case EBF_SRC_ALPHA_SATURATE: r = GL_SRC_ALPHA_SATURATE; break; | 4705 | case EBF_SRC_ALPHA_SATURATE: r = GL_SRC_ALPHA_SATURATE; break; |
4706 | } | 4706 | } |
4707 | return r; | 4707 | return r; |
4708 | } | 4708 | } |
4709 | 4709 | ||
4710 | GLenum COpenGLDriver::getZBufferBits() const | 4710 | GLenum COpenGLDriver::getZBufferBits() const |
4711 | { | 4711 | { |
4712 | GLenum bits = 0; | 4712 | GLenum bits = 0; |
4713 | switch (Params.ZBufferBits) | 4713 | switch (Params.ZBufferBits) |
4714 | { | 4714 | { |
4715 | case 16: | 4715 | case 16: |
4716 | bits = GL_DEPTH_COMPONENT16; | 4716 | bits = GL_DEPTH_COMPONENT16; |
4717 | break; | 4717 | break; |
4718 | case 24: | 4718 | case 24: |
4719 | bits = GL_DEPTH_COMPONENT24; | 4719 | bits = GL_DEPTH_COMPONENT24; |
4720 | break; | 4720 | break; |
4721 | case 32: | 4721 | case 32: |
4722 | bits = GL_DEPTH_COMPONENT32; | 4722 | bits = GL_DEPTH_COMPONENT32; |
4723 | break; | 4723 | break; |
4724 | default: | 4724 | default: |
4725 | bits = GL_DEPTH_COMPONENT; | 4725 | bits = GL_DEPTH_COMPONENT; |
4726 | break; | 4726 | break; |
4727 | } | 4727 | } |
4728 | return bits; | 4728 | return bits; |
4729 | } | 4729 | } |
4730 | 4730 | ||
4731 | #ifdef _IRR_COMPILE_WITH_CG_ | 4731 | #ifdef _IRR_COMPILE_WITH_CG_ |
4732 | const CGcontext& COpenGLDriver::getCgContext() | 4732 | const CGcontext& COpenGLDriver::getCgContext() |
4733 | { | 4733 | { |
4734 | return CgContext; | 4734 | return CgContext; |
4735 | } | 4735 | } |
4736 | #endif | 4736 | #endif |
4737 | 4737 | ||
4738 | 4738 | ||
4739 | } // end namespace | 4739 | } // end namespace |
4740 | } // end namespace | 4740 | } // end namespace |
4741 | 4741 | ||
4742 | #endif // _IRR_COMPILE_WITH_OPENGL_ | 4742 | #endif // _IRR_COMPILE_WITH_OPENGL_ |
4743 | 4743 | ||
4744 | namespace irr | 4744 | namespace irr |
4745 | { | 4745 | { |
4746 | namespace video | 4746 | namespace video |
4747 | { | 4747 | { |
4748 | 4748 | ||
4749 | 4749 | ||
4750 | // ----------------------------------- | 4750 | // ----------------------------------- |
4751 | // WINDOWS VERSION | 4751 | // WINDOWS VERSION |
4752 | // ----------------------------------- | 4752 | // ----------------------------------- |
4753 | #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ | 4753 | #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ |
4754 | IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, | 4754 | IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, |
4755 | io::IFileSystem* io, CIrrDeviceWin32* device) | 4755 | io::IFileSystem* io, CIrrDeviceWin32* device) |
4756 | { | 4756 | { |
4757 | #ifdef _IRR_COMPILE_WITH_OPENGL_ | 4757 | #ifdef _IRR_COMPILE_WITH_OPENGL_ |
4758 | COpenGLDriver* ogl = new COpenGLDriver(params, io, device); | 4758 | COpenGLDriver* ogl = new COpenGLDriver(params, io, device); |
4759 | if (!ogl->initDriver(device)) | 4759 | if (!ogl->initDriver(device)) |
4760 | { | 4760 | { |
4761 | ogl->drop(); | 4761 | ogl->drop(); |
4762 | ogl = 0; | 4762 | ogl = 0; |
4763 | } | 4763 | } |
4764 | return ogl; | 4764 | return ogl; |
4765 | #else | 4765 | #else |
4766 | return 0; | 4766 | return 0; |
4767 | #endif // _IRR_COMPILE_WITH_OPENGL_ | 4767 | #endif // _IRR_COMPILE_WITH_OPENGL_ |
4768 | } | 4768 | } |
4769 | #endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_ | 4769 | #endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_ |
4770 | 4770 | ||
4771 | // ----------------------------------- | 4771 | // ----------------------------------- |
4772 | // MACOSX VERSION | 4772 | // MACOSX VERSION |
4773 | // ----------------------------------- | 4773 | // ----------------------------------- |
4774 | #if defined(_IRR_COMPILE_WITH_OSX_DEVICE_) | 4774 | #if defined(_IRR_COMPILE_WITH_OSX_DEVICE_) |
4775 | IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, | 4775 | IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, |
4776 | io::IFileSystem* io, CIrrDeviceMacOSX *device) | 4776 | io::IFileSystem* io, CIrrDeviceMacOSX *device) |
4777 | { | 4777 | { |
4778 | #ifdef _IRR_COMPILE_WITH_OPENGL_ | 4778 | #ifdef _IRR_COMPILE_WITH_OPENGL_ |
4779 | return new COpenGLDriver(params, io, device); | 4779 | return new COpenGLDriver(params, io, device); |
4780 | #else | 4780 | #else |
4781 | return 0; | 4781 | return 0; |
4782 | #endif // _IRR_COMPILE_WITH_OPENGL_ | 4782 | #endif // _IRR_COMPILE_WITH_OPENGL_ |
4783 | } | 4783 | } |
4784 | #endif // _IRR_COMPILE_WITH_OSX_DEVICE_ | 4784 | #endif // _IRR_COMPILE_WITH_OSX_DEVICE_ |
4785 | 4785 | ||
4786 | // ----------------------------------- | 4786 | // ----------------------------------- |
4787 | // X11 VERSION | 4787 | // X11 VERSION |
4788 | // ----------------------------------- | 4788 | // ----------------------------------- |
4789 | #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ | 4789 | #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ |
4790 | IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, | 4790 | IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, |
4791 | io::IFileSystem* io, CIrrDeviceLinux* device) | 4791 | io::IFileSystem* io, CIrrDeviceLinux* device) |
4792 | { | 4792 | { |
4793 | #ifdef _IRR_COMPILE_WITH_OPENGL_ | 4793 | #ifdef _IRR_COMPILE_WITH_OPENGL_ |
4794 | COpenGLDriver* ogl = new COpenGLDriver(params, io, device); | 4794 | COpenGLDriver* ogl = new COpenGLDriver(params, io, device); |
4795 | if (!ogl->initDriver(device)) | 4795 | if (!ogl->initDriver(device)) |
4796 | { | 4796 | { |
4797 | ogl->drop(); | 4797 | ogl->drop(); |
4798 | ogl = 0; | 4798 | ogl = 0; |
4799 | } | 4799 | } |
4800 | return ogl; | 4800 | return ogl; |
4801 | #else | 4801 | #else |
4802 | return 0; | 4802 | return 0; |
4803 | #endif // _IRR_COMPILE_WITH_OPENGL_ | 4803 | #endif // _IRR_COMPILE_WITH_OPENGL_ |
4804 | } | 4804 | } |
4805 | #endif // _IRR_COMPILE_WITH_X11_DEVICE_ | 4805 | #endif // _IRR_COMPILE_WITH_X11_DEVICE_ |
4806 | 4806 | ||
4807 | 4807 | ||
4808 | // ----------------------------------- | 4808 | // ----------------------------------- |
4809 | // SDL VERSION | 4809 | // SDL VERSION |
4810 | // ----------------------------------- | 4810 | // ----------------------------------- |
4811 | #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ | 4811 | #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ |
4812 | IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, | 4812 | IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, |
4813 | io::IFileSystem* io, CIrrDeviceSDL* device) | 4813 | io::IFileSystem* io, CIrrDeviceSDL* device) |
4814 | { | 4814 | { |
4815 | #ifdef _IRR_COMPILE_WITH_OPENGL_ | 4815 | #ifdef _IRR_COMPILE_WITH_OPENGL_ |
4816 | return new COpenGLDriver(params, io, device); | 4816 | return new COpenGLDriver(params, io, device); |
4817 | #else | 4817 | #else |
4818 | return 0; | 4818 | return 0; |
4819 | #endif // _IRR_COMPILE_WITH_OPENGL_ | 4819 | #endif // _IRR_COMPILE_WITH_OPENGL_ |
4820 | } | 4820 | } |
4821 | #endif // _IRR_COMPILE_WITH_SDL_DEVICE_ | 4821 | #endif // _IRR_COMPILE_WITH_SDL_DEVICE_ |
4822 | 4822 | ||
4823 | } // end namespace | 4823 | } // end namespace |
4824 | } // end namespace | 4824 | } // end namespace |
4825 | 4825 | ||
4826 | 4826 | ||