source: trunk/src/scene.cpp @ 1309

Last change on this file since 1309 was 1241, checked in by sam, 8 years ago

gpu: fix a great lot of Direct3D problems, spotted using PIX.

  • Property svn:keywords set to Id
File size: 12.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#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    VertexDeclaration *m_vdecl;
64    VertexBuffer **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    data->m_vdecl = new VertexDeclaration(VertexStream<vec3>(VertexUsage::Position),
87                                          VertexStream<vec2>(VertexUsage::TexCoord));
88}
89
90Scene::~Scene()
91{
92    /* FIXME: this must be done while the GL context is still active.
93     * Change the code architecture to make sure of that. */
94    /* XXX: The test is necessary because of a crash with PSGL. */
95    for (int i = 0; i < data->nbufs; i++)
96        delete data->bufs[i];
97    free(data->bufs);
98
99    delete data->m_vdecl;
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, vec3 pos, int o, vec2 scale)
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 = -pos.y - 2 * 32 * pos.z + (o ? 0 : 32);
124    data->tiles[data->ntiles].tileset = tileset;
125    data->tiles[data->ntiles].id = id;
126    data->tiles[data->ntiles].pos = pos;
127    data->tiles[data->ntiles].o = o;
128    data->tiles[data->ntiles].scale = scale;
129    data->ntiles++;
130}
131
132void Scene::Render() // XXX: rename to Blit()
133{
134    if (!stdshader)
135    {
136#if !defined _XBOX && !defined __CELLOS_LV2__ && !defined USE_D3D9
137        stdshader = Shader::Create(
138#   if !defined HAVE_GLES_2X
139            "#version 130\n"
140#   endif
141            "\n"
142#   if defined HAVE_GLES_2X
143            "attribute vec3 in_Position;\n"
144            "attribute vec2 in_TexCoord;\n"
145            "varying vec2 pass_TexCoord;\n"
146#   else
147            "in vec3 in_Position;\n"
148            "in vec2 in_TexCoord;\n"
149#   endif
150            "uniform mat4 proj_matrix;\n"
151            "uniform mat4 view_matrix;\n"
152            "uniform mat4 model_matrix;\n"
153            "\n"
154            "void main()\n"
155            "{\n"
156            "    gl_Position = proj_matrix * view_matrix * model_matrix"
157            "                * vec4(in_Position, 1.0);\n"
158#   if defined HAVE_GLES_2X
159            "    pass_TexCoord = in_TexCoord;\n"
160#   else
161            "    gl_TexCoord[0] = vec4(in_TexCoord, 0.0, 0.0);\n"
162#   endif
163            "}\n",
164
165#   if !defined HAVE_GLES_2X
166            "#version 130\n"
167#   else
168            "precision mediump float;\n"
169#   endif
170            "\n"
171            "uniform sampler2D in_Texture;\n"
172#   if defined HAVE_GLES_2X
173            "varying vec2 pass_TexCoord;\n"
174#   endif
175            "\n"
176            "void main()\n"
177            "{\n"
178#   if defined HAVE_GLES_2X
179            "    vec4 col = texture2D(in_Texture, pass_TexCoord);\n"
180            //"    vec4 col = vec4(0.5, 1.0, 0.0, 0.5);\n"
181            //"    vec4 col = vec4(pass_TexCoord * 4.0, 0.0, 0.25);\n"
182#   else
183            "    vec4 col = texture2D(in_Texture, vec2(gl_TexCoord[0]));\n"
184#   endif
185#   if 0
186            "    float mul = 2.0;\n"
187#       if 1
188            "    vec2 d1 = mod(vec2(gl_FragCoord), vec2(2.0, 2.0));\n"
189            "    float t1 = mod(3.0 * d1.x + 2.0 * d1.y, 4.0);\n"
190            "    float dx2 = mod(floor(gl_FragCoord.x * 0.5), 2.0);\n"
191            "    float dy2 = mod(floor(gl_FragCoord.y * 0.5), 2.0);\n"
192            "    float t2 = mod(3.0 * dx2 + 2.0 * dy2, 4.0);\n"
193            "    float dx3 = mod(floor(gl_FragCoord.x * 0.25), 2.0);\n"
194            "    float dy3 = mod(floor(gl_FragCoord.y * 0.25), 2.0);\n"
195            "    float t3 = mod(3.0 * dx3 + 2.0 * dy3, 4.0);\n"
196            "    t1 = (1.0 + 16.0 * t1 + 4.0 * t2 + t3) / 65.0;\n"
197            "    t2 = t1;\n"
198            "    t3 = t1;\n"
199#       else
200            "    float rand = sin(gl_FragCoord.x * 1.23456) * 123.456\n"
201            "               + cos(gl_FragCoord.y * 2.34567) * 789.012;\n"
202            "    float t1 = mod(sin(rand) * 17.13043, 1.0);\n"
203            "    float t2 = mod(sin(rand) * 27.13043, 1.0);\n"
204            "    float t3 = mod(sin(rand) * 37.13043, 1.0);\n"
205#       endif
206            "    float fracx = fract(col.x * mul);\n"
207            "    float fracy = fract(col.y * mul);\n"
208            "    float fracz = fract(col.z * mul);\n"
209            "    fracx = fracx > t1 ? 1.0 : 0.0;\n"
210            "    fracy = fracy > t2 ? 1.0 : 0.0;\n"
211            "    fracz = fracz > t3 ? 1.0 : 0.0;\n"
212            "    col.x = (floor(col.x * mul) + fracx) / mul;\n"
213            "    col.y = (floor(col.y * mul) + fracy) / mul;\n"
214            "    col.z = (floor(col.z * mul) + fracz) / mul;\n"
215#   endif
216            "    gl_FragColor = col;\n"
217            "}\n");
218#else
219        stdshader = Shader::Create(
220            "void main(float4 in_Position : POSITION,"
221            "          float2 in_TexCoord : TEXCOORD0,"
222            "          uniform float4x4 proj_matrix,"
223            "          uniform float4x4 view_matrix,"
224            "          uniform float4x4 model_matrix,"
225            "          out float2 out_TexCoord : TEXCOORD0,"
226            "          out float4 out_Position : POSITION)"
227            "{"
228            "    out_Position = mul(proj_matrix, mul(view_matrix, mul(model_matrix, in_Position)));"
229            "    out_TexCoord = in_TexCoord;"
230            "}",
231
232            "void main(float2 in_TexCoord : TEXCOORD0,"
233#   if 0
234            "          float4 in_FragCoord : WPOS,"
235#   endif
236            "          uniform sampler2D tex,"
237            "          out float4 out_FragColor : COLOR)"
238            "{"
239            "    float4 col = tex2D(tex, in_TexCoord);"
240#   if 0
241            "    float mul = 2.0;\n"
242            "    float t1, t2, t3;\n"
243#       if 1
244            "    float dx1 = frac(in_FragCoord.x * 0.5) * 2.0;\n"
245            "    float dy1 = frac(in_FragCoord.y * 0.5) * 2.0;\n"
246            "    t1 = frac((3.0 * dx1 + 2.0 * dy1) / 4.0) * 4.0;\n"
247            "    float dx2 = frac(floor(in_FragCoord.x * 0.5) * 0.5) * 2.0;\n"
248            "    float dy2 = frac(floor(in_FragCoord.y * 0.5) * 0.5) * 2.0;\n"
249            "    t2 = frac((3.0 * dx2 + 2.0 * dy2) / 4.0) * 4.0;\n"
250            "    float dx3 = frac(floor(in_FragCoord.x * 0.25) * 0.5) * 2.0;\n"
251            "    float dy3 = frac(floor(in_FragCoord.y * 0.25) * 0.5) * 2.0;\n"
252            "    t3 = frac((3.0 * dx3 + 2.0 * dy3) / 4.0) * 4.0;\n"
253            "    t1 = (1.0 + 4.0 * t1 + t2) / 17.0;\n"
254            "    t2 = t1;\n"
255            "    t3 = t1;\n"
256#       else
257            "    float rand = sin(in_FragCoord.x * 1.23456) * 123.456\n"
258            "               + cos(in_FragCoord.y * 2.34567) * 789.012;\n"
259            "    t1 = frac(sin(rand) * 17.13043);\n"
260            "    t2 = frac(sin(rand) * 27.13043);\n"
261            "    t3 = frac(sin(rand) * 37.13043);\n"
262#       endif
263            "    float fracx = frac(col.x * mul);\n"
264            "    float fracy = frac(col.y * mul);\n"
265            "    float fracz = frac(col.z * mul);\n"
266            "    fracx = fracx > t1 ? 1.0 : 0.0;\n"
267            "    fracy = fracy > t2 ? 1.0 : 0.0;\n"
268            "    fracz = fracz > t3 ? 1.0 : 0.0;\n"
269            "    col.x = (floor(col.x * mul) + fracx) / mul;\n"
270            "    col.y = (floor(col.y * mul) + fracy) / mul;\n"
271            "    col.z = (floor(col.z * mul) + fracz) / mul;\n"
272#   endif
273            "    out_FragColor = col;"
274            "}");
275#endif
276    }
277
278#if 0
279    // Randomise, then sort.
280    for (int i = 0; i < data->ntiles; i++)
281    {
282        Tile tmp = data->tiles[i];
283        int j = rand() % data->ntiles;
284        data->tiles[i] = data->tiles[j];
285        data->tiles[j] = tmp;
286    }
287#endif
288    qsort(data->tiles, data->ntiles, sizeof(Tile), SceneData::Compare);
289
290    // XXX: debug stuff
291    data->model_matrix = mat4::translate(320.0f, 240.0f, 0.0f);
292    data->model_matrix *= mat4::rotate(-data->angle, 1.0f, 0.0f, 0.0f);
293#if 0
294    static float f = 0.0f;
295    f += 0.01f;
296    data->model_matrix *= mat4::rotate(6.0f * sinf(f), 1.0f, 0.0f, 0.0f);
297    data->model_matrix *= mat4::rotate(17.0f * cosf(f), 0.0f, 0.0f, 1.0f);
298#endif
299    data->model_matrix *= mat4::translate(-320.0f, -240.0f, 0.0f);
300    // XXX: end of debug stuff
301
302    ShaderUniform uni_mat, uni_tex;
303    ShaderAttrib attr_pos, attr_tex;
304    attr_pos = stdshader->GetAttribLocation("in_Position", VertexUsage::Position, 0);
305    attr_tex = stdshader->GetAttribLocation("in_TexCoord", VertexUsage::TexCoord, 0);
306
307    stdshader->Bind();
308
309    uni_mat = stdshader->GetUniformLocation("proj_matrix");
310    stdshader->SetUniform(uni_mat, Video::GetProjMatrix());
311    uni_mat = stdshader->GetUniformLocation("view_matrix");
312    stdshader->SetUniform(uni_mat, Video::GetViewMatrix());
313    uni_mat = stdshader->GetUniformLocation("model_matrix");
314    stdshader->SetUniform(uni_mat, data->model_matrix);
315
316#if defined USE_D3D9 || defined _XBOX
317#else
318    uni_tex = stdshader->GetUniformLocation("in_Texture");
319    stdshader->SetUniform(uni_tex, 0);
320
321#if !defined HAVE_GLES_2X
322    glEnable(GL_TEXTURE_2D);
323#endif
324    glEnable(GL_DEPTH_TEST);
325    glDepthFunc(GL_LEQUAL);
326#if defined HAVE_GL_2X && !defined __APPLE__
327    glEnable(GL_ALPHA_TEST);
328    glAlphaFunc(GL_GEQUAL, 0.01f);
329#endif
330    glEnable(GL_BLEND);
331    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
332#endif
333
334    for (int buf = 0, i = 0, n; i < data->ntiles; i = n, buf += 2)
335    {
336        /* Generate new vertex / texture coord buffers if necessary */
337        if (buf + 2 > data->nbufs)
338        {
339            data->bufs = (VertexBuffer **)realloc(data->bufs, (buf + 2) * sizeof(VertexBuffer *));
340            data->nbufs = buf + 2;
341        }
342        else
343        {
344            delete data->bufs[buf];
345            delete data->bufs[buf + 1];
346        }
347
348        /* Count how many quads will be needed */
349        for (n = i + 1; n < data->ntiles; n++)
350            if (data->tiles[i].tileset != data->tiles[n].tileset)
351                break;
352
353        /* Create a vertex array object */
354        data->bufs[buf] = new VertexBuffer(6 * 3 * (n - i) * sizeof(float));
355        float *vertex = (float *)data->bufs[buf]->Lock(0, 0);
356        data->bufs[buf + 1] = new VertexBuffer(6 * 2 * (n - i) * sizeof(float));
357        float *texture = (float *)data->bufs[buf + 1]->Lock(0, 0);
358
359        for (int j = i; j < n; j++)
360        {
361            data->tiles[i].tileset->BlitTile(data->tiles[j].id,
362                            data->tiles[j].pos, data->tiles[j].o,
363                            data->tiles[j].scale,
364                            vertex + 18 * (j - i), texture + 12 * (j - i));
365        }
366
367        data->bufs[buf]->Unlock();
368        data->bufs[buf + 1]->Unlock();
369
370        /* Bind texture */
371        data->tiles[i].tileset->Bind();
372
373        /* Bind vertex and texture coordinate buffers */
374        data->m_vdecl->Bind();
375        data->m_vdecl->SetStream(data->bufs[buf], attr_pos);
376        data->m_vdecl->SetStream(data->bufs[buf + 1], attr_tex);
377
378        /* Draw arrays */
379        data->m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, (n - i) * 2);
380        data->m_vdecl->Unbind();
381        data->tiles[i].tileset->Unbind();
382    }
383
384    free(data->tiles);
385    data->tiles = 0;
386    data->ntiles = 0;
387
388    stdshader->Unbind();
389
390#if defined USE_D3D9 || defined _XBOX
391    /* TODO */
392#else
393#if !defined HAVE_GLES_2X
394    glDisable(GL_TEXTURE_2D);
395#endif
396    glDisable(GL_DEPTH_TEST);
397#if defined HAVE_GL_2X && !defined __APPLE__
398    glDisable(GL_ALPHA_TEST);
399#endif
400    glDisable(GL_BLEND);
401#endif
402}
403
404} /* namespace lol */
405
Note: See TracBrowser for help on using the repository browser.