Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (539)
Games in Android Showcase (132)
games submitted by our members
Games in WIP (603)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Fast and easy projection matrix for 2d only rendering?  (Read 2815 times)
0 Members and 1 Guest are viewing this topic.
Offline Mac70
« Posted 2013-02-21 19:27:09 »

Like in topic. Is there any way to make fast and easy to use projection matrix only for 2d? Currently this is my code for projection matrix:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
public Matrix4f perspectiveMatrix(int width, int height, float FOV, float near, float far) {
        Matrix4f matrix = new Matrix4f();
       
        float fieldOfView = FOV;
        float aspectRatio = (float)width / (float)height;
        float near_plane = near;
        float far_plane = far;

        float y_scale = this.coTangent(this.degreesToRadians(fieldOfView / 2f));
        float x_scale = y_scale / aspectRatio;
        float frustum_length = far_plane - near_plane;

        matrix.m00 = x_scale;
        matrix.m11 = y_scale;
        matrix.m22 = -((far_plane + near_plane) / frustum_length);
        matrix.m23 = -1;
        matrix.m32 = -((2 * near_plane * far_plane) / frustum_length);
       
        return matrix;
    }


The best matrix should have/be:
-easy coordinates system - above code in resolution 800X600 and FOV 60 is rendering values in ranges which are really hard to manage in 2d game. Best possible coordinate system should be width/height in x and 1 in y.
-fast - I need to render 5000+ quads with textures, scale and rotation - currently this amount of quads rendered on screen (random positions, scaling and rotations) is increasing my GPU load to about 95-100%

Also, are there more optimalizations for 2d possible?

Check out my Devblog! Smiley
Offline matheus23

JGO Kernel


Medals: 114
Projects: 3


You think about my Avatar right now!


« Reply #1 - Posted 2013-02-21 19:41:42 »

Well, as the name of the perspective Matrix already says, it's perspective. That means, the objects close to the viewer seem to be bigger than the objects more far away. Even more: It means the room is projected onto the viewer's viewing plane (in this case the Framebuffer / PC screen) in the form of a trapeze / Cone.

The matrix you have there is a matrix used in 3D games.

What you want is an orthogonal matrix. Look at the libgdx code directly from "Matrix4" for example:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
/** Sets the matrix to an orthographic projection like glOrtho (http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml) following
 * the OpenGL equivalent
 *
 * @param left The left clipping plane
 * @param right The right clipping plane
 * @param bottom The bottom clipping plane
 * @param top The top clipping plane
 * @param near The near clipping plane
 * @param far The far clipping plane
 * @return This matrix for the purpose of chaining methods together. */

public Matrix4 setToOrtho (float left, float right, float bottom, float top, float near, float far) {
   this.idt();
   float x_orth = 2 / (right - left);
   float y_orth = 2 / (top - bottom);
   float z_orth = -2 / (far - near);

   float tx = -(right + left) / (right - left);
   float ty = -(top + bottom) / (top - bottom);
   float tz = -(far + near) / (far - near);

   val[M00] = x_orth;
   val[M10] = 0;
   val[M20] = 0;
   val[M30] = 0;
   val[M01] = 0;
   val[M11] = y_orth;
   val[M21] = 0;
   val[M31] = 0;
   val[M02] = 0;
   val[M12] = 0;
   val[M22] = z_orth;
   val[M32] = 0;
   val[M03] = tx;
   val[M13] = ty;
   val[M23] = tz;
   val[M33] = 1;

   return this;
}

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline Mac70
« Reply #2 - Posted 2013-02-21 20:09:49 »

I have tried to implement this matrix, but it doesn't work for me. Am I doing anything wrong?

I have changed this function into:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
public Matrix4f orthoMatrix(float left, float right, float bottom, float top, float near, float far) {
        Matrix4f matrix = new Matrix4f();
        float x_orth = 2 / (right - left);
        float y_orth = 2 / (top - bottom);
        float z_orth = -2 / (far - near);

        float tx = -(right + left) / (right - left);
        float ty = -(top + bottom) / (top - bottom);
        float tz = -(far + near) / (far - near);

        matrix.m00 = x_orth;
        matrix.m10 = 0;
        matrix.m20 = 0;
        matrix.m30 = 0;
        matrix.m01 = 0;
        matrix.m11 = y_orth;
        matrix.m21 = 0;
        matrix.m31 = 0;
        matrix.m02 = 0;
        matrix.m12 = 0;
        matrix.m22 = z_orth;
        matrix.m32 = 0;
        matrix.m03 = tx;
        matrix.m13 = ty;
        matrix.m23 = tz;
        matrix.m33 = 1;

        return matrix;
    }


Matrix initialization (screen resolution - 800X600):

1  
projectionMatrix = gCore.matrix.orthoMatrix(-400, 400, -300, 300, 0.1f, 1.1f);


Rendering (I am using scaleCoords and scaleScale functions to be able to input more programmer-friendly values, currently from range 0;100):

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
public void startDrawing() {
        GL20.glUseProgram(activeProgram);
       
        GL30.glBindVertexArray(vaoId);
        GL20.glEnableVertexAttribArray(0);
        GL20.glEnableVertexAttribArray(1);
        GL20.glEnableVertexAttribArray(2);

        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId);
    }
   
    public void render(int texture, int shader, float x, float y, float scalex, float scaley, float angle) {
        x = scaleCoords(x);
        y = scaleCoords(y);
        scalex = scaleScale(scalex);
        scaley = scaleScale(scaley);
        if (shader!=activeProgram) {
            GL20.glUseProgram(shader);
            projectionMatrixLocation = GL20.glGetUniformLocation(shader, "projectionMatrix");
            viewMatrixLocation = GL20.glGetUniformLocation(shader, "viewMatrix");
            modelMatrixLocation = GL20.glGetUniformLocation(shader, "modelMatrix");
            activeProgram = shader;
        }

        modelAngle.z = angle;
        modelPos.x = x;
        modelPos.y = y;
       
        modelScale.x = scalex;
        modelScale.y = scaley;
       
        viewMatrix = new Matrix4f();
        modelMatrix = new Matrix4f();

        Matrix4f.translate(cameraPos, viewMatrix, viewMatrix);
       
        Matrix4f.translate(modelPos, modelMatrix, modelMatrix);
        Matrix4f.scale(modelScale, modelMatrix, modelMatrix);
        Matrix4f.rotate(this.degreesToRadians(modelAngle.z), new Vector3f(0, 0, 1), modelMatrix, modelMatrix);
        //Matrix4f.rotate(this.degreesToRadians(modelAngle.y), new Vector3f(0, 1, 0), modelMatrix, modelMatrix);
        //Matrix4f.rotate(this.degreesToRadians(modelAngle.x), new Vector3f(1, 0, 0), modelMatrix, modelMatrix);
       
        projectionMatrix.store(matrix44Buffer); matrix44Buffer.flip();
        GL20.glUniformMatrix4(projectionMatrixLocation, false, matrix44Buffer);
        viewMatrix.store(matrix44Buffer); matrix44Buffer.flip();
        GL20.glUniformMatrix4(viewMatrixLocation, false, matrix44Buffer);
        modelMatrix.store(matrix44Buffer); matrix44Buffer.flip();
        GL20.glUniformMatrix4(modelMatrixLocation, false, matrix44Buffer);
       
        if (texture!=activeTexture) {
            GL13.glActiveTexture(GL13.GL_TEXTURE0);
            GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
            activeTexture = texture;
        }

        GL11.glDrawElements(GL11.GL_TRIANGLES, indicesCount, GL11.GL_UNSIGNED_BYTE, 0);
    }
   
    public void endRendering() {
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
        GL20.glDisableVertexAttribArray(0);
        GL20.glDisableVertexAttribArray(1);
        GL20.glDisableVertexAttribArray(2);
        GL30.glBindVertexArray(0);

        GL20.glUseProgram(0);
    }

    private float scaleCoords(float scale) {
        if (scale!=0) {
            scale=scale/50;
        }
        scale--;
        return scale;
    }
   
    private float scaleScale(float scale) {
        if (scale!=0) {
            scale=scale/50;
        }
        return scale;
    }

Check out my Devblog! Smiley
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline matheus23

JGO Kernel


Medals: 114
Projects: 3


You think about my Avatar right now!


« Reply #3 - Posted 2013-02-21 20:18:43 »

What doesn't work for you? What's wrong? Isn't it rendering? Does it look skewed?

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline Mac70
« Reply #4 - Posted 2013-02-21 20:24:25 »

I see only black (LWJGL default) screen and nothing more. Any render values which are working perfectly in perspective matrix does not work in ortho matrix.

Check out my Devblog! Smiley
Offline davedes
« Reply #5 - Posted 2013-02-21 20:27:58 »

Here is what lwjgl-basics uses for 2D ortho matrix:
https://github.com/mattdesl/lwjgl-basics/blob/master/src/mdesl/util/MathUtil.java

Basically modified from LibGDX.

Offline Mac70
« Reply #6 - Posted 2013-02-21 20:40:42 »

Isn't this almost the same code?

I am trying to find any solutions how to make this ortho work (I don't know where is the problem - in my rendering or in matrix itself), but there is lack of (good) ortho matrix tutorials in the Internet. It seems that the only hope is in you. Smiley

Check out my Devblog! Smiley
Offline davedes
« Reply #7 - Posted 2013-02-21 20:55:35 »

Yup, looks about the same.

Can't really be of any help, since there are many things that could cause this problem. It's hard to read and debug GL code when you mash it all into a single class.

Offline Mac70
« Reply #8 - Posted 2013-02-21 21:33:03 »

It seems that the best solution is... Removing the whole projection matrix and leave only view and model matrixes, then scalling x in this way: wanted_scale/(game_width/game_height). Can I do the same using projection matrix?

Check out my Devblog! Smiley
Offline loom_weaver

JGO Coder


Medals: 17



« Reply #9 - Posted 2013-02-22 01:35:26 »

FWIW this is what I do to enter/exit '2D mode'.  0,0 is the top-left corner and coordinates are pixel counts.

UIComponent.is2D is a global variable initially set to false.

Scala:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
  /**
   * Call before drawing 2D elements on the glCanvas.
   */

  protected def toggleOn2D() {
    if (!UIComponent.is2D) {
      val viewport: IntBuffer = BufferUtils.createIntBuffer(16)

      glGetInteger(GL_VIEWPORT, viewport)

      glMatrixMode(GL_PROJECTION)
      glPushMatrix()
      glLoadIdentity()

      glOrtho(viewport.get(0), viewport.get(0)+viewport.get(2), viewport.get(1), viewport.get(1)+viewport.get(3), -1, 1)
      glMatrixMode(GL_MODELVIEW)
      glPushMatrix()
      glLoadIdentity()
      glTranslated(0.375, 0.375, 0.0)  // slight transition for exact pixel positioning

      glPushAttrib(GL_DEPTH_BUFFER_BIT)
      glDisable(GL_DEPTH_TEST)

      UIComponent.is2D = true
    }
  }

  /**
   * Call before drawing 3D elements on the glCanvas or doing 3D calculations
   * involving the projection matrix.
   */

  protected def toggleOff2D() {
    if (UIComponent.is2D) {
      glPopAttrib()
      glMatrixMode(GL_PROJECTION)
      glPopMatrix()
      glMatrixMode(GL_MODELVIEW)
      glPopMatrix()

      UIComponent.is2D = false
    }
  }
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Mac70
« Reply #10 - Posted 2013-02-22 08:18:22 »

This is 'old' OpenGL way.

Is there any sense to add projection matrix if setting viewpoint to (height, height) and calculating aspect ratio (for things like interface rendering which must be always displayed in the fixed place on screen) works well?

Check out my Devblog! Smiley
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

rwatson462 (30 views)
2014-12-15 09:26:44

Mr.CodeIt (22 views)
2014-12-14 19:50:38

BurntPizza (43 views)
2014-12-09 22:41:13

BurntPizza (77 views)
2014-12-08 04:46:31

JscottyBieshaar (38 views)
2014-12-05 12:39:02

SHC (52 views)
2014-12-03 16:27:13

CopyableCougar4 (50 views)
2014-11-29 21:32:03

toopeicgaming1999 (116 views)
2014-11-26 15:22:04

toopeicgaming1999 (106 views)
2014-11-26 15:20:36

toopeicgaming1999 (32 views)
2014-11-26 15:20:08
Resources for WIP games
by kpars
2014-12-18 10:26:14

Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!