source: trunk/src/scene.cpp @ 1687

Last change on this file since 1687 was 1513, checked in by sam, 9 years ago

core: replace usage of sin() or std::sin() with lol::sin() where appropriate.

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