source: trunk/src/scene.cpp @ 790

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

tileset: replace the Tiler ID system with real TileSet objects. The only
thing that is still broken is the Layer <--> Map interface.

  • Property svn:keywords set to Id
File size: 9.7 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2011 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    int id, x, y, z, o;
34};
35
36static Shader *stdshader = NULL;
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 model_matrix;
56
57    Tile *tiles;
58    int ntiles;
59    float angle;
60
61#if defined HAVE_GL_2X
62    GLuint vao;
63#endif
64    GLuint *bufs;
65    int nbufs;
66
67    static Scene *scene;
68};
69
70Scene *SceneData::scene = NULL;
71
72/*
73 * Public Scene class
74 */
75
76Scene::Scene(float angle)
77  : data(new SceneData())
78{
79    data->tiles = 0;
80    data->ntiles = 0;
81    data->angle = angle;
82
83    data->bufs = 0;
84    data->nbufs = 0;
85
86#if defined HAVE_GL_2X
87    glGenVertexArrays(1, &data->vao);
88#endif
89}
90
91Scene::~Scene()
92{
93    /* FIXME: this must be done while the GL context is still active.
94     * Change the architecture to make sure of that. */
95    glDeleteBuffers(data->nbufs, data->bufs);
96#if defined HAVE_GL_2X
97    glDeleteVertexArrays(1, &data->vao);
98#endif
99    free(data->bufs);
100    delete data;
101}
102
103Scene *Scene::GetDefault()
104{
105    if (!SceneData::scene)
106        SceneData::scene = new Scene(0.0f);
107    return SceneData::scene;
108}
109
110void Scene::Reset()
111{
112    if (SceneData::scene)
113        delete SceneData::scene;
114    SceneData::scene = NULL;
115}
116
117void Scene::AddTile(TileSet *tileset, int id, int x, int y, int z, int o)
118{
119    if ((data->ntiles % 1024) == 0)
120        data->tiles = (Tile *)realloc(data->tiles,
121                                      (data->ntiles + 1024) * sizeof(Tile));
122    /* FIXME: this sorting only works for a 45-degree camera */
123    data->tiles[data->ntiles].prio = -y - 2 * 32 * z + (o ? 0 : 32);
124    data->tiles[data->ntiles].tileset = tileset;
125    data->tiles[data->ntiles].id = id;
126    data->tiles[data->ntiles].x = x;
127    data->tiles[data->ntiles].y = y;
128    data->tiles[data->ntiles].z = z;
129    data->tiles[data->ntiles].o = o;
130    data->ntiles++;
131}
132
133void Scene::Render() // XXX: rename to Blit()
134{
135    if (!stdshader)
136    {
137        stdshader = Shader::Create(
138            "#version 130\n"
139            "\n"
140#if defined HAVE_GLES_2X
141            "attribute vec3 in_Position;\n"
142            "attribute vec2 in_TexCoord;\n"
143            "varying vec2 pass_TexCoord;\n"
144#else
145            "in vec3 in_Position;\n"
146            "in vec2 in_TexCoord;\n"
147#endif
148            "uniform mat4 proj_matrix;\n"
149            "uniform mat4 view_matrix;\n"
150            "uniform mat4 model_matrix;\n"
151            "\n"
152            "void main()\n"
153            "{\n"
154            "    gl_Position = proj_matrix * view_matrix * model_matrix"
155            "                * vec4(in_Position, 1.0);\n"
156#if defined HAVE_GLES_2X
157            "    pass_TexCoord = in_TexCoord;\n"
158#else
159            "    gl_TexCoord[0] = vec4(in_TexCoord, 0.0, 0.0);\n"
160#endif
161            "}\n",
162
163            "#version 130\n"
164            "\n"
165            "uniform sampler2D in_Texture;\n"
166#if defined HAVE_GLES_2X
167            "varying vec2 pass_TexCoord;\n"
168#endif
169            "\n"
170            "void main()\n"
171            "{\n"
172#if defined HAVE_GLES_2X
173            "    vec4 col = texture2D(in_Texture, pass_TexCoord);\n"
174            //"    vec4 col = vec4(0.5, 1.0, 0.0, 0.5);\n"
175            //"    vec4 col = vec4(pass_TexCoord * 4.0, 0.0, 0.25);\n"
176#else
177            "    vec4 col = texture2D(in_Texture, vec2(gl_TexCoord[0]));\n"
178#endif
179#if 0
180            "    float mul = 2.0;\n"
181#if 0
182            "    vec2 d1 = mod(vec2(gl_FragCoord), vec2(2.0, 2.0));\n"
183            "    float t1 = mod(3.0 * d1.x + 2.0 * d1.y, 4.0);\n"
184            "    float dx2 = mod(floor(gl_FragCoord.x * 0.5), 2.0);\n"
185            "    float dy2 = mod(floor(gl_FragCoord.y * 0.5), 2.0);\n"
186            "    float t2 = mod(3.0 * dx2 + 2.0 * dy2, 4.0);\n"
187            "    float dx3 = mod(floor(gl_FragCoord.x * 0.25), 2.0);\n"
188            "    float dy3 = mod(floor(gl_FragCoord.y * 0.25), 2.0);\n"
189            "    float t3 = mod(3.0 * dx3 + 2.0 * dy3, 4.0);\n"
190            "    float t1 = (1.0 + 16.0 * t1 + 4.0 * t2 + t3) / 65.0;\n"
191            "    float t2 = t1;\n"
192            "    float t3 = t1;\n"
193#else
194            "    float rand = sin(gl_FragCoord.x * 1.23456) * 123.456\n"
195            "               + cos(gl_FragCoord.y * 2.34567) * 789.012;\n"
196            "    float t1 = mod(sin(rand) * 17.13043, 1.0);\n"
197            "    float t2 = mod(sin(rand) * 27.13043, 1.0);\n"
198            "    float t3 = mod(sin(rand) * 37.13043, 1.0);\n"
199#endif
200            "    float fracx = fract(col.x * mul);\n"
201            "    float fracy = fract(col.y * mul);\n"
202            "    float fracz = fract(col.z * mul);\n"
203            "    fracx = fracx > t1 ? 1.0 : 0.0;\n"
204            "    fracy = fracy > t2 ? 1.0 : 0.0;\n"
205            "    fracz = fracz > t3 ? 1.0 : 0.0;\n"
206            "    col.x = (floor(col.x * mul) + fracx) / mul;\n"
207            "    col.y = (floor(col.y * mul) + fracy) / mul;\n"
208            "    col.z = (floor(col.z * mul) + fracz) / mul;\n"
209#endif
210            "    gl_FragColor = col;\n"
211            "}\n");
212    }
213
214#if 0
215    // Randomise, then sort.
216    for (int i = 0; i < data->ntiles; i++)
217    {
218        Tile tmp = data->tiles[i];
219        int j = rand() % data->ntiles;
220        data->tiles[i] = data->tiles[j];
221        data->tiles[j] = tmp;
222    }
223#endif
224    qsort(data->tiles, data->ntiles, sizeof(Tile), SceneData::Compare);
225
226    // XXX: debug stuff
227    data->model_matrix = mat4::translate(320.0f, 240.0f, 0.0f);
228    data->model_matrix *= mat4::rotate(-data->angle, 1.0f, 0.0f, 0.0f);
229#if 0
230    static float f = 0.0f;
231    f += 0.01f;
232    data->model_matrix *= mat4::rotate(0.1f * sinf(f), 1.0f, 0.0f, 0.0f);
233    data->model_matrix *= mat4::rotate(0.3f * cosf(f), 0.0f, 0.0f, 1.0f);
234#endif
235    data->model_matrix *= mat4::translate(-320.0f, -240.0f, 0.0f);
236    // XXX: end of debug stuff
237
238    GLuint uni_mat, uni_tex, attr_pos, attr_tex;
239    attr_pos = stdshader->GetAttribLocation("in_Position");
240    attr_tex = stdshader->GetAttribLocation("in_TexCoord");
241
242#if !defined __CELLOS_LV2__ // Use cgGetNamedParameter etc.
243    stdshader->Bind();
244
245    uni_mat = stdshader->GetUniformLocation("proj_matrix");
246    glUniformMatrix4fv(uni_mat, 1, GL_FALSE, &Video::GetProjMatrix()[0][0]);
247    uni_mat = stdshader->GetUniformLocation("view_matrix");
248    glUniformMatrix4fv(uni_mat, 1, GL_FALSE, &Video::GetViewMatrix()[0][0]);
249    uni_mat = stdshader->GetUniformLocation("model_matrix");
250    glUniformMatrix4fv(uni_mat, 1, GL_FALSE, &data->model_matrix[0][0]);
251
252    uni_tex = stdshader->GetUniformLocation("in_Texture");
253    glUniform1i(uni_tex, 0);
254#endif
255
256    glEnable(GL_TEXTURE_2D);
257    glEnable(GL_DEPTH_TEST);
258    glDepthFunc(GL_LEQUAL);
259#if defined HAVE_GL_2X
260    glEnable(GL_ALPHA_TEST);
261    glAlphaFunc(GL_GEQUAL, 0.01f);
262#endif
263    glEnable(GL_BLEND);
264    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
265
266    for (int buf = 0, i = 0, n; i < data->ntiles; i = n, buf += 2)
267    {
268        /* Generate new vertex / texture coord buffers if necessary */
269        if (buf + 2 > data->nbufs)
270        {
271            data->bufs = (GLuint *)realloc(data->bufs, (buf + 2) * sizeof(GLuint));
272            glGenBuffers(buf + 2 - data->nbufs, data->bufs + data->nbufs);
273            data->nbufs = buf + 2;
274        }
275
276        /* Count how many quads will be needed */
277        for (n = i + 1; n < data->ntiles; n++)
278            if (data->tiles[i].tileset != data->tiles[n].tileset)
279                break;
280
281        /* Create a vertex array object */
282        float *vertex = (float *)malloc(6 * 3 * (n - i) * sizeof(float));
283        float *texture = (float *)malloc(6 * 2 * (n - i) * sizeof(float));
284
285        for (int j = i; j < n; j++)
286        {
287            data->tiles[i].tileset->BlitTile(data->tiles[j].id,
288                            data->tiles[j].x, data->tiles[j].y,
289                            data->tiles[j].z, data->tiles[j].o,
290                            vertex + 18 * (j - i), texture + 12 * (j - i));
291        }
292
293        stdshader->Bind();
294
295        /* Bind texture */
296        data->tiles[i].tileset->Bind();
297
298        /* Bind vertex, color and texture coordinate buffers */
299#if defined HAVE_GL_2X
300        glBindVertexArray(data->vao);
301#endif
302#if !defined __CELLOS_LV2__ // Use cgGLEnableClientState etc.
303        glEnableVertexAttribArray(attr_pos);
304        glEnableVertexAttribArray(attr_tex);
305
306        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]);
307        glBufferData(GL_ARRAY_BUFFER, 18 * (n - i) * sizeof(GLfloat),
308                     vertex, GL_STATIC_DRAW);
309        glVertexAttribPointer(attr_pos, 3, GL_FLOAT, GL_FALSE, 0, 0);
310
311        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]);
312        glBufferData(GL_ARRAY_BUFFER, 12 * (n - i) * sizeof(GLfloat),
313                     texture, GL_STATIC_DRAW);
314        glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, 0);
315#endif
316
317        /* Draw arrays */
318        glDrawArrays(GL_TRIANGLES, 0, (n - i) * 6);
319
320#if defined HAVE_GL_2X
321        glBindVertexArray(0);
322#endif
323#if !defined __CELLOS_LV2__ // Use cgGLEnableClientState etc.
324        glDisableVertexAttribArray(attr_pos);
325        glDisableVertexAttribArray(attr_tex);
326#endif
327
328        free(vertex);
329        free(texture);
330    }
331
332    free(data->tiles);
333    data->tiles = 0;
334    data->ntiles = 0;
335}
336
337} /* namespace lol */
338
Note: See TracBrowser for help on using the repository browser.