source: trunk/src/scene.cpp @ 1846

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

gpu: get rid of the inline 2D shader and create "tile.lolfx".

  • Property svn:keywords set to Id
File size: 6.6 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
25extern char const *lolfx_tile;
26
27namespace lol
28{
29
30struct Tile
31{
32    TileSet *tileset;
33    uint32_t prio;
34    vec3 pos;
35    vec2 scale;
36    int id, o;
37};
38
39/*
40 * Scene implementation class
41 */
42
43class SceneData
44{
45    friend class Scene;
46
47private:
48    static int Compare(void const *p1, void const *p2)
49    {
50        Tile const *t1 = (Tile const *)p1;
51        Tile const *t2 = (Tile const *)p2;
52
53        return t2->prio - t1->prio;
54    }
55
56    mat4 m_model_matrix;
57    mat4 m_view_matrix;
58    mat4 m_proj_matrix;
59
60    Array<Tile> tiles;
61
62    Shader *m_shader;
63    VertexDeclaration *m_vdecl;
64    Array<VertexBuffer *> bufs;
65
66    static Scene *scene;
67};
68
69Scene *SceneData::scene = NULL;
70
71/*
72 * Public Scene class
73 */
74
75Scene::Scene()
76  : data(new SceneData())
77{
78    data->m_model_matrix = mat4(1.f);
79    data->m_view_matrix = mat4(1.f);
80    data->m_proj_matrix = mat4::ortho(0, Video::GetSize().x,
81                                      0, Video::GetSize().y, -1000.f, 1000.f);
82
83    data->m_shader = 0;
84    data->m_vdecl = new VertexDeclaration(VertexStream<vec3>(VertexUsage::Position),
85                                          VertexStream<vec2>(VertexUsage::TexCoord));
86}
87
88Scene::~Scene()
89{
90    /* FIXME: this must be done while the GL context is still active.
91     * Change the code architecture to make sure of that. */
92    /* FIXME: also, make sure we do not add code to Reset() that will
93     * reallocate stuff */
94    Reset();
95
96    delete data->m_vdecl;
97    delete data;
98}
99
100Scene *Scene::GetDefault()
101{
102    if (!SceneData::scene)
103        SceneData::scene = new Scene();
104    return SceneData::scene;
105}
106
107void Scene::Reset()
108{
109    for (int i = 0; i < data->bufs.Count(); i++)
110        delete data->bufs[i];
111    data->bufs.Empty();
112}
113
114void Scene::SetViewMatrix(mat4 const &m)
115{
116    data->m_view_matrix = m;
117}
118
119void Scene::SetProjMatrix(mat4 const &m)
120{
121    data->m_proj_matrix = m;
122}
123
124mat4 const &Scene::GetViewMatrix(void)
125{
126    return data->m_view_matrix;
127}
128
129mat4 const &Scene::GetProjMatrix(void)
130{
131    return data->m_proj_matrix;
132}
133
134void Scene::AddTile(TileSet *tileset, int id, vec3 pos, int o, vec2 scale)
135{
136    Tile t;
137    /* FIXME: this sorting only works for a 45-degree camera */
138    t.prio = -pos.y - 2 * 32 * pos.z + (o ? 0 : 32);
139    t.tileset = tileset;
140    t.id = id;
141    t.pos = pos;
142    t.o = o;
143    t.scale = scale;
144
145    data->tiles.Push(t);
146}
147
148void Scene::Render() // XXX: rename to Blit()
149{
150    /* Early exit if nothing needs to be rendered */
151    if (!data->tiles.Count())
152        return;
153
154    if (!data->m_shader)
155        data->m_shader = Shader::Create(lolfx_tile);
156
157#if 0
158    // Randomise, then sort.
159    for (int i = 0; i < data->tiles.Count(); i++)
160    {
161        Tile tmp = data->tiles[i];
162        int j = rand() % data->tiles.Count();
163        data->tiles[i] = data->tiles[j];
164        data->tiles[j] = tmp;
165    }
166#endif
167    qsort(&data->tiles[0], data->tiles.Count(),
168          sizeof(Tile), SceneData::Compare);
169
170    // XXX: debug stuff
171    data->m_model_matrix = mat4::translate(320.0f, 240.0f, 0.0f);
172#if 0
173    static float f = 0.0f;
174    f += 0.01f;
175    data->m_model_matrix *= mat4::rotate(6.0f * sinf(f), 1.0f, 0.0f, 0.0f);
176    data->m_model_matrix *= mat4::rotate(17.0f * cosf(f), 0.0f, 0.0f, 1.0f);
177#endif
178    data->m_model_matrix *= mat4::translate(-320.0f, -240.0f, 0.0f);
179    // XXX: end of debug stuff
180
181    ShaderUniform uni_mat, uni_tex;
182    ShaderAttrib attr_pos, attr_tex;
183    attr_pos = data->m_shader->GetAttribLocation("in_Position", VertexUsage::Position, 0);
184    attr_tex = data->m_shader->GetAttribLocation("in_TexCoord", VertexUsage::TexCoord, 0);
185
186    data->m_shader->Bind();
187
188    uni_mat = data->m_shader->GetUniformLocation("proj_matrix");
189    data->m_shader->SetUniform(uni_mat, data->m_proj_matrix);
190    uni_mat = data->m_shader->GetUniformLocation("view_matrix");
191    data->m_shader->SetUniform(uni_mat, data->m_view_matrix);
192    uni_mat = data->m_shader->GetUniformLocation("model_matrix");
193    data->m_shader->SetUniform(uni_mat, data->m_model_matrix);
194
195#if defined USE_D3D9 || defined _XBOX
196#else
197    uni_tex = data->m_shader->GetUniformLocation("in_Texture");
198    data->m_shader->SetUniform(uni_tex, 0);
199
200#if !defined HAVE_GLES_2X
201    glEnable(GL_TEXTURE_2D);
202#endif
203    glEnable(GL_DEPTH_TEST);
204    glDepthFunc(GL_LEQUAL);
205#if defined HAVE_GL_2X && !defined __APPLE__
206    glEnable(GL_ALPHA_TEST);
207    glAlphaFunc(GL_GEQUAL, 0.01f);
208#endif
209    glEnable(GL_BLEND);
210    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
211#endif
212
213    for (int buf = 0, i = 0, n; i < data->tiles.Count(); i = n, buf += 2)
214    {
215        /* Count how many quads will be needed */
216        for (n = i + 1; n < data->tiles.Count(); n++)
217            if (data->tiles[i].tileset != data->tiles[n].tileset)
218                break;
219
220        /* Create a vertex array object */
221        VertexBuffer *vb1 = new VertexBuffer(6 * 3 * (n - i) * sizeof(float));
222        float *vertex = (float *)vb1->Lock(0, 0);
223        VertexBuffer *vb2 = new VertexBuffer(6 * 2 * (n - i) * sizeof(float));
224        float *texture = (float *)vb2->Lock(0, 0);
225
226        data->bufs.Push(vb1);
227        data->bufs.Push(vb2);
228
229        for (int j = i; j < n; j++)
230        {
231            data->tiles[i].tileset->BlitTile(data->tiles[j].id,
232                            data->tiles[j].pos, data->tiles[j].o,
233                            data->tiles[j].scale,
234                            vertex + 18 * (j - i), texture + 12 * (j - i));
235        }
236
237        vb1->Unlock();
238        vb2->Unlock();
239
240        /* Bind texture */
241        data->tiles[i].tileset->Bind();
242
243        /* Bind vertex and texture coordinate buffers */
244        data->m_vdecl->Bind();
245        data->m_vdecl->SetStream(vb1, attr_pos);
246        data->m_vdecl->SetStream(vb2, attr_tex);
247
248        /* Draw arrays */
249        data->m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, (n - i) * 2);
250        data->m_vdecl->Unbind();
251        data->tiles[i].tileset->Unbind();
252    }
253
254    data->tiles.Empty();
255
256    data->m_shader->Unbind();
257
258#if defined USE_D3D9 || defined _XBOX
259    /* TODO */
260#else
261#if !defined HAVE_GLES_2X
262    glDisable(GL_TEXTURE_2D);
263#endif
264    glDisable(GL_DEPTH_TEST);
265#if defined HAVE_GL_2X && !defined __APPLE__
266    glDisable(GL_ALPHA_TEST);
267#endif
268    glDisable(GL_BLEND);
269#endif
270}
271
272} /* namespace lol */
273
Note: See TracBrowser for help on using the repository browser.