EGLX : un petit traducteur GLX-EGL pour Wayland

Posté par . Édité par Nÿco, palm123 et Xavier Claude. Modéré par Nÿco. Licence CC by-sa
Tags :
57
27
oct.
2013
Serveurs d'affichage

Que ce soit un jeu vidéo, un petit logiciel de traitement ou une simple démo, on a tous dans notre coeur un vieux (comme dans vieux) logiciel utilisant des API obsolètes : OpenGL, X11… :-D

Malgré tout, l'antique OpenGL 1.X (celui avec glBegin(), glEnd() …) est en voie de disparition, remplacé par ses variantes mobiles que sont OpenGL ES 1.0, 2.0 et bientôt 3.0. Tout ça ne nous poserait pas de problème si X lui-même n'était pas en train d'être remplacé par Wayland, dont le compositeur de référence ne « comprend » qu'OpenGL ES en natif. Par ailleurs et par conséquent, la couche de glue entre GL et le système (GLX) change également, remplacée par EGL

C'est pour répondre à cette problèmatique que j'ai écrit EGLX, un traducteur GLX vers EGL/Wayland.

Couplé avec l'excellent traducteur GL vers GLES1 de jwz, il permet de recompiler une application GL/GLX et l'exécuter sous Wayland sans (beaucoup) modifier le code.

Une vidéo valant mieux qu'un long discours, voici une démonstration en vidéo et en image.

http://www.tarnyko.net/repo/posts/040/02.png

Techniquement, ce que fait EGLX est de fournir une "fausse" API X11/GLX au logiciel, qui va se retrouver à dialoguer avec Wayland. Par exemple, un appel du type :
XMapWindow (display, window);
va devenir :
wl_compositor_create_surface (…);
wl_egl_window_create (…);
eglCreateWindowSurface (…);

Bien sûr, tout n'est pas encore parfait, mais des intégrations GtkGLArea et wxWidgets sont déjà écrites ; le tout est disponible sur GitHub.

Et bien sûr, tout ceci ne devrait pas vous dispenser de porter votre code ;-).

  • # Ne pas confondre !

    Posté par . Évalué à 10.

    Attention à ne pas nourrir de confusion : la problématique GLX/EGL est (théoriquement) orthogonale à la problématique GL/GLES. L'API OpenGL non-ES a toujours sa place et est tout à fait compatible avec EGL. En fait, c'est la manière d'y accéder qui change. L'API GLX doit disparaître.

    Après, pour le moment ya des petits problèmes, comme par exemple le fait que sous Wayland seul OpenGL-ES est dispo car l'implémentation d'OpenGL est trop liée à X11 (ça va être corrigé par une nouvelle ABI proposée par NVidia).

    • [^] # Re: Ne pas confondre !

      Posté par (page perso) . Évalué à 4.

      la problématique GLX/EGL est (théoriquement) orthogonale à la problématique GL/GLES

      Tu as tout à fait raison.
      Je pensais d'ailleurs initialement faire une dépêche consacrée uniquement à l'aspect GLX (on prend une appli GLES/GLX sous X11 pour la porter en GLES/EGL sous Wayland).

      Le problème est que les cas d'application ne sont pas légion. L'immense majorité des applis GL sous X sont encore en vieux GL 1.X ; j'ai préféré mélanger avec la très courante problématique GL pour faire concret (et je pense que si EGLX est utilisé ailleurs, il le sera comme ça, de concert avec jwzGLES ou un autre wrapper).

      ça va être corrigé par une nouvelle ABI proposée par NVidia

      Alors là, je suis très intéressé. Je vais chercher, mais au cas où, aurais-tu un lien ?

  • # glshim

    Posté par (page perso) . Évalué à 1.

    Salut,

    A noter glshim peut etre une bonne alt a jwzgl.c

    http://boards.openpandora.org/index.php/topic/11506-opengl-implementation-tldr-more-games/

    gpg:0x467094BC

    • [^] # Re: glshim

      Posté par (page perso) . Évalué à 1.

      Effectivement ; d'autant qu'il intègre GLU (ce que jwzgl ne fait pas) et peut remplacer libGL.so à l'exécution, sans besoin de recompiler.

      Il a par contre comme jwzgl parfois tendance à se tromper dans les profondeurs.

      PS : L'idéal serait quand même d'avoir une vraie implémentation de référence. J'ai trouvé ça en rapport au commentaire de Léo, mais ça ne fournit pas EGL et ne me paraît pas encore prêt d'arriver, si ?

  • # OpenGL antique

    Posté par (page perso) . Évalué à 2.

    C'était quand même bien les glBegin/glEnd… Les versions ES et la façon de faire des nouveaux, c'est bien pour les perfs, mais c'est extrêmement peu pratique, il faut tordre son code et l'organisation des données pour faire plaisir au GPU. Du coup pas mal de bibliothèques proposent des équivalents aux antiques glBegin/glEnd et autres display lists: modes immédiats, sprite batching, scenegraph…

    http://devnewton.bci.im

    • [^] # Re: OpenGL antique

      Posté par . Évalué à 9.

      Tu peux décrire un peu mieux le problème pour nous expliquer, à nous autre ,qui ne prennont pas d'OpenGL au petit déjeuner ?

      "La première sécurité est la liberté"

      • [^] # Re: OpenGL antique

        Posté par . Évalué à 2.

        Bah, il décrit juste un problème courant(*): la méthode la plus simple pour écrire un programme n'est pas la plus efficace, OpenGL te fournit les 2 méthodes, EGL te donne juste les API pour la méthode efficace, ce qui se défend: si tu ne cherches pas à faire efficace pourquoi utiliser EGL??
        Tant qu'à faire autant utiliser un rendu logiciel..

        *:C'est le cas pour OpenGL, le parallélisme, la gestion mémoire (GC vs pas de GC)..

        • [^] # C'est pas faute d'avoir prévenu :)

          Posté par . Évalué à 4.

          s/EGL/OpenGL-ES/g

          EGL n'est pas une API de dessin, c'est une API standard pour obtenir des buffers graphiques (par exemple une fenêtre) ! Ces derniers pouvant être utilisés par OpenGL. Ou OpenGL-ES. Ou OpenVG. Ou OpenMAX…

      • [^] # Re: OpenGL antique

        Posté par (page perso) . Évalué à 6.

        Voici le code OpenGL antique que j'utilise pour afficher des sprites avec des effets (rotation, zoom, transparence):

        private void drawSprite(Sprite sprite) {
                GL11.glPushMatrix();
                GL11.glTranslatef(sprite.getPosition().getX(), sprite.getPosition().getY(),0.0f);
                GL11.glRotatef(sprite.getRotate(), 0, 0, 1.0f);
                GL11.glScalef(sprite.getScale(), sprite.getScale(), 1);
                final IAnimationFrame frame = sprite.getPlay().getCurrentFrame();
                final IAnimationImage image = frame.getImage();
                if (image.hasAlpha()) {
                    GL11.glEnable(GL11.GL_BLEND);
                }
                GL11.glBindTexture(GL11.GL_TEXTURE_2D, image.getId());
        
                final float u1, u2;
                if (sprite.isMirrorX()) {
                    u1 = frame.getU2();
                    u2 = frame.getU1();
                } else {
                    u1 = frame.getU1();
                    u2 = frame.getU2();
                }
        
                final float v1, v2;
                if (sprite.isMirrorY()) {
                    v1 = frame.getV1();
                    v2 = frame.getV2();
                } else {
                    v1 = frame.getV2();
                    v2 = frame.getV1();
                }
                final Color color = sprite.getColor();
                GL11.glColor4ub(color.getRedByte(), color.getGreenByte(), color.getBlueByte(), color.getAlphaByte());
                float x1 = -sprite.getWidth() / 2.0f;
                float x2 = sprite.getWidth() / 2.0f;
                float y1 = -sprite.getHeight() / 2.0f;
                float y2 = sprite.getHeight() / 2.0f;
                GL11.glBegin(GL11.GL_QUADS);
                GL11.glTexCoord2f(u1, v1);
                GL11.glVertex2f(x1, y2);
                GL11.glTexCoord2f(u2, v1);
                GL11.glVertex2f(x2, y2);
                GL11.glTexCoord2f(u2, v2);
                GL11.glVertex2f(x2, y1);
                GL11.glTexCoord2f(u1, v2);
                GL11.glVertex2f(x1, y1);
                GL11.glEnd();
                GL11.glColor3f(1f, 1f, 1f);
                if (image.hasAlpha()) {
                    GL11.glDisable(GL11.GL_BLEND);
                }
                GL11.glPopMatrix();
            }
        

        Voici l'équivalent en OpenGL moderne:

        public class SpriteBatch {
                public static final String U_TEXTURE = "u_texture";
                public static final String U_PROJ_VIEW = "u_projView";
        
                public static final String ATTR_COLOR = "Color";
                public static final String ATTR_POSITION = "Position";
                public static final String ATTR_TEXCOORD = "TexCoord";
        
                public static final String DEFAULT_VERT_SHADER = "uniform mat4 " + U_PROJ_VIEW + ";\n"
                                + "attribute vec4 " + ATTR_COLOR + ";\n" + "attribute vec2 " + ATTR_TEXCOORD + ";\n"
                                + "attribute vec2 " + ATTR_POSITION + ";\n" + "varying vec4 vColor;\n"
                                + "varying vec2 vTexCoord; \n" + "void main() {\n" + "        vColor = " + ATTR_COLOR + ";\n"
                                + "        vTexCoord = " + ATTR_TEXCOORD + ";\n" + "        gl_Position = " + U_PROJ_VIEW
                                + " * vec4(" + ATTR_POSITION + ".xy, 0.0, 1.0);\n" + "}";
        
                public static final String DEFAULT_FRAG_SHADER = "uniform sampler2D " + U_TEXTURE + ";\n"
                                + "varying vec4 vColor;\n" + "varying vec2 vTexCoord;\n" + "void main() {\n"
                                + "        vec4 texColor = texture2D(" + U_TEXTURE + ", vTexCoord);\n"
                                + "        gl_FragColor = vColor * texColor;\n" + "}";
        
                public static final List<VertexAttrib> ATTRIBUTES = Arrays.asList(new VertexAttrib(0,
                                ATTR_POSITION, 2), new VertexAttrib(1, ATTR_COLOR, 4), new VertexAttrib(2,
                                ATTR_TEXCOORD, 2));
        
                static ShaderProgram defaultShader;
                public static int renderCalls = 0;
        
                protected FloatBuffer buf16;
                protected Matrix4f projMatrix = new Matrix4f();
                protected Matrix4f viewMatrix = new Matrix4f();
                protected Matrix4f transpositionPool = new Matrix4f();
                private Matrix4f projViewMatrix = new Matrix4f(); //only for re-using Matrix4f objects
        
                protected Texture texture;
                protected ShaderProgram program;
        
                protected VertexData data;
        
                private int idx;
                private int maxIndex;
        
                private Color color = new Color();
                private boolean drawing = false;
        
                public static ShaderProgram getDefaultShader() throws LWJGLException {
                        return defaultShader == null ? (defaultShader = new ShaderProgram(DEFAULT_VERT_SHADER, DEFAULT_FRAG_SHADER,
                                        ATTRIBUTES)) : defaultShader;
                }
        
                public SpriteBatch(ShaderProgram program) {
                        this(program, 1000);
                }
        
                public SpriteBatch(ShaderProgram program, int size) {
                        this(program, 1000, true);
                }
        
                public SpriteBatch(ShaderProgram program, int size, boolean updateUniforms) {                
                        this.program = program;
        
                        // later we can do some abstraction to replace this with VBOs...
                        this.data = new VertexArray(size * 6, ATTRIBUTES);
        
                        // max indices before we need to flush the renderer
                        maxIndex = size * 6;
        
                        // default size
                        resize(Display.getWidth(), Display.getHeight());
                }
        
                /**
                 * Creates a sprite batch with a default shader, shared across all sprite batches.
                 * @param size
                 * @throws LWJGLException
                 */
                public SpriteBatch(int size) throws LWJGLException {
                        this(getDefaultShader(), size);
                }
        
                public SpriteBatch() throws LWJGLException {
                        this(1000);
                }
        
                public Matrix4f getViewMatrix() {
                        return viewMatrix;
                }
        
                public Matrix4f getProjectionMatrix() {
                        return projMatrix;
                }
        
                public Matrix4f getCombinedMatrix() {
                        Matrix4f.mul(Matrix4f.transpose(projMatrix, transpositionPool),
                                        viewMatrix, projViewMatrix);
                        return projViewMatrix;
                }
        
                /** A convenience method to resize the projection matrix to the given
                 * dimensions, using y-down ortho 2D. This will invoke a call to
                 * updateMatrices.
                 *
                 * @param width
                 * @param height */
                public void resize(int width, int height) {
                        projMatrix = MathUtil.toOrtho2D(projMatrix, 0, 0, width, height);
                        updateUniforms();
                }
        
                /** Sets this SpriteBatch's color to the RGBA values of the given color
                 * object.
                 *
                 * @param color the RGBA values to use */
                public void setColor(Color color) {
                        setColor(color.r, color.g, color.b, color.a);
                }
        
                /** Sets this SpriteBatch's color to the given RGBA values.
                 *
                 * @param r the red value
                 * @param g the green value
                 * @param b the blue value
                 * @param a the alpha value */
                public void setColor(float r, float g, float b, float a) {
                        color.set(r, g, b, a);
                }
        
                /** Call to multiply the the projection with the view matrix and save the
                 * result in the uniform mat4 {@value #U_PROJ_VIEW}, as well as update the
                 * {@value #U_TEXTURE} uniform. */
                public void updateUniforms() {
                        updateUniforms(program);
                }
        
                /** Call to multiply the the projection with the view matrix and save the
                 * result in the uniform mat4 {@value #U_PROJ_VIEW}, as well as update the
                 * {@value #U_TEXTURE} uniform. */
                public void updateUniforms(ShaderProgram program) {
                        projViewMatrix = getCombinedMatrix();
        
                        // bind the program before sending uniforms
                        program.use();
        
                        boolean oldStrict = ShaderProgram.isStrictMode();
        
                        //disable strict mode so we don't run into any problems
                        ShaderProgram.setStrictMode(false);
        
                        // we can now utilize ShaderProgram's hash map which may be better than
                        // glGetUniformLocation
        
                        // Store the the multiplied matrix in the "projViewMatrix"-uniform:
                        program.setUniformMatrix(U_PROJ_VIEW, false, projViewMatrix);
        
                        // upload texcoord 0
                        program.setUniformi(U_TEXTURE, 0);
        
                        //reset strict mode
                        ShaderProgram.setStrictMode(oldStrict);
                }
        
                /** An advanced call that allows you to change the shader without uploading
                 * shader uniforms. This will flush the batch if we are within begin().
                 *
                 * @param program
                 * @param updateUniforms whether to call updateUniforms after changing the
                 * programs */
                public void setShader(ShaderProgram program, boolean updateUniforms) {
                        if (program==null)
                                throw new NullPointerException("shader cannot be null; use getDefaultShader instead");
                        if (drawing) //if we are already drawing, flush the batch before switching shaders
                                flush();
                        this.program = program; //now switch the shader
                        if (updateUniforms) //send uniform data to shader
                                updateUniforms();
                        else if (drawing) //if we don't want to update, then just start the program if we are drawing
                                program.use();
                }
        
                /** Changes the shader and updates it with the current texture and projView
                 * uniforms. This will flush the batch if we are within begin().
                 *
                 * @param program the new program to use */
                public void setShader(ShaderProgram program) {
                        setShader(program, true);
                }
        
                public ShaderProgram getShader() {
                        return program;
                }
        
                public void begin() {
                        if (drawing)
                                throw new IllegalStateException("must not be drawing before calling begin()");
                        drawing = true;
                        program.use();
                        idx = 0;
                        renderCalls = 0;
                        texture = null;
                }
        
                public void end() {
                        if (!drawing)
                                throw new IllegalStateException("must be drawing before calling end()");
                        drawing = false;
                        flush();
                }
        
                public void flush() {
                        if (idx > 0) {
                                data.flip();
                                render();
                                idx = 0;
                                data.clear();
                        }
                }
        
                public void drawRegion(Texture tex, float srcX, float srcY, float srcWidth, float srcHeight,
                                float dstX, float dstY) {
                        drawRegion(tex, srcX, srcY, srcWidth, srcHeight, dstX, dstY, srcWidth, srcHeight);
                }
        
                public void drawRegion(Texture tex, float srcX, float srcY, float srcWidth, float srcHeight,
                                float dstX, float dstY, float dstWidth, float dstHeight) {
                        float u = srcX / tex.getWidth();
                        float v = srcY / tex.getHeight();
                        float u2 = (srcX + srcWidth) / tex.getWidth();
                        float v2 = (srcY + srcHeight) / tex.getHeight();
                        draw(tex, dstX, dstY, dstWidth, dstHeight, u, v, u2, v2);
                }
        
                public void drawRegion(TextureRegion region, float srcX, float srcY, float srcWidth, float srcHeight, float dstX, float dstY) {
                        drawRegion(region, srcX, srcY, srcWidth, srcHeight, dstX, dstY, srcWidth, srcHeight);
                }
        
                public void drawRegion(TextureRegion region, float srcX, float srcY, float srcWidth, float srcHeight,
                                float dstX, float dstY, float dstWidth, float dstHeight) {
                        drawRegion(region.getTexture(), region.getRegionX() + srcX, region.getRegionY() + srcY,
                                        srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight);                
                }
        
                public void draw(ITexture tex, float x, float y) {
                        draw(tex, x, y, tex.getWidth(), tex.getHeight());
                }
        
                public void draw(ITexture tex, float x, float y, float width, float height) {
                        draw(tex, x, y, width, height, tex.getU(), tex.getV(), tex.getU2(), tex.getV2());
                }
        
        
                public void draw(ITexture tex, float x, float y, float originX, float originY, float rotationRadians) {
                        draw(tex, x, y, tex.getWidth(), tex.getHeight(), originX, originY, rotationRadians);
                }
        
                public void draw(ITexture tex, float x, float y, float width, float height,
                                float originX, float originY, float rotationRadians) {
                        draw(tex, x, y, width, height, originX, originY, rotationRadians, tex.getU(), tex.getV(), tex.getU2(), tex.getV2());
                }
        
                public void draw(ITexture tex, float x, float y, float width, float height,
                                float originX, float originY, float rotationRadians,
                                float u, float v,
                                float u2, float v2) {
                        checkFlush(tex);
                        final float r = color.r;
                        final float g = color.g;
                        final float b = color.b;
                        final float a = color.a;
        
        
                        float x1,y1, x2,y2, x3,y3, x4,y4;
        
                        if (rotationRadians != 0) {
                                float scaleX = 1f;//width/tex.getWidth();
                                float scaleY = 1f;//height/tex.getHeight();
        
                                float cx = originX*scaleX;
                                float cy = originY*scaleY;
        
                                float p1x = -cx;
                                float p1y = -cy;
                                float p2x = width - cx;
                                float p2y = -cy;
                                float p3x = width - cx;
                                float p3y = height - cy;
                                float p4x = -cx;
                                float p4y = height - cy;
        
                                final float cos = (float) Math.cos(rotationRadians);
                                final float sin = (float) Math.sin(rotationRadians);
        
                                x1 = x + (cos * p1x - sin * p1y) + cx; // TOP LEFT
                                y1 = y + (sin * p1x + cos * p1y) + cy;
                                x2 = x + (cos * p2x - sin * p2y) + cx; // TOP RIGHT
                                y2 = y + (sin * p2x + cos * p2y) + cy;
                                x3 = x + (cos * p3x - sin * p3y) + cx; // BOTTOM RIGHT
                                y3 = y + (sin * p3x + cos * p3y) + cy;
                                x4 = x + (cos * p4x - sin * p4y) + cx; // BOTTOM LEFT
                                y4 = y + (sin * p4x + cos * p4y) + cy;
                        } else {
                                x1 = x;
                                y1 = y;
        
                                x2 = x+width;
                                y2 = y;
        
                                x3 = x+width;
                                y3 = y+height;
        
                                x4 = x;
                                y4 = y+height;
                        }
        
                        // top left, top right, bottom left
                        vertex(x1, y1, r, g, b, a, u, v);
                        vertex(x2, y2, r, g, b, a, u2, v);
                        vertex(x4, y4, r, g, b, a, u, v2);
        
                        // top right, bottom right, bottom left
                        vertex(x2, y2, r, g, b, a, u2, v);
                        vertex(x3, y3, r, g, b, a, u2, v2);
                        vertex(x4, y4, r, g, b, a, u, v2);
                }
        
                public void draw(ITexture tex, float x, float y, float width, float height, float u, float v,
                                float u2, float v2) {
                        draw(tex, x, y, width, height, x, y, 0f, u, v, u2, v2);
                }
        
                /** Renders a texture using custom vertex attributes; e.g. for different
                 * vertex colours. This will ignore the current batch color and "x/y translation",
                 * as well as the U/V coordinates of the given ITexture.
                 *
                 * @param tex the texture to use
                 * @param vertices an array of 6 vertices, each holding 8 attributes (total
                 * = 48 elements)
                 * @param offset the offset from the vertices array to start from */
                public void draw(ITexture tex, float[] vertices, int offset) {
                        checkFlush(tex);
                        data.put(vertices, offset, data.getTotalNumComponents() * 6);
                        idx += 6;
                }
        
                VertexData vertex(float x, float y, float r, float g, float b, float a, float u, float v) {
                        data.put(x).put(y).put(r).put(g).put(b).put(a).put(u).put(v);
                        idx++;
                        return data;
                }
        
                protected void checkFlush(ITexture sprite) {
                        if (sprite == null || sprite.getTexture()==null)
                                throw new NullPointerException("null texture");
        
                        // we need to bind a different texture/type. this is
                        // for convenience; ideally the user should order
                        // their rendering wisely to minimize texture binds
                        if (sprite.getTexture() != this.texture || idx >= maxIndex) {
                                // apply the last texture
                                flush();
                                this.texture = sprite.getTexture();
                        }
                }
        
                private void render() {
                        if (texture != null)
                                texture.bind();
                        data.bind();
                        data.draw(GL_TRIANGLES, 0, idx);
                        data.unbind();
                        renderCalls++;
                }
        }
        

        http://devnewton.bci.im

        • [^] # Re: OpenGL antique

          Posté par . Évalué à 6.

          j'ai pas tout lu.
          Mais dans ton nouveau code tu mélanges des shader aussi et ça alourdi pas mal.
          Les shader gèrent le traitement de des données (ici, le pipe graphique) et sont indépendant de la soumissions des données (immediate mode, display list, vbo, …)

          Après, je me permet une remarque (et je me trompe peut-être car je n'ai pas tout le code sous la main), mais dans ton code d'origine, j'ai l'impression que tu parcours ton data model pour faire l'affichage.
          C'est là que ta séparation code/donnée est mal faite !

          Dans ton parcours de data model, tu dois construire un noeud de scenegraph avec seulement les infos utiles pour le rendu :
          une seule matrice de transformation (tu la calcules à ce moment précis)
          Ton mesh (les vertex avec tous leurs attributs)
          Les données supplémentaires (reference vers une texture à bind, shader particulier à utiliser…)
          Les states OpenGL dont tu as besoin (material, lights, …)

          Ton rendu se fait ensuite en parcourant ton scenegraph, appliquand le state, la matrice de transformation et soumettant les données.
          Ça c'est pour un scene graph simple (sans effet compliqué de lumière, transparence, …) et sans essayer de minimiser les changement d'états d'OpenGL qui coutent très cher.

          Tu peux alors mettre à jour juste une partie de ces données (une entité de ton jeu met à jour son noeud dans le scene graph)
          Tu peux également faire le rendu dans un thread distinct pour garder un framerate constant et utiliser un lock sur les noeuds que tu mets à jour (ou construire un noeud à coté et juste faire un remplacement quand il est fini)
          Et tu retrouve un "logique" qui ressemble à du direct mode dans ton code "de dessin" qui est en fait le code de création d'un noeud de scene graph tout en ayant un rendu optimisé et surtout découplé du reste du code, donc facile à faire évoluer.

          Après, c'est peut-être ce que tu fais déjà avec ta classe Sprite et je l'ai mal compris juste.

          • [^] # Re: OpenGL antique

            Posté par (page perso) . Évalué à 4.

            C'est là que ta séparation code/donnée est mal faite !

            J'utilise un entity system :

            • la classe Sprite est un composant qu'on peut ajouter/enlever à une entité pour lui donner une existence visuelle.
            • une autre classe, DrawSystem, se charge de parcourir les entités ayant le composant Sprite pour les afficher.

            Si j'ai besoin de perf, je peux remplacer DrawSystem par quelquechose de plus intelligent, mais j'espère ne pas avoir à le faire, car sortir un scenegraph qui regroupe les données, minimise les changement d'états et joue avec les shaders pour diminuer la conso CPU, c'est beaucoup pour afficher quelques sprites et je ne suis pas certains de pouvoir battre un bon driver :-)

            https://github.com/devnewton/ned-et-les-maki/tree/master/game/src/main/java/org/geekygoblin/nedetlesmaki/game

            http://devnewton.bci.im

            • [^] # Re: OpenGL antique

              Posté par . Évalué à 3.

              nickel alors :)

              Juste une question que je me suis posé en lisant la dépêche sur les entity système.
              Pourquoi ne pas juste les ranger les composants dans des listes et les faire réferencer par les entités ?
              Comme ça, pour processer un type de composant, tu attaques directement la liste sans te soucier de quelle entité est connectée dessus (ça rejoins un peu l'idée du scene graph en fait), et tu n'as pas besoin de faire une lourde requete sur des associations entre entités et composants !

              Pour le coup de battre un bon driver, détrompe toi ! quand on sait ce que l'on fait, on est toujours meilleur que les optimisations générales d'un sous sytème.
              L'exemple simple est de ne pas faire une opération quand elle est déjà faite ou inutile car tu n'en auras plus besoin (genre appeler sort sur un tableau que tu sais déjà trié). Ça, aucun sous système ne peut le décider à ta place, et tu gagnes un facteur temps infini ;)

              • [^] # Re: OpenGL antique

                Posté par . Évalué à 3.

                Pourquoi ne pas juste les ranger les composants dans des listes et les faire réferencer par les entités ?

                Normalement, c'est ce qu'il faut faire, les composants sont rangés par type (ça s'appelle le modèle ES Alpha et ça se rapproche d'une base de données). Dans Artemis, ils ne font pas comme ça, c'est l'autre méthode, les composants sont dans les entités, j'aime moins.

                Comme ça, pour processer un type de composant, tu attaques directement la liste sans te soucier de quelle entité est connectée dessus (ça rejoins un peu l'idée du scene graph en fait), et tu n'as pas besoin de faire une lourde requete sur des associations entre entités et composants !

                Oui et non. Souvent, une entité à plusieurs composants, et un système a besoin de plusieurs composants de cette entité (typiquement, il va lire certains composants et il va en écrire d'autres), donc ça sert à quelque chose de savoir à quelle entité appartient tel composant. Pour certains composants, on peut faire comme tu dis mais ça ne change pas grand chose par rapport au cas de base finalement.

            • [^] # Re: OpenGL antique

              Posté par . Évalué à 3.

              J'utilise un entity system

              Et alors ? Est-ce que ça te plaît comme manière de penser ? Je vois que tu as déjà pas mal de code, ça m'impressionne. Et que tes composants sont tout petits, tu n'as pas peur d'avoir trop découpé ? Il y a des choses, je me demandais comment j'allais faire, je pourrai m'inspirer de tes techniques ;)

              • [^] # Re: OpenGL antique

                Posté par (page perso) . Évalué à 3.

                En fait, dans un précédent projet, je faisais de l'entity system avant que ça s'appelle comme ça! Il faudrait un historien pour savoir à partir de quand et par qui ça a été théorisé.

                Dans le code de Ned et les maki, je n'ai fait que les composants graphiques, pour le reste c'est un autre développeur qui s'en charge, mais je pense que son découpage fin correspond aux règles du jeu sur lequel on travaille.

                http://devnewton.bci.im

                • [^] # Re: OpenGL antique

                  Posté par . Évalué à 3.

                  En fait, dans un précédent projet, je faisais de l'entity system avant que ça s'appelle comme ça! Il faudrait un historien pour savoir à partir de quand et par qui ça a été théorisé.

                  D'après tout ce que j'ai pu lire, effectivement, ça existe depuis longtemps même si ça ne s'appelait pas comme ça et qu'il y avait beaucoup de variantes. Après, j'ai l'impression que les articles que j'avais mentionné (notamment celui sur les MMO) ont été un début de théorisation (notamment le parallèle avec les bases de données). D'ailleurs, c'est le même auteur qui a fait le wiki sur la question. Mais je pense que le concept n'a pas été complètement exploré ni assez théorisé (les variantes notamment).

                  • [^] # Re: OpenGL antique

                    Posté par . Évalué à 3.

                    Je pense surtout qu'on y arrive naturellement en codant le chose et en apprenant de ses erreur et projets passés.
                    Quand j'ai lu ton message sur le entity system, beaucoup de choses mon paru naturelles alors que je ne m'étais jamais renseigné sur le sujet.
                    Le truc qui est cool par contre, c'est d'arriver à la formaliser, à comprendre ce qu'il y a d'intéressant, à voir aussi les défauts, pour ne pas l'utiliser à toutes les sauces (un peu comme quand tu découvres l'héritage ou les templates… j'en ai mis partout et nimporte comment moi :D)

                    • [^] # Re: OpenGL antique

                      Posté par . Évalué à 2.

                      Oui, la formalisation est intéressante mais incomplète encore, je pense. Et comme tu dis, ça ne fait pas tout. Par exemple, on ressent assez vite le besoin d'avoir en parallèle un outil de message ou d'événements pour communiquer entre entité. Et ça s'explique assez bien. Avec les systèmes, on a plutôt un truc de type polling, on examine et on modifie l'état de manière régulière. Il faut donc contrebalancer avec un truc de type événement, c'est-à-dire où le polling est sous-optimal. C'est en tout cas ma façon de le voir. Mais ce qui est drôle, c'est que dans pas mal de présentation, soit c'est présenté en même temps, en disant que ça fait pas partie d'un système à entité, soit c'est relégué presque aux oubliettes en disant que souvent, on le met, mais sans voir qu'en fait, c'est indispensable.

                      • [^] # Re: OpenGL antique

                        Posté par (page perso) . Évalué à 4.

                        Pour le messaging, je crée des entités avec un composant de type Message :-) Le système qui les traite les jette après usage.

                        http://devnewton.bci.im

                        • [^] # Re: OpenGL antique

                          Posté par . Évalué à 2.

                          Pour des messages simples, ça marche. Mais après, je trouve que ce n'est pas très flexible. Si ton type Message est simple (c'est-à-dire sans héritage et polymorphisme), tu ne peux pas faire grand chose.

                          • [^] # Re: OpenGL antique

                            Posté par (page perso) . Évalué à 2.

                            Le message est une entité, donc elle peut avoir plein de composants :-)

                            http://devnewton.bci.im

                            • [^] # Re: OpenGL antique

                              Posté par . Évalué à 3.

                              Ok, j'achète ;)

                              Mais puisque tu as réponse à tout :P dans ton système, tu es obligé de gérer tous les événements au même endroit non ?

                              • [^] # Re: OpenGL antique

                                Posté par (page perso) . Évalué à 2.

                                Je préfère une gestion centralisée des événements, mais tu peux utiliser plusieurs types de composants pour les faire traiter par plusieurs systèmes ou alors mettre en place un système "Poste" qui va distribuer le courrier.

                                http://devnewton.bci.im

              • [^] # Re: OpenGL antique

                Posté par . Évalué à 2.

                Et que tes composants sont tout petits, tu n'as pas peur d'avoir trop découpé ?

                En programmation, plus les classes sont petites et cohésives et plus c'est facile a maintenir.
                La dessus, la JVM (newton adventures est en java) a été beaucoup travaillée pour optimiser ce genre de code. Je ne sais pas si un compilateur C/C++ est capable d'avoir des optimisations aussi poussées dans de tel cas.

                • [^] # Re: OpenGL antique

                  Posté par (page perso) . Évalué à 4.

                  Un compilo C++ mets facilement une grosse fessée cul nu à la jvm pour les jeux. Entre les struct, les templates et l'absence de garbage collector, on n'est pas sur la même planète.

                  http://devnewton.bci.im

                  • [^] # Re: OpenGL antique

                    Posté par . Évalué à 2.

                    Pour avoir jouer avec un IA en Java, j'estime l'efficacité d'une JVM Sun à l'équivalent de gcc -O0. Il n'y même pas de sortie de test des boucles, ni d'inline des getter/setter. Une methode static est bien plus rapide qu'une méthode virtuel normal.

                    "La première sécurité est la liberté"

                    • [^] # Re: OpenGL antique

                      Posté par . Évalué à 2.

                      Pour avoir jouer avec un IA en Java,

                      Qu'est ce qu'un IA?

                      Il n'y même pas de sortie de test des boucles

                      De quelle optimisation parles-tu?

                      ni d'inline des getter/setter.

                      A propos de l'inline des getters/setters je n'y crois pas du tout: http://blog.xebia.fr/2013/05/27/comprendre-le-fonctionnement-de-la-jvm-article-1/

                      Une methode static est bien plus rapide qu'une méthode virtuel normal.

                      A propos des methodes statics, je te crois sans peine, c'est toujours le plus rapide a appeler quel que soit le langage.

                       

                      As-tu au moins laisser la JVM "chauffer" et trouver les methodes a inliner?

                      • [^] # Re: OpenGL antique

                        Posté par . Évalué à -1. Dernière modification le 29/10/13 à 15:04.

                        "Qu'est ce qu'un IA?"

                        une intelligence artificiel pour un jeu.

                        "De quelle optimisation parles-tu?"

                        for() {if()…} -> if(){for()…}{for()…}
                        un peu de déroulage de boucle, etc…
                        réutiliser les objets au lieu de les oublier et en créer d'autre. En gros, faire en sorte de ne jamais faire de new en rythme de croisière.

                        "A propos de l'inline des getters/setters je n'y crois pas du tout"

                        Je m'en fout pas mal de ton avis. Quand tu vires les getter/setter et que tu gagnes 30% de perf, tu te dis que le compilo optimise rien (c'était une JVM sun sous Linux)

                        "A propos des methodes statics, je te crois sans peine, c'est toujours le plus rapide a appeler quel que soit le langage."

                        Y'a des moyens pour que la différence soit minime, c'est loin d'être le cas.

                        "As-tu au moins laisser la JVM "chauffer" et trouver les methodes a inliner?"

                        Peut-être pas assez. Mais tout le code était chaud car cyclique avec un parcours d'arbre.

                        "La première sécurité est la liberté"

                        • [^] # Re: OpenGL antique

                          Posté par . Évalué à 5.

                          De quelle optimisation parles-tu?

                          for() {if()…} -> if(){for()…}{for()…}
                          un peu de déroulage de boucle, etc…

                          "-XX:LoopUnrollLimit=n Unroll loop bodies with server compiler intermediate representation node count less than this value. The limit used by the server compiler is a function of this value, not the actual value. The default value varies with the platform on which the JVM is running."

                          Encore une fois, la JVM fait beaucoup plus d'optimisations que tu ne le penses.

                          réutiliser les objets au lieu de les oublier et en créer d'autre. En gros, faire en sorte de ne jamais faire de new en rythme de croisière.

                          Ca, c'est a toi de le faire.
                          J'ai deja vu du code comme ca, et je me suis demande si les gains etaient vraiment au RDV au final.

                          A propos de l'inline des getters/setters je n'y crois pas du tout

                          Je m'en fout pas mal de ton avis.

                          Ah oui je me rappelle de toi, tu es le gars qui se plaint sans arret que les perfs de Java sont a chier, mais qui refuse d'en apprendre plus sur le fonctionnement du langage et de la JVM.
                          Je te laisse troller tout seul alors.
                          Amuses toi bien.

                          • [^] # Re: OpenGL antique

                            Posté par . Évalué à -2.

                            "Ah oui je me rappelle de toi, tu es le gars qui se plaint sans arret que les perfs de Java sont a chier, mais qui refuse d'en apprendre plus sur le fonctionnement du langage et de la JVM."

                            Les perf pas top, je les es vu, donc dire que tu n'y crois pas trop… C'est un peu énorme.

                            "La première sécurité est la liberté"

                  • [^] # Re: OpenGL antique

                    Posté par . Évalué à 2.

                    Je suis d'accord.

                    C'est pour ca que la depeche sur Rust m'a beaucoup interesse avec la possiblite d'utiliser de n'utiliser le GC que lorsque l'on en a vraiment besoin.

                    Il manque juste un systeme equivalent aux templates dans Rust pour etre aussi performant que le C++.

                    • [^] # Re: OpenGL antique

                      Posté par (page perso) . Évalué à 4.

                      • [^] # Re: OpenGL antique

                        Posté par . Évalué à 2.

                        Generics != templates

                        J parlais des templates pour faire echo a ce que tu disais sur les perfs.

                        Les generics en java donnent syntaxiquement quelque chose d'equivalent des templates C++, mais cela n'a rien a voir niveau perf. GCC est capable de triturer un template a tel point que ne subsistent que les instructions reelement utiles et les perfs sont bluffantes.

                        Je me demandais si le compilateur de Rust pouvait sortir des perfs aussi bonnes qu'avec les templates de C++.

                        • [^] # Re: OpenGL antique

                          Posté par (page perso) . Évalué à 3.

                          De loin, les generics et les traits de Rust semblent faire le boulot des templates en C++. Par contre ça m'étonnerais que le jeune compilateur carbure autant que les meilleurs compilos C++.

                          http://devnewton.bci.im

                • [^] # Re: OpenGL antique

                  Posté par . Évalué à 3.

                  En programmation, plus les classes sont petites et cohésives et plus c'est facile a maintenir.

                  Oui mais bon, il y a des limites. Par exemple, si je crée un composant CoordX et un composant CoordY, ça n'a pas de sens parce que les deux sont toujours associés donc on a tout intérêt à mettre tout ensemble.

                  • [^] # Re: OpenGL antique

                    Posté par . Évalué à 3.

                    Ne me fais pas dire ce que je n'ai pas dit!
                    Je n'ai pas dit de créer plus de classes qu'il n'y en a besoin.

                    • [^] # Re: OpenGL antique

                      Posté par . Évalué à 2.

                      Ma question portait sur ce cas là en particulier, pas sur le cas général (auquel cas, je suis d'accord avec ce que tu as dit).

    • [^] # Re: OpenGL antique

      Posté par . Évalué à 5.

      glBegin et glEnd sont excellent …pour l'apprentissage.
      En général, si tu dois torturer ton code pour qu'il s'en passe, c'est que déjà à l'origine, soit :
      - tu as une mauvaise séparation de tes données et algorithmes.
      - tu as organisé ton code en pensant glBegin/glEnd
      - tu as du mal à penser vbo par manque d'habitude/de pratique

      De toute façon, les diplay list couplées à du mode immédiat sont en interne, dans tous les pilotes récents, implémentée avec des vbo et du state tracking (qui est une horreur d'un point de vu bogues et perf)
      Donc vu qu'en tant que développeur de ton jeu, tu sais ce que tu fais, en général il faut mieux s'occuper du state tracking soi même avec un scene graph adapté à son rendu et faire du vbo
      Ce qui au final ne change pas beaucoup d'un glBegin/glEnd, tu peux très bien le gérer de la sorte avec tes propres appels begin/end et faire un flush à la fin qui balancera le draw de tes vbos.

      • [^] # Re: OpenGL antique

        Posté par (page perso) . Évalué à 2.

        Disons qu'organiser toutes les données d'une application dans de gros buffers globaux, ce n'est pas naturel en développement objet :-)

        Je trouve que les premières versions d'opengl avaient réussit à abstraire la réalité du hardware (gros buffers) avec une api élégante (glBegin/glEnd, display lists). Les dernières versions donnent le sentiment de taper directement dans le GPU et la prochaine API d'AMD promets d'être encore plus bas niveau.

        Je pense que ce mouvement qui vise à donner aux développeurs un accès direct au hardware est bon pour les performances, mais mauvais pour la concurrence et l'innovation: un nouveau constructeur de carte graphique ne peut que faire comme les autres.

        http://devnewton.bci.im

        • [^] # Re: OpenGL antique

          Posté par . Évalué à 4.

          Disons qu'organiser toutes les données d'une application dans de gros buffers globaux, ce n'est pas naturel en développement objet :-)

          Tu veux dire en java :D ? (ok ok, c'était un blague…)
          Mais pas tant que ça en fait, d'un point de vue optimisation mémoire (surtout gestion cache et fragmentation), avoir des données "volumineuses" dans de gros buffer et que les objets aient juste les entrées pour y acceder n'est pas si mauvais que ça.
          Et d'un point de vue programmation objet, je ne vois pas de soucis non plus. La POO pour moi (c'est un avis personnel et discutable) me donne surtout des outils pour gêrer les relations entre les données et leur traitement ainsi le flux d'execution (à un niveau assez élevé, je ne parle pas des for, if, …)
          Mais je prends toujours (ok, pas toujours du tout… mais je sais que c'est mal !) soin de séparer correctement mes données de mon code de traitement.
          Au final, cela est assez agnostique de "l'endroit" ou tu ranges tes données, il suffit de bien encapsuler tes accès et tout se passe bien.

          Après, on parle d'optimisation ! C'est sur que si tu n'en as pas besoin, et bien ça peut paraitre lourd à faire de cette manière.

          Mais je pense aussi que si tu n'en as pas besoin, c'est que tu n'as pas besoin d'un accès direct au métériel non plus, donc peut-être qu'utiliser une surcouche comme SDL (si tu reste en 2D) serait plus intéressant pour toi.
          Il faut bien se rendre compte que la lib OpenGL est écrite pour les gros besoins en performance, donc ça ne me surprends pas que cela colle avec une organisation optimale de données en mémoire.

          Je trouve que les premières versions d'opengl avaient réussit à abstraire la réalité du hardware

          OpenGL a toujours été près du matériel, la différence c'est qu'à l'époque, les cartes fonctionnaient de façon très différente.

          Je pense que ce mouvement qui vise à donner aux développeurs un accès direct au hardware est bon pour les performances, mais mauvais pour la concurrence et l'innovation: un nouveau constructeur de carte graphique ne peut que faire comme les autres.

          Là dessus je suis d'accord. Je ne pense pas que cela favorise l'innovation car il faudrait que quelqu'un avec une approche différente arrive avec un truc bien mieux que ce qu'il se fait actuellement pour arriver à percer (un peu comme à l'époque du glide).
          Mais si on arrive par le bas (ce qui est un peu plus réaliste), on n'a pas le choix et il faut se contenter de suivre.

          • [^] # Re: OpenGL antique

            Posté par (page perso) . Évalué à 6.

            Après, on parle d'optimisation ! C'est sur que si tu n'en as pas besoin, et bien ça peut paraitre lourd à faire de cette manière.

            J'en ai besoin, mais je préfère que le driver s'en charge, car il connaît mieux le GPU que moi! Aujourd'hui, quand tu cherches La bonne façon de faire avec OpenGL, pour la plupart des sujets, il y a trois bonnes façons: celle qui plaît aux GPU intel, celle que préfère les cartes AMD et celle recommandée pour les puces NVIDIA. Et encore je ne fais pas de dev mobile…

            http://devnewton.bci.im

            • [^] # Re: OpenGL antique

              Posté par . Évalué à 2.

              Dans ce ce cas là, vbo + shaders + scenegraph.
              Et surtout, minimiser les changement d'états d'OpenGL !

              Sans rentrer dans l'optimisation par carte (je n'ai jamais eu besoin d'aller jusque là moi, au boulot on a une liste de cartes + drivers officiellement supportés pour les clients, en gros, la plus grosse nvidia à 999999$, pour le reste, ils changent de carte ou ils peuvent courrir… :D), ça fait déjà pas mal la différence.

              Si j'avais un peu plus de temps (et que c'était codé en c++. Désolé, mais il faut aussi que ça m'amuse un peu ;)) je m'en serais vonlontier mêlé un peu ;)

              • [^] # Re: OpenGL antique

                Posté par (page perso) . Évalué à 1.

                et que c'était codé en c++. Désolé, mais il faut aussi que ça m'amuse un peu ;)

                Si tu ne veux pas rejoindre le côté bloated du développement, il y a rewind qui fait un jeu aussi.

                http://devnewton.bci.im

                • [^] # Re: OpenGL antique

                  Posté par . Évalué à 2.

                  C'est ce que j'ai cru comprendre et je me suis à un moment posé la question :)
                  Et je me suis trouvé une autre excellente excuse pour eviter d'entrer dans un projet qui me prendra beaucoup de temps.
                  Reste plus qu'à me souvenir laquelle !

                  (hum.. je suis crédible là ?)

                  • [^] # Re: OpenGL antique

                    Posté par . Évalué à 1.

                    C'est ce que j'ai cru comprendre et je me suis à un moment posé la question :)

                    Tu peux prendre ton temps pour la réponse, je ne vais pas trop vite ;)

                    Et je me suis trouvé une autre excellente excuse pour eviter d'entrer dans un projet qui me prendra beaucoup de temps.

                    Oui et non. Je n'ai pas beaucoup de temps non plus, donc j'essaie d'avancer lentement mais sûrement. J'ai une liste de choses à faire qui s'allonge donc, ça devrait aller pour m'occuper un moment. Si quelqu'un me rejoint à un moment, ça devrait aller avec tous les articles et toute la documentation que j'écris au fur et à mesure.

                    • [^] # Re: OpenGL antique

                      Posté par . Évalué à 2.

                      En fait, c'est plus le projet en lui même qui m'embete.
                      Comme je l'ai déjà écrit dans un message sur une de tes dépêches, j'ai écrit un petit moteur de RPG quand j'étais étudiant qui faisait des trucs sympa. Les graphismes étant honteusement pompés de jeux proprios et libres (secret of mana, the mana world et rpg maker 95)
                      Mais je me suis fait avoir car il me manquait la partie screenbord et plan de ce que je voulais vraiment. Et je sais que là, je n'ai pas plus avancé là dessus.

                      Ce qui me motiverai plus, ça serait un projet plus petit, genre un moteur de defense tower assez customizable pour que les gens puissent faire leur propre lvl et modifiant la difficulté, voir certaines règles de base.
                      Là je serait partant ! Mais l'autre soucis est que je suis très stricte et exigeant sur la qualité du code, du coup ça serait trop chiant de bosser avec moi et je me ferais jeter de la team illico :D

                      • [^] # Re: OpenGL antique

                        Posté par . Évalué à 2.

                        Ce qui me motiverai plus, ça serait un projet plus petit, genre un moteur de defense tower assez customizable pour que les gens puissent faire leur propre lvl et modifiant la difficulté, voir certaines règles de base.

                        Ok, une fois que j'ai fini mon jeu (prévois 2 ans, au bas mot, ça te laisse de la marge), on se fait ça.

                        Mais l'autre soucis est que je suis très stricte et exigeant sur la qualité du code, du coup ça serait trop chiant de bosser avec moi et je me ferais jeter de la team illico :D

                        J'aime beaucoup le beau code et je suis très chiant aussi. Si on a la même chiantitude, ça devrait aller. T'auras qu'à jeter un coup d’œil à mon code pour me dire s'il est sale ou pas selon tes critères.

                        • [^] # Re: OpenGL antique

                          Posté par . Évalué à 2.

                          si tu veux on se fait une séance de code revue un de ces 4 et je te dit ce que j'en pense.
                          Sans trop rentrer dedans ni trop connaitre, ça sera plutôt des considérations esthétiques, mais c'est toujours ça de pris !

                      • [^] # Re: OpenGL antique

                        Posté par (page perso) . Évalué à 2.

                        MCMic a un projet qui pourrait te plaire: http://mcmic.haxx.es/index.php?page=geneticinvasion

                        http://devnewton.bci.im

                        • [^] # Re: OpenGL antique

                          Posté par . Évalué à 3.

                          tu sais que si tu arrives à me faire me lancer dans un projet, je te maudirai jusqu'à la 1392ème génération ?

                          • [^] # Re: OpenGL antique

                            Posté par (page perso) . Évalué à 3.

                            Tu n'es pas obligé de passer tout ton temps dessus. Parfois ajuster un menu, une animation ou un petit effet, ça ajoute une touche pro sans demander trop d'effort.

                            http://devnewton.bci.im

                            • [^] # Re: OpenGL antique

                              Posté par (page perso) . Évalué à 3.

                              Tiens, voilà un rail de coke. Tu n'es pas obligé de le sniffer complètement. Commence maintenant, et tu reviendras le finir plus tard. :-)

            • [^] # Re: OpenGL antique

              Posté par . Évalué à 2.

              C'est pas le rôle des "moteurs 3D" d'abstraire tout ça ?

              "La première sécurité est la liberté"

              • [^] # Re: OpenGL antique

                Posté par . Évalué à 2.

                Oui, mais il y a 2 contres indications que je connais aux "moteurs 3d"

                1) si tu fais un tout petit truc, il faut quand mêem éviter d'utiliser une usine autour pour gêrer le rendu.

                1,5) si tu aimes bien coder et que tu as envie de t'amuser à le faire toi même parce que ça te botte et que tu as envie d'apprendre et de progresser dans le domaine.

                2) si tu as des besoins très spécifiques qui ne sont pas gêrés par un moteur 3d classique (genre beaucoup de rotations)

                Je pense que dans son cas, il est partit de 1) et maintenant il est à 2), tout en ayant passé par l'étape 1,5)

              • [^] # Re: OpenGL antique

                Posté par (page perso) . Évalué à 3.

                Oui, mais c'est un dilemme: est-ce que je prends un moteur 3D pour faire un mon jeu 2D? Ca va tout m'optimiser aux petits oignons, mais je vais devoir embarquer un gros cadriciel genre jmonkey, playn ou libgdx qui ne seront pas packagé dans debian avant 2042.

                http://devnewton.bci.im

                • [^] # Re: OpenGL antique

                  Posté par . Évalué à 6.

                  tu utilises debian !!
                  Je savais que tu étais quelqu'un de bien, malgrès tes déviances java :D

                  • [^] # Re: OpenGL antique

                    Posté par . Évalué à 3.

                    Il est développeur de jeu, c'est forcément quelqu'un de bien ! :P

                • [^] # Re: OpenGL antique

                  Posté par . Évalué à 2.

                  Et personne n'a voulu faire de moteur 3D intermédiaire, un peu comme SDL pour la 2D à une certaine époque ? Les EFL ne sont pas bien ?

                  "La première sécurité est la liberté"

                  • [^] # Re: OpenGL antique

                    Posté par (page perso) . Évalué à 3.

                    Il y a beaucoup des moteurs de jeu ou de toolkits qui essayent de tout faire, mais pratiquement aucun scenegraph 2d simple. Ce qui s'en rapproche le plus aujourd'hui, c'est la SFML et encore…

                    http://devnewton.bci.im

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.