source: trunk/src/video.cpp @ 2370

Last change on this file since 2370 was 2370, checked in by touky, 7 years ago

render : Added DebugRenderMode & corresponding shaders. naive (VERY) implementation in MeshViewer.

  • Property svn:keywords set to Id
File size: 9.5 KB
RevLine 
[105]1//
[221]2// Lol Engine
[105]3//
[2216]4// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
[221]5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
[2183]8//   http://www.wtfpl.net/ for more details.
[221]9//
[105]10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
[1233]15#if defined _XBOX
[1173]16#   include <xtl.h>
17#   undef near /* Fuck Microsoft */
18#   undef far /* Fuck Microsoft again */
19#elif defined _WIN32
[1233]20#   if defined USE_D3D9
21#      include <d3d9.h>
22#   endif
[105]23#   define WIN32_LEAN_AND_MEAN
24#   include <windows.h>
[1044]25#   undef near /* Fuck Microsoft */
26#   undef far /* Fuck Microsoft again */
[105]27#endif
28
[150]29#include "core.h"
[673]30#include "lolgl.h"
[105]31
[758]32using namespace std;
33
[1189]34/* FIXME: g_d3ddevice should never be exported */
[1208]35#if defined USE_D3D9
36IDirect3DDevice9 *g_d3ddevice;
37#   if defined USE_SDL
38extern HWND g_hwnd;
39#   endif
40#elif defined _XBOX
[1189]41D3DDevice *g_d3ddevice;
42#endif
43
[686]44namespace lol
45{
46
[784]47class VideoData
48{
49    friend class Video;
50
51private:
[1325]52    static mat4 proj_matrix;
[863]53    static ivec2 saved_viewport;
[2370]54    static DebugRenderMode render_mode;
[1771]55#if defined USE_D3D9 || defined _XBOX
56#   if defined USE_D3D9
[1208]57    static IDirect3D9 *d3d_ctx;
58    static IDirect3DDevice9 *d3d_dev;
[1771]59#   elif defined _XBOX
[1173]60    static Direct3D *d3d_ctx;
61    static D3DDevice *d3d_dev;
[1771]62#   endif
[1199]63    static D3DCOLOR clear_color;
[1771]64    static float clear_depth;
[1173]65#endif
[784]66};
[707]67
[784]68mat4 VideoData::proj_matrix;
[1050]69ivec2 VideoData::saved_viewport(0, 0);
[2370]70DebugRenderMode VideoData::render_mode = DebugRenderMode::Default;
[653]71
[1771]72#if defined USE_D3D9 || defined _XBOX
73#   if defined USE_D3D9
[1208]74IDirect3D9 *VideoData::d3d_ctx;
75IDirect3DDevice9 *VideoData::d3d_dev;
[1771]76#   elif defined _XBOX
[1173]77Direct3D *VideoData::d3d_ctx;
78D3DDevice *VideoData::d3d_dev;
[1771]79#   endif
[1199]80D3DCOLOR VideoData::clear_color;
[1771]81float VideoData::clear_depth;
[1173]82#endif
83
[105]84/*
85 * Public Video class
86 */
87
[863]88void Video::Setup(ivec2 size)
[105]89{
[1208]90#if defined USE_D3D9 || defined _XBOX
[1173]91    VideoData::d3d_ctx = Direct3DCreate9(D3D_SDK_VERSION);
92    if (!VideoData::d3d_ctx)
93    {
94        Log::Error("cannot initialise D3D\n");
95        exit(EXIT_FAILURE);
96    }
97
[1208]98    HWND window = 0;
[1173]99    D3DPRESENT_PARAMETERS d3dpp;
100    memset(&d3dpp, 0, sizeof(d3dpp));
101
[1208]102#   if defined USE_SDL
103    window = g_hwnd;
104    d3dpp.hDeviceWindow = g_hwnd;
105    d3dpp.Windowed = TRUE;
106#   elif defined _XBOX
[1173]107    XVIDEO_MODE VideoMode;
108    XGetVideoMode( &VideoMode );
109    if (size.x > VideoMode.dwDisplayWidth)
110        size.x = VideoMode.dwDisplayWidth;
111    if (size.y > VideoMode.dwDisplayHeight)
112        size.y = VideoMode.dwDisplayHeight;
[1208]113#   endif
[1173]114    VideoData::saved_viewport = size;
115
116    d3dpp.BackBufferWidth = size.x;
117    d3dpp.BackBufferHeight = size.y;
118    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
119    d3dpp.BackBufferCount = 1;
120    d3dpp.EnableAutoDepthStencil = TRUE;
121    d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
122    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
123    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
124
[1208]125    HRESULT hr = VideoData::d3d_ctx->CreateDevice(0, D3DDEVTYPE_HAL, window,
126                                                  D3DCREATE_HARDWARE_VERTEXPROCESSING,
127                                                  &d3dpp, &VideoData::d3d_dev);
128    if (FAILED(hr))
[1173]129    {
130        Log::Error("cannot create D3D device\n");
131        exit(EXIT_FAILURE);
132    }
[1189]133
134    g_d3ddevice = VideoData::d3d_dev;
[1173]135#else
136#   if defined USE_GLEW && !defined __APPLE__
[808]137    /* Initialise GLEW if necessary */
138    GLenum glerr = glewInit();
139    if (glerr != GLEW_OK)
140    {
141        Log::Error("cannot initialise GLEW: %s\n", glewGetErrorString(glerr));
142        exit(EXIT_FAILURE);
143    }
[1173]144#   endif
[808]145
[105]146    /* Initialise OpenGL */
[755]147    glViewport(0, 0, size.x, size.y);
[784]148    VideoData::saved_viewport = size;
[707]149
[1173]150#   if defined HAVE_GL_2X && !defined __APPLE__
[207]151    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
[1173]152#   endif
[674]153#endif
[1771]154
155    /* Initialise reasonable scene default properties */
156    SetClearColor(vec4(0.1f, 0.2f, 0.3f, 1.0f));
157    SetClearDepth(1.f);
[2370]158    SetDebugRenderMode(DebugRenderMode::Default);
[209]159}
[207]160
[209]161void Video::SetFov(float theta)
162{
[755]163    vec2 size = GetSize();
164    float near = -size.x - size.y;
165    float far = size.x + size.y;
[209]166
[939]167#if defined __ANDROID__
[780]168    size = vec2(640.0f, 480.0f);
[727]169#endif
170
[209]171    /* Set the projection matrix */
172    if (theta < 1e-4f)
173    {
174        /* The easy way: purely orthogonal projection. */
[784]175        VideoData::proj_matrix = mat4::ortho(0, size.x, 0, size.y, near, far);
[209]176    }
177    else
178    {
179        /* Compute a view that approximates the glOrtho view when theta
180         * approaches zero. This view ensures that the z=0 plane fills
181         * the screen. */
182        float t1 = tanf(theta / 2);
[755]183        float t2 = t1 * size.y / size.y;
184        float dist = size.x / (2.0f * t1);
[209]185
186        near += dist;
187        far += dist;
188
189        if (near <= 0.0f)
190        {
191            far -= (near - 1.0f);
192            near = 1.0f;
193        }
194
[784]195        mat4 proj = mat4::frustum(-near * t1, near * t1,
196                                  -near * t2, near * t2, near, far);
197        mat4 trans = mat4::translate(-0.5f * size.x, -0.5f * size.y, -dist);
198        VideoData::proj_matrix = proj * trans;
[209]199    }
[105]200}
201
[211]202void Video::SetDepth(bool set)
203{
[1208]204#if defined USE_D3D9 || defined _XBOX
[1179]205#   define STR0(x) #x
206#   define STR(x) STR0(x)
207#   pragma message(__FILE__ "(" STR(__LINE__) "): warning: Video::SetDepth() not implemented")
208#else
[211]209    if (set)
210        glEnable(GL_DEPTH_TEST);
211    else
212        glDisable(GL_DEPTH_TEST);
[1179]213#endif
[211]214}
215
[1199]216void Video::SetClearColor(vec4 color)
217{
[1208]218#if defined USE_D3D9 || defined _XBOX
[1199]219    VideoData::clear_color = D3DCOLOR_XRGB((int)(color.r * 255.999f),
220                                           (int)(color.g * 255.999f),
221                                           (int)(color.b * 255.999f));
222#else
223    glClearColor(color.r, color.g, color.b, color.a);
224#endif
225}
226
[1771]227void Video::SetClearDepth(float f)
[105]228{
[1208]229#if defined USE_D3D9 || defined _XBOX
[1771]230    VideoData::clear_depth = f;
[2085]231#elif defined HAVE_GLES_2X
232    glClearDepthf(f);
[1771]233#else
234    glClearDepth(f);
235#endif
236}
237
[2370]238void Video::SetDebugRenderMode(DebugRenderMode d)
239{
240    if (d == DebugRenderMode::Max)
241        return;
242
243    switch(d)
244    {
245        //All these modes are handled in the shaders.
246        case DebugRenderMode::Default:
247        case DebugRenderMode::Lighting:
248        case DebugRenderMode::Normal:
249        case DebugRenderMode::UV:
250        {
251#if defined USE_D3D9 || defined _XBOX
252#else
253            glEnable(GL_CULL_FACE);
254            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
255#endif
256            break;
257        }
258        case DebugRenderMode::Wireframe:
259        {
260            if (VideoData::render_mode == DebugRenderMode::Wireframe)
261            {
262#if defined USE_D3D9 || defined _XBOX
263#else
264                if (glIsEnabled(GL_CULL_FACE) == GL_TRUE)
265                    glDisable(GL_CULL_FACE);
266                else
267                    glEnable(GL_CULL_FACE);
268#endif
269            }
270            else
271            {
272#if defined USE_D3D9 || defined _XBOX
273#else
274                glDisable(GL_CULL_FACE);
275#endif
276            }
277#if defined USE_D3D9 || defined _XBOX
278#else
279            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
280#endif
281            break;
282        }
283    }
284    VideoData::render_mode = d;
285}
286
287DebugRenderMode Video::GetDebugRenderMode()
288{
289    return VideoData::render_mode;
290}
291
[1771]292void Video::Clear(ClearMask m)
293{
294#if defined USE_D3D9 || defined _XBOX
295    int mask = 0;
296    if (m & ClearMask::Color)
297        mask |= D3DCLEAR_TARGET;
298    if (m & ClearMask::Depth)
299        mask |= D3DCLEAR_ZBUFFER;
300    if (m & ClearMask::Stencil)
301        mask |= D3DCLEAR_STENCIL;
302    if (FAILED(VideoData::d3d_dev->Clear(0, NULL, mask,
303                                         VideoData::clear_color,
304                                         VideoData::clear_depth, 0)))
[1236]305        Abort();
[1173]306#else
[1771]307    /* FIXME: is this necessary here? */
308    ivec2 size = GetSize();
[755]309    glViewport(0, 0, size.x, size.y);
[1771]310
311    GLbitfield mask = 0;
312    if (m & ClearMask::Color)
313        mask |= GL_COLOR_BUFFER_BIT;
314    if (m & ClearMask::Depth)
315        mask |= GL_DEPTH_BUFFER_BIT;
316    if (m & ClearMask::Stencil)
317        mask |= GL_STENCIL_BUFFER_BIT;
318    glClear(mask);
[1173]319#endif
[653]320
[662]321    SetFov(0.0f);
[105]322}
[139]323
[653]324void Video::Destroy()
325{
[784]326    ;
[653]327}
328
[140]329void Video::Capture(uint32_t *buffer)
330{
[1208]331#if defined USE_D3D9 || defined _XBOX
[1173]332    /* TODO */
333#else
[140]334    GLint v[4];
[1173]335#   if defined __CELLOS_LV2__
[758]336    // FIXME: use psglCreateDeviceAuto && psglGetDeviceDimensions
337    v[2] = 1920;
338    v[3] = 1080;
[1173]339#   else
[140]340    glGetIntegerv(GL_VIEWPORT, v);
[1173]341#   endif
[140]342    int width = v[2], height = v[3];
343
[1173]344#   if defined HAVE_GL_2X
[140]345    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
[1173]346#   endif
[140]347    glPixelStorei(GL_PACK_ALIGNMENT, 1);
348
[1173]349#   if defined GL_BGRA
[615]350    glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, buffer);
[1173]351#   else
[216]352    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
[1173]353#   endif
[140]354
355    for (int j = 0; j < height / 2; j++)
356        for (int i = 0; i < width; i++)
357        {
358            uint32_t tmp = buffer[j * width + i];
359            buffer[j * width + i] = buffer[(height - j - 1) * width + i];
360            buffer[(height - j - 1) * width + i] = tmp;
361        }
[1173]362#endif
[140]363}
364
[863]365ivec2 Video::GetSize()
[139]366{
[1208]367#if defined USE_D3D9 || defined _XBOX
[1173]368    return VideoData::saved_viewport;
369#elif 1
[1108]370    /* GetSize() is called too often on the game thread; we cannot rely on
371     * the GL context at this point */
[784]372    return VideoData::saved_viewport;
[758]373#elif defined __CELLOS_LV2__
374    // FIXME: use psglCreateDeviceAuto && psglGetDeviceDimensions
[707]375#else
[139]376    GLint v[4];
377    glGetIntegerv(GL_VIEWPORT, v);
[863]378    return ivec2(v[2], v[3]);
[707]379#endif
[139]380}
381
[686]382} /* namespace lol */
383
Note: See TracBrowser for help on using the repository browser.