source: trunk/src/scene.cpp @ 650

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

Fix shader crap syntax, caused by space-like UTF-8 characters.

  • Property svn:keywords set to Id
File size: 7.0 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 <cstdio>
17#include <cmath>
18
19#ifdef WIN32
20#   define WIN32_LEAN_AND_MEAN
21#   include <windows.h>
22#endif
23#if defined __APPLE__ && defined __MACH__
24#   include <OpenGL/gl.h>
25#else
26#   define GL_GLEXT_PROTOTYPES
27#   include <GL/gl.h>
28#endif
29
30#include "core.h"
31
32#define ATTRIB_POSITION 42 /* arbitrary id */
33#define SHADER_CRAP 0
34
35struct Tile
36{
37    uint32_t prio, code;
38    int x, y, z, o;
39};
40
41/*
42 * Scene implementation class
43 */
44
45class SceneData
46{
47    friend class Scene;
48
49private:
50    static int Compare(void const *p1, void const *p2)
51    {
52        Tile const *t1 = (Tile const *)p1;
53        Tile const *t2 = (Tile const *)p2;
54
55        return t2->prio - t1->prio;
56    }
57
58    Tile *tiles;
59    int ntiles;
60    float angle;
61
62#if SHADER_CRAP
63    GLuint prog, sh1, sh2;
64    GLint uni_mvp, uni_color;
65#endif
66    GLuint *bufs;
67    int nbufs;
68
69    static Scene *scene;
70};
71
72Scene *SceneData::scene = NULL;
73
74#if SHADER_CRAP
75static char const *vertexshader =
76    "attribute vec4 position;\n"
77    "uniform mat4 mvp;\n"
78    "\n"
79    "void main()\n"
80    "{\n"
81    "    gl_Position = mvp * position;\n"
82    "}\n";
83
84static char const *fragmentshader =
85    "uniform /*lowp*/ vec4 color;\n"
86    "\n"
87    "void main()\n"
88    "{\n"
89    "    gl_FragColor = color;\n"
90    "}\n";
91#endif
92
93/*
94 * Public Scene class
95 */
96
97Scene::Scene(float angle)
98  : data(new SceneData())
99{
100    data->tiles = 0;
101    data->ntiles = 0;
102    data->angle = angle;
103
104    data->bufs = 0;
105    data->nbufs = 0;
106
107#if SHADER_CRAP
108    data->sh1 = glCreateShader(GL_VERTEX_SHADER);
109    glShaderSource(data->sh1, 1, &vertexshader, NULL);
110    glCompileShader(data->sh1);
111
112    char buf[4096];
113    GLsizei dummy;
114    glGetShaderInfoLog(data->sh1, 4096, &dummy, buf);
115    fprintf(stderr, "sh1 %i: %s", data->sh1, buf);
116
117    data->sh2 = glCreateShader(GL_FRAGMENT_SHADER);
118    glShaderSource(data->sh2, 1, &fragmentshader, NULL);
119    glCompileShader(data->sh2);
120
121    glGetShaderInfoLog(data->sh2, 4096, &dummy, buf);
122    fprintf(stderr, "sh2 %i: %s", data->sh2, buf);
123
124    data->prog = glCreateProgram();
125    glAttachShader(data->prog, data->sh1);
126    glAttachShader(data->prog, data->sh2);
127
128    glBindAttribLocation(data->prog, ATTRIB_POSITION, "position");
129    glLinkProgram(data->prog);
130    glValidateProgram(data->prog);
131
132    data->uni_mvp = glGetUniformLocation(data->prog, "mvp");
133    data->uni_color = glGetUniformLocation(data->prog, "color");
134#endif
135}
136
137Scene::~Scene()
138{
139    /* FIXME: this must be done while the GL context is still active.
140     * Change the architecture to make sure of that. */
141#if SHADER_CRAP
142    glDetachShader(data->prog, data->sh1);
143    glDetachShader(data->prog, data->sh2);
144    glDeleteShader(data->sh1);
145    glDeleteShader(data->sh2);
146    glDeleteProgram(data->prog);
147#endif
148    glDeleteBuffers(data->nbufs, data->bufs);
149    delete data;
150}
151
152Scene *Scene::GetDefault()
153{
154    if (!SceneData::scene)
155        SceneData::scene = new Scene(0.0f);
156    return SceneData::scene;
157}
158
159void Scene::Reset()
160{
161    if (SceneData::scene)
162        delete SceneData::scene;
163    SceneData::scene = NULL;
164}
165
166void Scene::AddTile(uint32_t code, int x, int y, int z, int o)
167{
168    if ((data->ntiles % 1024) == 0)
169        data->tiles = (Tile *)realloc(data->tiles,
170                                      (data->ntiles + 1024) * sizeof(Tile));
171    /* FIXME: this sorting only works for a 45-degree camera */
172    data->tiles[data->ntiles].prio = -y - 2 * 32 * z + (o ? 0 : 32);
173    data->tiles[data->ntiles].code = code;
174    data->tiles[data->ntiles].x = x;
175    data->tiles[data->ntiles].y = y;
176    data->tiles[data->ntiles].z = z;
177    data->tiles[data->ntiles].o = o;
178    data->ntiles++;
179}
180
181void Scene::Render() // XXX: rename to Blit()
182{
183#if 0
184    // Randomise, then sort.
185    for (int i = 0; i < data->ntiles; i++)
186    {
187        Tile tmp = data->tiles[i];
188        int j = rand() % data->ntiles;
189        data->tiles[i] = data->tiles[j];
190        data->tiles[j] = tmp;
191    }
192#endif
193    qsort(data->tiles, data->ntiles, sizeof(Tile), SceneData::Compare);
194
195    // XXX: debug stuff
196    glPushMatrix();
197    static float f = 0.0f;
198    f += 0.05f;
199    glTranslatef(320.0f, 240.0f, 0.0f);
200    glRotatef(-data->angle, 1.0f, 0.0f, 0.0f);
201#if 0
202    glRotatef(3.0f * sinf(f), 1.0f, 0.0f, 0.0f);
203    glRotatef(8.0f * cosf(f), 0.0f, 0.0f, 1.0f);
204#endif
205    glTranslatef(-320.0f, -240.0f, 0.0f);
206    // XXX: end of debug stuff
207
208    for (int buf = 0, i = 0, n; i < data->ntiles; i = n, buf += 2)
209    {
210        /* Generate new vertex / texture coord buffers if necessary */
211        if (buf + 2 > data->nbufs)
212        {
213            data->bufs = (GLuint *)realloc(data->bufs, (buf + 2) * sizeof(GLuint));
214            glGenBuffers(buf + 2 - data->nbufs, data->bufs + data->nbufs);
215            data->nbufs = buf + 2;
216        }
217
218        /* Count how many quads will be needed */
219        for (n = i + 1; n < data->ntiles; n++)
220            if (data->tiles[i].code >> 16 != data->tiles[n].code >> 16)
221                break;
222
223        /* Create a vertex array object */
224        float *vertex = (float *)malloc(6 * 3 * (n - i) * sizeof(float));
225        float *texture = (float *)malloc(6 * 2 * (n - i) * sizeof(float));
226
227        for (int j = i; j < n; j++)
228        {
229            Tiler::BlitTile(data->tiles[j].code, data->tiles[j].x,
230                            data->tiles[j].y, data->tiles[j].z, data->tiles[j].o,
231                            vertex + 18 * (j - i), texture + 12 * (j - i));
232        }
233
234        glEnableClientState(GL_VERTEX_ARRAY);
235        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
236#if SHADER_CRAP
237        glUseProgram(data->prog);
238        float4x4 mvp = float4x4::identity();
239        mvp = mvp - mvp;
240        glUniformMatrix4fv(data->uni_mvp, 1, GL_FALSE, (GLfloat *)&mvp[0][0]);
241        glUniform4f(data->uni_color, 1.0f, 0.0f, 1.0f, 1.0f);
242#endif
243
244        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]);
245        glBufferData(GL_ARRAY_BUFFER, 6 * 3 * (n - i) * sizeof(float),
246                     vertex, GL_DYNAMIC_DRAW);
247        glVertexPointer(3, GL_FLOAT, 0, NULL);
248#if SHADER_CRAP
249        glVertexAttribPointer(ATTRIB_POSITION, (n - i) * 6, GL_FLOAT, false, 0, vertex);
250        glEnableVertexAttribArray(ATTRIB_POSITION);
251#endif
252
253        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]);
254        glBufferData(GL_ARRAY_BUFFER, 6 * 2 * (n - i) * sizeof(float),
255                     texture, GL_DYNAMIC_DRAW);
256        glTexCoordPointer(2, GL_FLOAT, 0, NULL);
257
258        Tiler::Bind(data->tiles[i].code);
259        glDrawArrays(GL_TRIANGLES, 0, (n - i) * 6);
260
261        glDisableClientState(GL_VERTEX_ARRAY);
262        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
263
264        free(vertex);
265        free(texture);
266    }
267
268    glPopMatrix();
269
270    free(data->tiles);
271    data->tiles = 0;
272    data->ntiles = 0;
273}
274
Note: See TracBrowser for help on using the repository browser.