source: trunk/src/scene.cpp @ 1329

Last change on this file since 1329 was 1329, checked in by sam, 10 years ago

core: convert some realloc() calls to our nice dynamic Array class.

  • Property svn:keywords set to Id
File size: 12.3 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
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
8//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <cstdlib>
16#include <cmath>
17
18#ifdef WIN32
19#   define WIN32_LEAN_AND_MEAN
20#   include <windows.h>
21#endif
22
23#include "core.h"
24#include "lolgl.h"
25
26namespace lol
27{
28
29struct Tile
30{
31    TileSet *tileset;
32    uint32_t prio;
33    vec3 pos;
34    vec2 scale;
35    int id, o;
36};
37
38/*
39 * Scene implementation class
40 */
41
42class SceneData
43{
44    friend class Scene;
45
46private:
47    static int Compare(void const *p1, void const *p2)
48    {
49        Tile const *t1 = (Tile const *)p1;
50        Tile const *t2 = (Tile const *)p2;
51
52        return t2->prio - t1->prio;
53    }
54
55    mat4 m_model_matrix;
56    mat4 m_view_matrix;
57    mat4 m_proj_matrix;
58
59    Array<Tile> tiles;
60
61    Shader *m_shader;
62    VertexDeclaration *m_vdecl;
63    Array<VertexBuffer *> bufs;
64
65    static Scene *scene;
66};
67
68Scene *SceneData::scene = NULL;
69
70/*
71 * Public Scene class
72 */
73
74Scene::Scene()
75  : data(new SceneData())
76{
77    data->m_model_matrix = mat4(1.f);
78    data->m_view_matrix = mat4(1.f);
79    data->m_proj_matrix = mat4::ortho(0, Video::GetSize().x,
80                                      0, Video::GetSize().y, -1000.f, 1000.f);
81
82    data->m_shader = 0;
83    data->m_vdecl = new VertexDeclaration(VertexStream<vec3>(VertexUsage::Position),
84                                          VertexStream<vec2>(VertexUsage::TexCoord));
85}
86
87Scene::~Scene()
88{
89    /* FIXME: this must be done while the GL context is still active.
90     * Change the code architecture to make sure of that. */
91    /* FIXME: also, make sure we do not add code to Reset() that will
92     * reallocate stuff */
93    Reset();
94
95    delete data->m_vdecl;
96    delete data;
97}
98
99Scene *Scene::GetDefault()
100{
101    if (!SceneData::scene)
102        SceneData::scene = new Scene();
103    return SceneData::scene;
104}
105
106void Scene::Reset()
107{
108    for (int i = 0; i < data->bufs.Count(); i++)
109        delete data->bufs[i];
110    data->bufs.Empty();
111}
112
113void Scene::SetViewMatrix(mat4 const &m)
114{
115    data->m_view_matrix = m;
116}
117
118void Scene::SetProjMatrix(mat4 const &m)
119{
120    data->m_proj_matrix = m;
121}
122
123mat4 const &Scene::GetViewMatrix(void)
124{
125    return data->m_view_matrix;
126}
127
128mat4 const &Scene::GetProjMatrix(void)
129{
130    return data->m_proj_matrix;
131}
132
133void Scene::AddTile(TileSet *tileset, int id, vec3 pos, int o, vec2 scale)
134{
135    Tile t;
136    /* FIXME: this sorting only works for a 45-degree camera */
137    t.prio = -pos.y - 2 * 32 * pos.z + (o ? 0 : 32);
138    t.tileset = tileset;
139    t.id = id;
140    t.pos = pos;
141    t.o = o;
142    t.scale = scale;
143
144    data->tiles.Push(t);
145}
146
147void Scene::Render() // XXX: rename to Blit()
148{
149    if (!data->m_shader)
150    {
151#if !defined _XBOX && !defined __CELLOS_LV2__ && !defined USE_D3D9
152        data->m_shader = Shader::Create(
153#   if !defined HAVE_GLES_2X
154            "#version 130\n"
155#   endif
156            "\n"
157#   if defined HAVE_GLES_2X
158            "attribute vec3 in_Position;\n"
159            "attribute vec2 in_TexCoord;\n"
160            "varying vec2 pass_TexCoord;\n"
161#   else
162            "in vec3 in_Position;\n"
163            "in vec2 in_TexCoord;\n"
164#   endif
165            "uniform mat4 proj_matrix;\n"
166            "uniform mat4 view_matrix;\n"
167            "uniform mat4 model_matrix;\n"
168            "\n"
169            "void main()\n"
170            "{\n"
171            "    gl_Position = proj_matrix * view_matrix * model_matrix"
172            "                * vec4(in_Position, 1.0);\n"
173#   if defined HAVE_GLES_2X
174            "    pass_TexCoord = in_TexCoord;\n"
175#   else
176            "    gl_TexCoord[0] = vec4(in_TexCoord, 0.0, 0.0);\n"
177#   endif
178            "}\n",
179
180#   if !defined HAVE_GLES_2X
181            "#version 130\n"
182#   else
183            "precision mediump float;\n"
184#   endif
185            "\n"
186            "uniform sampler2D in_Texture;\n"
187#   if defined HAVE_GLES_2X
188            "varying vec2 pass_TexCoord;\n"
189#   endif
190            "\n"
191            "void main()\n"
192            "{\n"
193#   if defined HAVE_GLES_2X
194            "    vec4 col = texture2D(in_Texture, pass_TexCoord);\n"
195            //"    vec4 col = vec4(0.5, 1.0, 0.0, 0.5);\n"
196            //"    vec4 col = vec4(pass_TexCoord * 4.0, 0.0, 0.25);\n"
197#   else
198            "    vec4 col = texture2D(in_Texture, vec2(gl_TexCoord[0]));\n"
199#   endif
200#   if 0
201            "    float mul = 2.0;\n"
202#       if 1
203            "    vec2 d1 = mod(vec2(gl_FragCoord), vec2(2.0, 2.0));\n"
204            "    float t1 = mod(3.0 * d1.x + 2.0 * d1.y, 4.0);\n"
205            "    float dx2 = mod(floor(gl_FragCoord.x * 0.5), 2.0);\n"
206            "    float dy2 = mod(floor(gl_FragCoord.y * 0.5), 2.0);\n"
207            "    float t2 = mod(3.0 * dx2 + 2.0 * dy2, 4.0);\n"
208            "    float dx3 = mod(floor(gl_FragCoord.x * 0.25), 2.0);\n"
209            "    float dy3 = mod(floor(gl_FragCoord.y * 0.25), 2.0);\n"
210            "    float t3 = mod(3.0 * dx3 + 2.0 * dy3, 4.0);\n"
211            "    t1 = (1.0 + 16.0 * t1 + 4.0 * t2 + t3) / 65.0;\n"
212            "    t2 = t1;\n"
213            "    t3 = t1;\n"
214#       else
215            "    float rand = sin(gl_FragCoord.x * 1.23456) * 123.456\n"
216            "               + cos(gl_FragCoord.y * 2.34567) * 789.012;\n"
217            "    float t1 = mod(sin(rand) * 17.13043, 1.0);\n"
218            "    float t2 = mod(sin(rand) * 27.13043, 1.0);\n"
219            "    float t3 = mod(sin(rand) * 37.13043, 1.0);\n"
220#       endif
221            "    float fracx = fract(col.x * mul);\n"
222            "    float fracy = fract(col.y * mul);\n"
223            "    float fracz = fract(col.z * mul);\n"
224            "    fracx = fracx > t1 ? 1.0 : 0.0;\n"
225            "    fracy = fracy > t2 ? 1.0 : 0.0;\n"
226            "    fracz = fracz > t3 ? 1.0 : 0.0;\n"
227            "    col.x = (floor(col.x * mul) + fracx) / mul;\n"
228            "    col.y = (floor(col.y * mul) + fracy) / mul;\n"
229            "    col.z = (floor(col.z * mul) + fracz) / mul;\n"
230#   endif
231            "    gl_FragColor = col;\n"
232            "}\n");
233#else
234        data->m_shader = Shader::Create(
235            "void main(float4 in_Position : POSITION,"
236            "          float2 in_TexCoord : TEXCOORD0,"
237            "          uniform float4x4 proj_matrix,"
238            "          uniform float4x4 view_matrix,"
239            "          uniform float4x4 model_matrix,"
240            "          out float2 out_TexCoord : TEXCOORD0,"
241            "          out float4 out_Position : POSITION)"
242            "{"
243            "    out_Position = mul(proj_matrix, mul(view_matrix, mul(model_matrix, in_Position)));"
244            "    out_TexCoord = in_TexCoord;"
245            "}",
246
247            "void main(float2 in_TexCoord : TEXCOORD0,"
248#   if 0
249            "          float4 in_FragCoord : WPOS,"
250#   endif
251            "          uniform sampler2D tex,"
252            "          out float4 out_FragColor : COLOR)"
253            "{"
254            "    float4 col = tex2D(tex, in_TexCoord);"
255#   if 0
256            "    float mul = 2.0;\n"
257            "    float t1, t2, t3;\n"
258#       if 1
259            "    float dx1 = frac(in_FragCoord.x * 0.5) * 2.0;\n"
260            "    float dy1 = frac(in_FragCoord.y * 0.5) * 2.0;\n"
261            "    t1 = frac((3.0 * dx1 + 2.0 * dy1) / 4.0) * 4.0;\n"
262            "    float dx2 = frac(floor(in_FragCoord.x * 0.5) * 0.5) * 2.0;\n"
263            "    float dy2 = frac(floor(in_FragCoord.y * 0.5) * 0.5) * 2.0;\n"
264            "    t2 = frac((3.0 * dx2 + 2.0 * dy2) / 4.0) * 4.0;\n"
265            "    float dx3 = frac(floor(in_FragCoord.x * 0.25) * 0.5) * 2.0;\n"
266            "    float dy3 = frac(floor(in_FragCoord.y * 0.25) * 0.5) * 2.0;\n"
267            "    t3 = frac((3.0 * dx3 + 2.0 * dy3) / 4.0) * 4.0;\n"
268            "    t1 = (1.0 + 4.0 * t1 + t2) / 17.0;\n"
269            "    t2 = t1;\n"
270            "    t3 = t1;\n"
271#       else
272            "    float rand = sin(in_FragCoord.x * 1.23456) * 123.456\n"
273            "               + cos(in_FragCoord.y * 2.34567) * 789.012;\n"
274            "    t1 = frac(sin(rand) * 17.13043);\n"
275            "    t2 = frac(sin(rand) * 27.13043);\n"
276            "    t3 = frac(sin(rand) * 37.13043);\n"
277#       endif
278            "    float fracx = frac(col.x * mul);\n"
279            "    float fracy = frac(col.y * mul);\n"
280            "    float fracz = frac(col.z * mul);\n"
281            "    fracx = fracx > t1 ? 1.0 : 0.0;\n"
282            "    fracy = fracy > t2 ? 1.0 : 0.0;\n"
283            "    fracz = fracz > t3 ? 1.0 : 0.0;\n"
284            "    col.x = (floor(col.x * mul) + fracx) / mul;\n"
285            "    col.y = (floor(col.y * mul) + fracy) / mul;\n"
286            "    col.z = (floor(col.z * mul) + fracz) / mul;\n"
287#   endif
288            "    out_FragColor = col;"
289            "}");
290#endif
291    }
292
293#if 0
294    // Randomise, then sort.
295    for (int i = 0; i < data->tiles.Count(); i++)
296    {
297        Tile tmp = data->tiles[i];
298        int j = rand() % data->tiles.Count();
299        data->tiles[i] = data->tiles[j];
300        data->tiles[j] = tmp;
301    }
302#endif
303    qsort(&data->tiles[0], data->tiles.Count(),
304          sizeof(Tile), SceneData::Compare);
305
306    // XXX: debug stuff
307    data->m_model_matrix = mat4::translate(320.0f, 240.0f, 0.0f);
308#if 0
309    static float f = 0.0f;
310    f += 0.01f;
311    data->m_model_matrix *= mat4::rotate(6.0f * sinf(f), 1.0f, 0.0f, 0.0f);
312    data->m_model_matrix *= mat4::rotate(17.0f * cosf(f), 0.0f, 0.0f, 1.0f);
313#endif
314    data->m_model_matrix *= mat4::translate(-320.0f, -240.0f, 0.0f);
315    // XXX: end of debug stuff
316
317    ShaderUniform uni_mat, uni_tex;
318    ShaderAttrib attr_pos, attr_tex;
319    attr_pos = data->m_shader->GetAttribLocation("in_Position", VertexUsage::Position, 0);
320    attr_tex = data->m_shader->GetAttribLocation("in_TexCoord", VertexUsage::TexCoord, 0);
321
322    data->m_shader->Bind();
323
324    uni_mat = data->m_shader->GetUniformLocation("proj_matrix");
325    data->m_shader->SetUniform(uni_mat, data->m_proj_matrix);
326    uni_mat = data->m_shader->GetUniformLocation("view_matrix");
327    data->m_shader->SetUniform(uni_mat, data->m_view_matrix);
328    uni_mat = data->m_shader->GetUniformLocation("model_matrix");
329    data->m_shader->SetUniform(uni_mat, data->m_model_matrix);
330
331#if defined USE_D3D9 || defined _XBOX
332#else
333    uni_tex = data->m_shader->GetUniformLocation("in_Texture");
334    data->m_shader->SetUniform(uni_tex, 0);
335
336#if !defined HAVE_GLES_2X
337    glEnable(GL_TEXTURE_2D);
338#endif
339    glEnable(GL_DEPTH_TEST);
340    glDepthFunc(GL_LEQUAL);
341#if defined HAVE_GL_2X && !defined __APPLE__
342    glEnable(GL_ALPHA_TEST);
343    glAlphaFunc(GL_GEQUAL, 0.01f);
344#endif
345    glEnable(GL_BLEND);
346    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
347#endif
348
349    for (int buf = 0, i = 0, n; i < data->tiles.Count(); i = n, buf += 2)
350    {
351        /* Count how many quads will be needed */
352        for (n = i + 1; n < data->tiles.Count(); n++)
353            if (data->tiles[i].tileset != data->tiles[n].tileset)
354                break;
355
356        /* Create a vertex array object */
357        VertexBuffer *vb1 = new VertexBuffer(6 * 3 * (n - i) * sizeof(float));
358        float *vertex = (float *)vb1->Lock(0, 0);
359        VertexBuffer *vb2 = new VertexBuffer(6 * 2 * (n - i) * sizeof(float));
360        float *texture = (float *)vb2->Lock(0, 0);
361
362        data->bufs.Push(vb1);
363        data->bufs.Push(vb2);
364
365        for (int j = i; j < n; j++)
366        {
367            data->tiles[i].tileset->BlitTile(data->tiles[j].id,
368                            data->tiles[j].pos, data->tiles[j].o,
369                            data->tiles[j].scale,
370                            vertex + 18 * (j - i), texture + 12 * (j - i));
371        }
372
373        vb1->Unlock();
374        vb2->Unlock();
375
376        /* Bind texture */
377        data->tiles[i].tileset->Bind();
378
379        /* Bind vertex and texture coordinate buffers */
380        data->m_vdecl->Bind();
381        data->m_vdecl->SetStream(vb1, attr_pos);
382        data->m_vdecl->SetStream(vb2, attr_tex);
383
384        /* Draw arrays */
385        data->m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, (n - i) * 2);
386        data->m_vdecl->Unbind();
387        data->tiles[i].tileset->Unbind();
388    }
389
390    data->tiles.Empty();
391
392    data->m_shader->Unbind();
393
394#if defined USE_D3D9 || defined _XBOX
395    /* TODO */
396#else
397#if !defined HAVE_GLES_2X
398    glDisable(GL_TEXTURE_2D);
399#endif
400    glDisable(GL_DEPTH_TEST);
401#if defined HAVE_GL_2X && !defined __APPLE__
402    glDisable(GL_ALPHA_TEST);
403#endif
404    glDisable(GL_BLEND);
405#endif
406}
407
408} /* namespace lol */
409
Note: See TracBrowser for help on using the repository browser.