source: trunk/src/scene.cpp @ 1198

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

core: allow each blitted tile to be stretched differently.

  • Property svn:keywords set to Id
File size: 15.0 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
38static Shader *stdshader = NULL;
39
40/*
41 * Scene implementation class
42 */
43
44class SceneData
45{
46    friend class Scene;
47
48private:
49    static int Compare(void const *p1, void const *p2)
50    {
51        Tile const *t1 = (Tile const *)p1;
52        Tile const *t2 = (Tile const *)p2;
53
54        return t2->prio - t1->prio;
55    }
56
57    mat4 model_matrix;
58
59    Tile *tiles;
60    int ntiles;
61    float angle;
62
63#if defined _XBOX
64#   define STR0(x) #x
65#   define STR(x) STR0(x)
66#   pragma message(__FILE__ "(" STR(__LINE__) "): warning: Scene not implemented")
67#   undef STR
68#   undef STR0
69#else
70#if defined HAVE_GL_2X && !defined __APPLE__
71    GLuint vao;
72#endif
73    GLuint *bufs;
74    int nbufs;
75#endif
76
77    static Scene *scene;
78};
79
80Scene *SceneData::scene = NULL;
81
82/*
83 * Public Scene class
84 */
85
86Scene::Scene(float angle)
87  : data(new SceneData())
88{
89    data->tiles = 0;
90    data->ntiles = 0;
91    data->angle = angle;
92
93#if defined _XBOX
94#   define STR0(x) #x
95#   define STR(x) STR0(x)
96#   pragma message(__FILE__ "(" STR(__LINE__) "): warning: Scene::Scene() not implemented")
97#   undef STR
98#   undef STR0
99#else
100    data->bufs = 0;
101    data->nbufs = 0;
102#endif
103
104#if defined HAVE_GL_2X && !defined __APPLE__
105    glGenVertexArrays(1, &data->vao);
106#endif
107}
108
109Scene::~Scene()
110{
111#if defined _XBOX
112#   define STR0(x) #x
113#   define STR(x) STR0(x)
114#   pragma message(__FILE__ "(" STR(__LINE__) "): warning: Scene::~Scene() not implemented")
115#   undef STR
116#   undef STR0
117#else
118    /* FIXME: this must be done while the GL context is still active.
119     * Change the code architecture to make sure of that. */
120    /* XXX: The test is necessary because of a crash with PSGL. */
121    if (data->nbufs > 0)
122        glDeleteBuffers(data->nbufs, data->bufs);
123#if defined HAVE_GL_2X && !defined __APPLE__
124    glDeleteVertexArrays(1, &data->vao);
125#endif
126    free(data->bufs);
127#endif
128    delete data;
129}
130
131Scene *Scene::GetDefault()
132{
133    if (!SceneData::scene)
134        SceneData::scene = new Scene(0.0f);
135    return SceneData::scene;
136}
137
138void Scene::Reset()
139{
140    if (SceneData::scene)
141        delete SceneData::scene;
142    SceneData::scene = NULL;
143}
144
145void Scene::AddTile(TileSet *tileset, int id, vec3 pos, int o, vec2 scale)
146{
147#if !defined _XBOX /* No WPOS on Xbox */
148    if ((data->ntiles % 1024) == 0)
149        data->tiles = (Tile *)realloc(data->tiles,
150                                      (data->ntiles + 1024) * sizeof(Tile));
151    /* FIXME: this sorting only works for a 45-degree camera */
152    data->tiles[data->ntiles].prio = -pos.y - 2 * 32 * pos.z + (o ? 0 : 32);
153    data->tiles[data->ntiles].tileset = tileset;
154    data->tiles[data->ntiles].id = id;
155    data->tiles[data->ntiles].pos = pos;
156    data->tiles[data->ntiles].o = o;
157    data->tiles[data->ntiles].scale = scale;
158    data->ntiles++;
159#endif
160}
161
162void Scene::Render() // XXX: rename to Blit()
163{
164#if !defined _XBOX /* No WPOS on Xbox */
165    if (!stdshader)
166    {
167#if !defined _XBOX && !defined __CELLOS_LV2__
168        stdshader = Shader::Create(
169#if !defined HAVE_GLES_2X
170            "#version 130\n"
171#endif
172            "\n"
173#if defined HAVE_GLES_2X
174            "attribute vec3 in_Position;\n"
175            "attribute vec2 in_TexCoord;\n"
176            "varying vec2 pass_TexCoord;\n"
177#else
178            "in vec3 in_Position;\n"
179            "in vec2 in_TexCoord;\n"
180#endif
181            "uniform mat4 proj_matrix;\n"
182            "uniform mat4 view_matrix;\n"
183            "uniform mat4 model_matrix;\n"
184            "\n"
185            "void main()\n"
186            "{\n"
187            "    gl_Position = proj_matrix * view_matrix * model_matrix"
188            "                * vec4(in_Position, 1.0);\n"
189#if defined HAVE_GLES_2X
190            "    pass_TexCoord = in_TexCoord;\n"
191#else
192            "    gl_TexCoord[0] = vec4(in_TexCoord, 0.0, 0.0);\n"
193#endif
194            "}\n",
195
196#if !defined HAVE_GLES_2X
197            "#version 130\n"
198#else
199            "precision mediump float;\n"
200#endif
201            "\n"
202            "uniform sampler2D in_Texture;\n"
203#if defined HAVE_GLES_2X
204            "varying vec2 pass_TexCoord;\n"
205#endif
206            "\n"
207            "void main()\n"
208            "{\n"
209#if defined HAVE_GLES_2X
210            "    vec4 col = texture2D(in_Texture, pass_TexCoord);\n"
211            //"    vec4 col = vec4(0.5, 1.0, 0.0, 0.5);\n"
212            //"    vec4 col = vec4(pass_TexCoord * 4.0, 0.0, 0.25);\n"
213#else
214            "    vec4 col = texture2D(in_Texture, vec2(gl_TexCoord[0]));\n"
215#endif
216#if 0
217            "    float mul = 2.0;\n"
218#if 1
219            "    vec2 d1 = mod(vec2(gl_FragCoord), vec2(2.0, 2.0));\n"
220            "    float t1 = mod(3.0 * d1.x + 2.0 * d1.y, 4.0);\n"
221            "    float dx2 = mod(floor(gl_FragCoord.x * 0.5), 2.0);\n"
222            "    float dy2 = mod(floor(gl_FragCoord.y * 0.5), 2.0);\n"
223            "    float t2 = mod(3.0 * dx2 + 2.0 * dy2, 4.0);\n"
224            "    float dx3 = mod(floor(gl_FragCoord.x * 0.25), 2.0);\n"
225            "    float dy3 = mod(floor(gl_FragCoord.y * 0.25), 2.0);\n"
226            "    float t3 = mod(3.0 * dx3 + 2.0 * dy3, 4.0);\n"
227            "    t1 = (1.0 + 16.0 * t1 + 4.0 * t2 + t3) / 65.0;\n"
228            "    t2 = t1;\n"
229            "    t3 = t1;\n"
230#else
231            "    float rand = sin(gl_FragCoord.x * 1.23456) * 123.456\n"
232            "               + cos(gl_FragCoord.y * 2.34567) * 789.012;\n"
233            "    float t1 = mod(sin(rand) * 17.13043, 1.0);\n"
234            "    float t2 = mod(sin(rand) * 27.13043, 1.0);\n"
235            "    float t3 = mod(sin(rand) * 37.13043, 1.0);\n"
236#endif
237            "    float fracx = fract(col.x * mul);\n"
238            "    float fracy = fract(col.y * mul);\n"
239            "    float fracz = fract(col.z * mul);\n"
240            "    fracx = fracx > t1 ? 1.0 : 0.0;\n"
241            "    fracy = fracy > t2 ? 1.0 : 0.0;\n"
242            "    fracz = fracz > t3 ? 1.0 : 0.0;\n"
243            "    col.x = (floor(col.x * mul) + fracx) / mul;\n"
244            "    col.y = (floor(col.y * mul) + fracy) / mul;\n"
245            "    col.z = (floor(col.z * mul) + fracz) / mul;\n"
246#endif
247            "    gl_FragColor = col;\n"
248            "}\n");
249#else
250        stdshader = Shader::Create(
251            "void main(float4 in_Position : POSITION,"
252            "          float2 in_TexCoord : TEXCOORD0,"
253            "          uniform float4x4 proj_matrix,"
254            "          uniform float4x4 view_matrix,"
255            "          uniform float4x4 model_matrix,"
256            "          out float2 out_TexCoord : TEXCOORD0,"
257            "          out float4 out_Position : POSITION)"
258            "{"
259            "    out_Position = mul(proj_matrix, mul(view_matrix, mul(model_matrix, in_Position)));"
260            "    out_TexCoord = in_TexCoord;"
261            "}",
262
263            "void main(float2 in_TexCoord : TEXCOORD0,"
264            "          float4 in_FragCoord : WPOS,"
265            "          uniform sampler2D tex,"
266            "          out float4 out_FragColor : COLOR)"
267            "{"
268            "    float4 col = tex2D(tex, in_TexCoord);"
269#if 0
270            "    float mul = 2.0;\n"
271            "    float t1, t2, t3;\n"
272#if 1
273            "    float dx1 = frac(in_FragCoord.x * 0.5) * 2.0;\n"
274            "    float dy1 = frac(in_FragCoord.y * 0.5) * 2.0;\n"
275            "    t1 = frac((3.0 * dx1 + 2.0 * dy1) / 4.0) * 4.0;\n"
276            "    float dx2 = frac(floor(in_FragCoord.x * 0.5) * 0.5) * 2.0;\n"
277            "    float dy2 = frac(floor(in_FragCoord.y * 0.5) * 0.5) * 2.0;\n"
278            "    t2 = frac((3.0 * dx2 + 2.0 * dy2) / 4.0) * 4.0;\n"
279            "    float dx3 = frac(floor(in_FragCoord.x * 0.25) * 0.5) * 2.0;\n"
280            "    float dy3 = frac(floor(in_FragCoord.y * 0.25) * 0.5) * 2.0;\n"
281            "    t3 = frac((3.0 * dx3 + 2.0 * dy3) / 4.0) * 4.0;\n"
282            "    t1 = (1.0 + 4.0 * t1 + t2) / 17.0;\n"
283            "    t2 = t1;\n"
284            "    t3 = t1;\n"
285#else
286            "    float rand = sin(in_FragCoord.x * 1.23456) * 123.456\n"
287            "               + cos(in_FragCoord.y * 2.34567) * 789.012;\n"
288            "    t1 = frac(sin(rand) * 17.13043);\n"
289            "    t2 = frac(sin(rand) * 27.13043);\n"
290            "    t3 = frac(sin(rand) * 37.13043);\n"
291#endif
292            "    float fracx = frac(col.x * mul);\n"
293            "    float fracy = frac(col.y * mul);\n"
294            "    float fracz = frac(col.z * mul);\n"
295            "    fracx = fracx > t1 ? 1.0 : 0.0;\n"
296            "    fracy = fracy > t2 ? 1.0 : 0.0;\n"
297            "    fracz = fracz > t3 ? 1.0 : 0.0;\n"
298            "    col.x = (floor(col.x * mul) + fracx) / mul;\n"
299            "    col.y = (floor(col.y * mul) + fracy) / mul;\n"
300            "    col.z = (floor(col.z * mul) + fracz) / mul;\n"
301#endif
302            "    out_FragColor = col;"
303            "}");
304#endif
305    }
306
307#if 0
308    // Randomise, then sort.
309    for (int i = 0; i < data->ntiles; i++)
310    {
311        Tile tmp = data->tiles[i];
312        int j = rand() % data->ntiles;
313        data->tiles[i] = data->tiles[j];
314        data->tiles[j] = tmp;
315    }
316#endif
317    qsort(data->tiles, data->ntiles, sizeof(Tile), SceneData::Compare);
318
319    // XXX: debug stuff
320    data->model_matrix = mat4::translate(320.0f, 240.0f, 0.0f);
321    data->model_matrix *= mat4::rotate(-data->angle, 1.0f, 0.0f, 0.0f);
322#if 0
323    static float f = 0.0f;
324    f += 0.01f;
325    data->model_matrix *= mat4::rotate(6.0f * sinf(f), 1.0f, 0.0f, 0.0f);
326    data->model_matrix *= mat4::rotate(17.0f * cosf(f), 0.0f, 0.0f, 1.0f);
327#endif
328    data->model_matrix *= mat4::translate(-320.0f, -240.0f, 0.0f);
329    // XXX: end of debug stuff
330
331    int uni_mat, uni_tex, attr_pos, attr_tex;
332#if !defined __CELLOS_LV2__
333    attr_pos = stdshader->GetAttribLocation("in_Position");
334    attr_tex = stdshader->GetAttribLocation("in_TexCoord");
335#endif
336
337    stdshader->Bind();
338
339    uni_mat = stdshader->GetUniformLocation("proj_matrix");
340    stdshader->SetUniform(uni_mat, Video::GetProjMatrix());
341    uni_mat = stdshader->GetUniformLocation("view_matrix");
342    stdshader->SetUniform(uni_mat, Video::GetViewMatrix());
343    uni_mat = stdshader->GetUniformLocation("model_matrix");
344    stdshader->SetUniform(uni_mat, data->model_matrix);
345
346#if defined _XBOX
347#   define STR0(x) #x
348#   define STR(x) STR0(x)
349#   pragma message(__FILE__ "(" STR(__LINE__) "): warning: Scene::Render() not implemented")
350#   undef STR
351#   undef STR0
352#elif !defined __CELLOS_LV2__
353    uni_tex = stdshader->GetUniformLocation("in_Texture");
354    glUniform1i(uni_tex, 0);
355#else
356    // WTF? this doesn't exist
357    //uni_tex = stdshader->GetUniformLocation("in_Texture");
358    //cgGLSetParameter1i((CGparameter)(intptr_t)uni_tex, 0);
359#endif
360
361#if defined _XBOX
362#   define STR0(x) #x
363#   define STR(x) STR0(x)
364#   pragma message(__FILE__ "(" STR(__LINE__) "): warning: Scene::Render() not implemented")
365#   undef STR
366#   undef STR0
367#else
368#if !defined HAVE_GLES_2X
369    glEnable(GL_TEXTURE_2D);
370#endif
371    glEnable(GL_DEPTH_TEST);
372    glDepthFunc(GL_LEQUAL);
373#if defined HAVE_GL_2X && !defined __APPLE__
374    glEnable(GL_ALPHA_TEST);
375    glAlphaFunc(GL_GEQUAL, 0.01f);
376#endif
377    glEnable(GL_BLEND);
378    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
379#endif
380
381    for (int buf = 0, i = 0, n; i < data->ntiles; i = n, buf += 2)
382    {
383#if defined _XBOX
384#   define STR0(x) #x
385#   define STR(x) STR0(x)
386#   pragma message(__FILE__ "(" STR(__LINE__) "): warning: Scene::Render() not implemented")
387#   undef STR
388#   undef STR0
389#else
390        /* Generate new vertex / texture coord buffers if necessary */
391        if (buf + 2 > data->nbufs)
392        {
393            data->bufs = (uint32_t *)realloc(data->bufs, (buf + 2) * sizeof(uint32_t));
394            glGenBuffers(buf + 2 - data->nbufs, data->bufs + data->nbufs);
395            data->nbufs = buf + 2;
396        }
397#endif
398
399        /* Count how many quads will be needed */
400        for (n = i + 1; n < data->ntiles; n++)
401            if (data->tiles[i].tileset != data->tiles[n].tileset)
402                break;
403
404        /* Create a vertex array object */
405        float *vertex = (float *)malloc(6 * 3 * (n - i) * sizeof(float));
406        float *texture = (float *)malloc(6 * 2 * (n - i) * sizeof(float));
407
408        for (int j = i; j < n; j++)
409        {
410            data->tiles[i].tileset->BlitTile(data->tiles[j].id,
411                            data->tiles[j].pos, data->tiles[j].o,
412                            data->tiles[j].scale,
413                            vertex + 18 * (j - i), texture + 12 * (j - i));
414        }
415
416        stdshader->Bind();
417
418        /* Bind texture */
419        data->tiles[i].tileset->Bind();
420
421        /* Bind vertex, color and texture coordinate buffers */
422#if defined HAVE_GL_2X && !defined __APPLE__
423        glBindVertexArray(data->vao);
424#endif
425#if defined _XBOX
426#   define STR0(x) #x
427#   define STR(x) STR0(x)
428#   pragma message(__FILE__ "(" STR(__LINE__) "): warning: Scene::Render() not implemented")
429#   undef STR
430#   undef STR0
431#else
432#if !defined __CELLOS_LV2__ // Use cgGLEnableClientState etc.
433        glEnableVertexAttribArray(attr_pos);
434        glEnableVertexAttribArray(attr_tex);
435
436        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]);
437        glBufferData(GL_ARRAY_BUFFER, 18 * (n - i) * sizeof(GLfloat),
438                     vertex, GL_STATIC_DRAW);
439        glVertexAttribPointer(attr_pos, 3, GL_FLOAT, GL_FALSE, 0, 0);
440
441        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]);
442        glBufferData(GL_ARRAY_BUFFER, 12 * (n - i) * sizeof(GLfloat),
443                     texture, GL_STATIC_DRAW);
444        glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, 0);
445#else
446        glEnableClientState(GL_VERTEX_ARRAY);
447        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
448
449        glVertexPointer(3, GL_FLOAT, 0, vertex);
450        glTexCoordPointer(2, GL_FLOAT, 0, texture);
451#endif
452
453        /* Draw arrays */
454        glDrawArrays(GL_TRIANGLES, 0, (n - i) * 6);
455
456#if defined HAVE_GL_2X && !defined __APPLE__
457        glBindVertexArray(0);
458#endif
459#if !defined __CELLOS_LV2__ // Use cgGLEnableClientState etc.
460        glDisableVertexAttribArray(attr_pos);
461        glDisableVertexAttribArray(attr_tex);
462#else
463        glDisableClientState(GL_VERTEX_ARRAY);
464        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
465#endif
466#endif
467
468        free(vertex);
469        free(texture);
470    }
471
472    free(data->tiles);
473    data->tiles = 0;
474    data->ntiles = 0;
475
476#if defined _XBOX
477#   define STR0(x) #x
478#   define STR(x) STR0(x)
479#   pragma message(__FILE__ "(" STR(__LINE__) "): warning: Scene::Render() not implemented")
480#   undef STR
481#   undef STR0
482#else
483#if !defined HAVE_GLES_2X
484    glDisable(GL_TEXTURE_2D);
485#endif
486    glDisable(GL_DEPTH_TEST);
487#if defined HAVE_GL_2X && !defined __APPLE__
488    glDisable(GL_ALPHA_TEST);
489#endif
490    glDisable(GL_BLEND);
491#endif
492#endif /* _XBOX */
493}
494
495} /* namespace lol */
496
Note: See TracBrowser for help on using the repository browser.