• 【libGDX】使用Mesh绘制三角形


    1 Mesh 和 ShaderProgram 简介

    1.1 创建 Mesh

            1)Mesh 的构造方法

    1. public Mesh(boolean isStatic, int maxVertices, int maxIndices, VertexAttribute... attributes)
    2. public Mesh(boolean isStatic, int maxVertices, int maxIndices, VertexAttributes attributes)
    • isStatic:网格是否是静态的,如果网格数据不经常改动,设置为静态的可以优化性能;
    • maxVertices:顶点最大个数;
    • maxIndices:三角形顶点索引最大个数;
    • attributes:顶点属性,主要包含:位置、颜色、法线、纹理坐标等。

            2)VertexAttribute 的构造方法

    public VertexAttribute(int usage, int numComponents, String alias)
    • usage:顶点属性编号;
    • numComponents:该属性的维度;
    • alias:属性别名,在 Shader 中会用到该别名,建议以 “a_” 开头,如:a_position。

            3)网格创建实例

    1. private void initMesh() { // 初始化网格
    2. float[] vertices = {...}; // 顶点序列
    3. short[] indices = {...}; // 三角形顶点索引
    4. VertexAttribute vertexAttr = new VertexAttribute(Usage.Position, 3, "a_position");
    5. mMesh = new Mesh(true, vertices.length / 3, indices.length, vertexAttr);
    6. mMesh.setVertices(vertices);
    7. mMesh.setIndices(indices);
    8. }

    1.2 绘制 Mesh

            1)Mesh 的 render 方法

    1. public void render(ShaderProgram shader, int primitiveType)
    2. public void render(ShaderProgram shader, int primitiveType, int offset, int count)
    • shader:shader 程序;
    • primitiveType:图元类型,即:点(GL_POINTS)、线(GL_LINES、GL_LINE_LOOP、GL_LINE_STRIP)、面(GL_TRIANGLES、GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN);
    • offset:顶点数据偏移,通常取 0.
    • count:顶点个数。

            2)图元类型(primitiveType) 

            对于线段类型图元,输入顶点序列 abcdef,根据图元类型,组装成的线段如下:

            对于三角形类型图元,输入顶点序列 abcdef,根据图元类型,组装成的三角形如下:

    1.3 ShaderProgram 简介

            1)绑定和释放着色器程序

    1. // 开始渲染(已过时, 内部直接调用bind, 因此可以使用bind方法替换begin方法)
    2. public void begin()
    3. // 绑定着色器程序, 内部调用: gl.glUseProgram(program)
    4. public void bind()
    5. // 结束渲染(已过时, 内部是空实现, 因此可以不调用end方法)
    6. public void end()
    7. // 释放资源
    8. public void dispose()

            2)设置着色器程序参数

    1. // 设置整型Uniform变量
    2. public void setUniformi(String name, int value)
    3. // 设置二维整型Uniform向量
    4. public void setUniformi(String name, int value1, int value2)
    5. // 设置三维整型Uniform向量
    6. public void setUniformi(String name, int value1, int value2, int value3)
    7. // 设置四维整型Uniform向量
    8. public void setUniformi(String name, int value1, int value2, int value3, int value4)
    9. // 设置浮点型Uniform变量
    10. public void setUniformf(String name, float value)
    11. public void setUniform1fv(String name, float[] values, int offset, int length)
    12. // 设置vec2型Uniform变量
    13. public void setUniform2fv(String name, float[] values, int offset, int length)
    14. public void setUniformf(String name, float value1, float value2)
    15. public void setUniformf(String name, Vector2 values)
    16. // 设置vec3型Uniform变量
    17. public void setUniform3fv(String name, float[] values, int offset, int length)
    18. public void setUniformf(String name, float value1, float value2, float value3)
    19. public void setUniformf(String name, Vector3 values)
    20. // 设置vec4型Uniform变量
    21. public void setUniform4fv(String name, float[] values, int offset, int length)
    22. public void setUniformf(String name, float value1, float value2, float value3, float value4)
    23. public void setUniformf(String name, Color values)
    24. // 设置三维Uniform矩阵
    25. public void setUniformMatrix(String name, Matrix3 matrix)
    26. // 设置四维Uniform矩阵
    27. public void setUniformMatrix(String name, Matrix4 matrix)

            说明:name 可以使用 int 型的 location 变量替换,在 VertexAttributes.Usage 中有定义,如下。

    1. public static final class Usage {
    2. public static final int Position = 1;
    3. public static final int ColorUnpacked = 2;
    4. public static final int ColorPacked = 4;
    5. public static final int Normal = 8;
    6. public static final int TextureCoordinates = 16;
    7. public static final int Generic = 32;
    8. public static final int BoneWeight = 64;
    9. public static final int Tangent = 128;
    10. public static final int BiNormal = 256;
    11. }

    2 绘制三角形

    2.1 绘制纯色三角形

            DesktopLauncher.java

    1. package com.zhyan8.game;
    2. import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;
    3. import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
    4. import com.zhyan8.game.Plane;
    5. public class DesktopLauncher {
    6. public static void main (String[] arg) {
    7. Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
    8. config.setForegroundFPS(60);
    9. config.setTitle("Triangle");
    10. new Lwjgl3Application(new Triangle(), config);
    11. }
    12. }

            Triangle.java

    1. package com.zhyan8.game;
    2. import com.badlogic.gdx.ApplicationAdapter;
    3. import com.badlogic.gdx.Gdx;
    4. import com.badlogic.gdx.graphics.GL30;
    5. import com.badlogic.gdx.graphics.Mesh;
    6. import com.badlogic.gdx.graphics.VertexAttribute;
    7. import com.badlogic.gdx.graphics.VertexAttributes.Usage;
    8. import com.badlogic.gdx.graphics.glutils.ShaderProgram;
    9. public class Triangle extends ApplicationAdapter {
    10. private ShaderProgram mShaderProgram;
    11. private Mesh mMesh;
    12. @Override
    13. public void create() {
    14. initShader();
    15. initMesh();
    16. }
    17. @Override
    18. public void render() {
    19. Gdx.gl.glClearColor(0.455f, 0.725f, 1.0f, 1.0f);
    20. Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
    21. // mShaderProgram.begin(); // 已过时, 请使用bind方法替换
    22. mShaderProgram.bind();
    23. mMesh.render(mShaderProgram, GL30.GL_TRIANGLES);
    24. //mShaderProgram.end(); // 已过时, 可以去掉
    25. }
    26. @Override
    27. public void dispose() {
    28. mShaderProgram.dispose();
    29. mMesh.dispose();
    30. }
    31. private void initShader() { // 初始化着色器程序
    32. String vertex = Gdx.files.internal("shaders/triangle_vertex.glsl").readString();
    33. String fragment = Gdx.files.internal("shaders/triangle_fragment.glsl").readString();
    34. mShaderProgram = new ShaderProgram(vertex, fragment);
    35. }
    36. private void initMesh() { // 初始化网格
    37. float[] vertices = {
    38. -0.5f, -0.5f, 0.0f,
    39. 0.5f, -0.5f, 0.0f,
    40. 0.0f, 0.5f, 0.0f
    41. };
    42. short[] indices = {0, 1, 2};
    43. VertexAttribute vertexAttr = new VertexAttribute(Usage.Position, 3, "a_position");
    44. mMesh = new Mesh(true, vertices.length / 3, indices.length, vertexAttr);
    45. mMesh.setVertices(vertices);
    46. mMesh.setIndices(indices);
    47. }
    48. }

            triangle_vertex.glsl

    1. #version 300 es
    2. in vec3 a_position;
    3. void main() {
    4. gl_Position = vec4(a_position, 1.0);
    5. }

            说明:triangle_vertex.glsl 文件放在【assets / shaders】目录下面。

            triangle_fragment.glsl

    1. #version 300 es
    2. precision mediump float; // 声明float型变量的精度为mediump
    3. out vec4 fragColor;
    4. void main() {
    5. fragColor = vec4(1, 0, 0, 1);
    6. }

            说明:triangle_fragment.glsl 文件放在【assets / shaders】目录下面。 

            运行效果如下。

    2.2 绘制彩色三角形

            Triangle.java

    1. package com.zhyan8.game;
    2. import com.badlogic.gdx.ApplicationAdapter;
    3. import com.badlogic.gdx.Gdx;
    4. import com.badlogic.gdx.graphics.GL30;
    5. import com.badlogic.gdx.graphics.Mesh;
    6. import com.badlogic.gdx.graphics.VertexAttribute;
    7. import com.badlogic.gdx.graphics.VertexAttributes.Usage;
    8. import com.badlogic.gdx.graphics.glutils.ShaderProgram;
    9. public class Triangle extends ApplicationAdapter {
    10. private ShaderProgram mShaderProgram;
    11. private Mesh mMesh;
    12. @Override
    13. public void create() {
    14. initShader();
    15. initMesh();
    16. }
    17. @Override
    18. public void render() {
    19. Gdx.gl.glClearColor(0.455f, 0.725f, 1.0f, 1.0f);
    20. Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
    21. // mShaderProgram.begin(); // 已过时, 请使用bind方法替换
    22. mShaderProgram.bind();
    23. mMesh.render(mShaderProgram, GL30.GL_TRIANGLES);
    24. //mShaderProgram.end(); // 已过时, 可以去掉
    25. }
    26. @Override
    27. public void dispose() {
    28. mShaderProgram.dispose();
    29. mMesh.dispose();
    30. }
    31. private void initShader() { // 初始化着色器程序
    32. String vertex = Gdx.files.internal("shaders/triangle_vertex.glsl").readString();
    33. String fragment = Gdx.files.internal("shaders/triangle_fragment.glsl").readString();
    34. mShaderProgram = new ShaderProgram(vertex, fragment);
    35. }
    36. private void initMesh() { // 初始化网格
    37. float[] vertices = {
    38. // 前3位是顶点位置数据, 后4位是顶点颜色数据
    39. -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
    40. 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
    41. 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f
    42. };
    43. short[] indices = {0, 1, 2};
    44. VertexAttribute vertexPosition = new VertexAttribute(Usage.Position, 3, "a_position");
    45. VertexAttribute vertexColor = new VertexAttribute(Usage.ColorUnpacked, 4, "a_color");
    46. mMesh = new Mesh(true, vertices.length / 7, indices.length, vertexPosition, vertexColor);
    47. mMesh.setVertices(vertices);
    48. mMesh.setIndices(indices);
    49. }
    50. }

            triangle_vertex.glsl

    1. #version 300 es
    2. in vec3 a_position;
    3. in vec4 a_color;
    4. out vec4 v_color;
    5. void main() {
    6. gl_Position = vec4(a_position, 1.0);
    7. v_color = a_color;
    8. }

            triangle_fragment.glsl

    1. #version 300 es
    2. precision mediump float; // 声明float型变量的精度为mediump
    3. in vec4 v_color;
    4. out vec4 fragColor;
    5. void main() {
    6. fragColor = v_color;
    7. }

            运行效果如下。 

     2.3 三角形宽高比适配

            本节通过引入相机,使得绘制后的三角形宽高比与三角形模型的宽高比一致。 

            Triangle.java

    1. package com.zhyan8.game;
    2. import com.badlogic.gdx.ApplicationAdapter;
    3. import com.badlogic.gdx.Gdx;
    4. import com.badlogic.gdx.graphics.GL30;
    5. import com.badlogic.gdx.graphics.Mesh;
    6. import com.badlogic.gdx.graphics.OrthographicCamera;
    7. import com.badlogic.gdx.graphics.VertexAttribute;
    8. import com.badlogic.gdx.graphics.VertexAttributes.Usage;
    9. import com.badlogic.gdx.graphics.glutils.ShaderProgram;
    10. public class Triangle extends ApplicationAdapter {
    11. private OrthographicCamera mCamera;
    12. private ShaderProgram mShaderProgram;
    13. private Mesh mMesh;
    14. @Override
    15. public void create() {
    16. initCamera();
    17. initShader();
    18. initMesh();
    19. }
    20. @Override
    21. public void render() {
    22. Gdx.gl.glClearColor(0.455f, 0.725f, 1.0f, 1.0f);
    23. Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
    24. // mShaderProgram.begin(); // 已过时, 请使用bind方法替换
    25. mShaderProgram.bind();
    26. mShaderProgram.setUniformMatrix("u_projectionViewMatrix", mCamera.combined);
    27. mMesh.render(mShaderProgram, GL30.GL_TRIANGLES);
    28. //mShaderProgram.end(); // 已过时, 可以去掉
    29. }
    30. @Override
    31. public void dispose() {
    32. mShaderProgram.dispose();
    33. mMesh.dispose();
    34. }
    35. private void initCamera() {
    36. mCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    37. mCamera.near = 0.3f;
    38. mCamera.far = 1000f;
    39. mCamera.zoom = 0.005f; // 相机缩放级别, 值越大观察范围越大, 看到的图形越小
    40. mCamera.position.set(0f, 0f, -5f);
    41. mCamera.lookAt(0, 0, 0);
    42. mCamera.update();
    43. }
    44. private void initShader() { // 初始化着色器程序
    45. String vertex = Gdx.files.internal("shaders/triangle_vertex.glsl").readString();
    46. String fragment = Gdx.files.internal("shaders/triangle_fragment.glsl").readString();
    47. mShaderProgram = new ShaderProgram(vertex, fragment);
    48. }
    49. private void initMesh() { // 初始化网格
    50. float[] vertices = {
    51. -0.5f, -0.5f, 0.0f,
    52. 0.5f, -0.5f, 0.0f,
    53. 0.0f, 0.5f, 0.0f,
    54. };
    55. short[] indices = {0, 1, 2};
    56. VertexAttribute vertexPosition = new VertexAttribute(Usage.Position, 3, "a_position");
    57. mMesh = new Mesh(true, vertices.length / 3, indices.length, vertexPosition);
    58. mMesh.setVertices(vertices);
    59. mMesh.setIndices(indices);
    60. }
    61. }

            说明:这里设置的三角形底边和高都为 1,即宽高比为 1: 1,我们期望绘制后的三角形宽高比也是 1 : 1,这时就需要通过相机进行变换。

            triangle_vertex.glsl

    1. #version 300 es
    2. in vec3 a_position;
    3. uniform mat4 u_projectionViewMatrix;
    4. void main() {
    5. gl_Position = u_projectionViewMatrix * vec4(a_position, 1.0);
    6. }

            说明:这里通过正交相机的观察矩阵和投影矩阵变换,实现模型宽高比的适配,也可以对输入坐标的 y 值乘以屏幕宽高比,作为 gl_Position.y 的值。

            triangle_fragment.glsl

    1. #version 300 es
    2. precision mediump float; // 声明float型变量的精度为mediump
    3. out vec4 fragColor;
    4. void main() {
    5. fragColor = vec4(0, 1, 0, 0);
    6. }

            运行效果如下,可以看到,绘制后的三角形宽高比也是 1 : 1。

  • 相关阅读:
    小白怎么搭建自己的公众号题库系统?
    C++(17):模板嵌套类的.template及::template
    商业智能BI
    2013-2020年全国31省数字经济数据集
    概述UVM中的build、configure和connect【uvm】
    vue面试题汇总
    Spring源码深度解析:七、bean的加载① - doGetBean概述
    一种自动化九点标定工具原理(包涵部分源码)
    webpack自定义loader
    【算法挨揍日记】day08——30. 串联所有单词的子串、76. 最小覆盖子串
  • 原文地址:https://blog.csdn.net/m0_37602827/article/details/134521380