【libGDX】使用Mesh繪制三角形

1 Mesh 和 ShaderProgram 簡(jiǎn)介

1.1 創(chuàng)建 Mesh

1)Mesh 的構(gòu)造方法

public Mesh(boolean isStatic, int maxVertices, int maxIndices, VertexAttribute... attributes)
public Mesh(boolean isStatic, int maxVertices, int maxIndices, VertexAttributes attributes)
  • isStatic:網(wǎng)格是否是靜態(tài)的蓖墅,如果網(wǎng)格數(shù)據(jù)不經(jīng)常改動(dòng),設(shè)置為靜態(tài)的可以優(yōu)化性能躲撰;
  • maxVertices:頂點(diǎn)最大個(gè)數(shù);
  • maxIndices:三角形頂點(diǎn)索引最大個(gè)數(shù)昆禽;
  • attributes:頂點(diǎn)屬性茬缩,主要包含:位置卿拴、顏色、法線梨与、紋理坐標(biāo)等堕花。

2)VertexAttribute 的構(gòu)造方法

public VertexAttribute(int usage, int numComponents, String alias)
  • usage:頂點(diǎn)屬性編號(hào);
  • numComponents:該屬性的維度粥鞋;
  • alias:屬性別名缘挽,在 Shader 中會(huì)用到該別名,建議以 “a_” 開頭呻粹,如:a_position壕曼。

3)網(wǎng)格創(chuàng)建實(shí)例

private void initMesh() { // 初始化網(wǎng)格
    float[] vertices = {...}; // 頂點(diǎn)序列
    short[] indices = {...}; // 三角形頂點(diǎn)索引
    VertexAttribute vertexAttr = new VertexAttribute(Usage.Position, 3, "a_position");
    mMesh = new Mesh(true, vertices.length / 3, indices.length, vertexAttr);
    mMesh.setVertices(vertices);
    mMesh.setIndices(indices);
}

1.2 繪制 Mesh

1)Mesh 的 render 方法

public void render(ShaderProgram shader, int primitiveType)
public void render(ShaderProgram shader, int primitiveType, int offset, int count)
  • shader:著色器程序;
  • primitiveType:圖元類型等浊,即:點(diǎn)(GL_POINTS)腮郊、線(GL_LINES、GL_LINE_LOOP筹燕、GL_LINE_STRIP)伴榔、面(GL_TRIANGLES、GL_TRIANGLE_STRIP庄萎、GL_TRIANGLE_FAN)踪少;
  • offset:頂點(diǎn)數(shù)據(jù)偏移,通常取 0.
  • count:頂點(diǎn)個(gè)數(shù)糠涛。

2)圖元類型(primitiveType)

對(duì)于線段類型圖元援奢,輸入頂點(diǎn)序列 abcdef,根據(jù)圖元類型忍捡,組裝成的線段如下:

對(duì)于三角形類型圖元集漾,輸入頂點(diǎn)序列 abcdef,根據(jù)圖元類型砸脊,組裝成的三角形如下:

1.3 ShaderProgram 簡(jiǎn)介

1)綁定和釋放著色器程序

// 開始渲染(已過(guò)時(shí), 內(nèi)部直接調(diào)用bind, 因此可以使用bind方法替換begin方法)
public void begin()
// 綁定著色器程序, 內(nèi)部調(diào)用: gl.glUseProgram(program)
public void bind()
// 結(jié)束渲染(已過(guò)時(shí), 內(nèi)部是空實(shí)現(xiàn), 因此可以不調(diào)用end方法)
public void end()
// 釋放資源
public void dispose()

2)設(shè)置著色器程序參數(shù)

// 設(shè)置整型Uniform變量
public void setUniformi(String name, int value)
// 設(shè)置二維整型Uniform向量
public void setUniformi(String name, int value1, int value2)
// 設(shè)置三維整型Uniform向量
public void setUniformi(String name, int value1, int value2, int value3)
// 設(shè)置四維整型Uniform向量
public void setUniformi(String name, int value1, int value2, int value3, int value4)
// 設(shè)置浮點(diǎn)型Uniform變量
public void setUniformf(String name, float value)
public void setUniform1fv(String name, float[] values, int offset, int length)
// 設(shè)置vec2型Uniform變量
public void setUniform2fv(String name, float[] values, int offset, int length)
public void setUniformf(String name, float value1, float value2)
public void setUniformf(String name, Vector2 values)
// 設(shè)置vec3型Uniform變量
public void setUniform3fv(String name, float[] values, int offset, int length)
public void setUniformf(String name, float value1, float value2, float value3)
public void setUniformf(String name, Vector3 values)
// 設(shè)置vec4型Uniform變量
public void setUniform4fv(String name, float[] values, int offset, int length)
public void setUniformf(String name, float value1, float value2, float value3, float value4)
public void setUniformf(String name, Color values)
// 設(shè)置三維Uniform矩陣
public void setUniformMatrix(String name, Matrix3 matrix)
// 設(shè)置四維Uniform矩陣
public void setUniformMatrix(String name, Matrix4 matrix)

說(shuō)明:name 可以使用 int 型的 location 變量替換具篇,在 VertexAttributes.Usage 中有定義,如下凌埂。

public static final class Usage {
    public static final int Position = 1;
    public static final int ColorUnpacked = 2;
    public static final int ColorPacked = 4;
    public static final int Normal = 8;
    public static final int TextureCoordinates = 16;
    public static final int Generic = 32;
    public static final int BoneWeight = 64;
    public static final int Tangent = 128;
    public static final int BiNormal = 256;
}

2 繪制三角形

本節(jié)將使用 Mesh驱显、ShaderProgram、Shader 繪制三角形瞳抓,OpenGL ES 的實(shí)現(xiàn)見博客 → 繪制三角形埃疫、繪制彩色三角形,本節(jié)完整代碼資源見 → 使用Mesh繪制三角形孩哑。

2.1 繪制純色三角形

DesktopLauncher.java

package com.zhyan8.game;

import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;

public class DesktopLauncher {
    public static void main (String[] arg) {
        Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
        config.setForegroundFPS(60);
        config.setTitle("Triangle");
        new Lwjgl3Application(new Triangle(), config);
    }
}

Triangle.java

package com.zhyan8.game;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL30;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;

public class Triangle extends ApplicationAdapter {
    private ShaderProgram mShaderProgram;
    private Mesh mMesh;

    @Override
    public void create() {
        initShader();
        initMesh();
    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(0.455f, 0.725f, 1.0f, 1.0f);
        Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
        // mShaderProgram.begin(); // 已過(guò)時(shí), 請(qǐng)使用bind方法替換
        mShaderProgram.bind();
        mMesh.render(mShaderProgram, GL30.GL_TRIANGLES);
        // mShaderProgram.end(); // 已過(guò)時(shí), 可以去掉
    }

    @Override
    public void dispose() {
        mShaderProgram.dispose();
        mMesh.dispose();
    }

    private void initShader() { // 初始化著色器程序
        String vertex = Gdx.files.internal("shaders/triangle_vertex.glsl").readString();
        String fragment = Gdx.files.internal("shaders/triangle_fragment.glsl").readString();
        mShaderProgram = new ShaderProgram(vertex, fragment);
    }

    private void initMesh() { // 初始化網(wǎng)格
        float[] vertices = {
            -0.5f, -0.5f, 0.0f,
            0.5f, -0.5f, 0.0f,
            0.0f, 0.5f, 0.0f
        };
        short[] indices = {0, 1, 2};
        VertexAttribute vertexAttr = new VertexAttribute(Usage.Position, 3, "a_position");
        mMesh = new Mesh(true, vertices.length / 3, indices.length, vertexAttr);
        mMesh.setVertices(vertices);
        mMesh.setIndices(indices);
    }
}

triangle_vertex.glsl

#version 300 es

in vec3 a_position;

void main() {
    gl_Position = vec4(a_position, 1.0);
}

說(shuō)明:triangle_vertex.glsl 文件放在【assets / shaders】目錄下面栓霜。

triangle_fragment.glsl

#version 300 es
precision mediump float; // 聲明float型變量的精度為mediump

out vec4 fragColor;

void main() {
    fragColor = vec4(1, 0, 0, 1);
}

說(shuō)明:triangle_fragment.glsl 文件放在【assets / shaders】目錄下面。

運(yùn)行效果如下横蜒。

2.2 繪制彩色三角形

Triangle.java

package com.zhyan8.game;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL30;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;

public class Triangle extends ApplicationAdapter {
    private ShaderProgram mShaderProgram;
    private Mesh mMesh;

    @Override
    public void create() {
        initShader();
        initMesh();
    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(0.455f, 0.725f, 1.0f, 1.0f);
        Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
        // mShaderProgram.begin(); // 已過(guò)時(shí), 請(qǐng)使用bind方法替換
        mShaderProgram.bind();
        mMesh.render(mShaderProgram, GL30.GL_TRIANGLES);
        // mShaderProgram.end(); // 已過(guò)時(shí), 可以去掉
    }

    @Override
    public void dispose() {
        mShaderProgram.dispose();
        mMesh.dispose();
    }

    private void initShader() { // 初始化著色器程序
        String vertex = Gdx.files.internal("shaders/triangle_vertex.glsl").readString();
        String fragment = Gdx.files.internal("shaders/triangle_fragment.glsl").readString();
        mShaderProgram = new ShaderProgram(vertex, fragment);
    }

    private void initMesh() { // 初始化網(wǎng)格
        float[] vertices = {
            // 前3位是頂點(diǎn)位置數(shù)據(jù), 后4位是頂點(diǎn)顏色數(shù)據(jù)
            -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
            0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
            0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f
        };
        short[] indices = {0, 1, 2};
        VertexAttribute vertexPosition = new VertexAttribute(Usage.Position, 3, "a_position");
        VertexAttribute vertexColor = new VertexAttribute(Usage.ColorUnpacked, 4, "a_color");
        mMesh = new Mesh(true, vertices.length / 7, indices.length, vertexPosition, vertexColor);
        mMesh.setVertices(vertices);
        mMesh.setIndices(indices);
    }
}

triangle_vertex.glsl

#version 300 es

in vec3 a_position;
in vec4 a_color;

out vec4 v_color;

void main() {
    gl_Position = vec4(a_position, 1.0);
    v_color = a_color;
}

triangle_fragment.glsl

#version 300 es
precision mediump float; // 聲明float型變量的精度為mediump

in vec4 v_color;

out vec4 fragColor;

void main() {
    fragColor = v_color;
}

運(yùn)行效果如下胳蛮。

2.3 三角形寬高比適配

本節(jié)通過(guò)引入相機(jī)销凑,使得繪制后的三角形寬高比與三角形模型的寬高比一致。

Triangle.java

package com.zhyan8.game;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL30;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;

public class Triangle extends ApplicationAdapter {
    private OrthographicCamera mCamera;
    private ShaderProgram mShaderProgram;
    private Mesh mMesh;

    @Override
    public void create() {
        initCamera();
        initShader();
        initMesh();
    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(0.455f, 0.725f, 1.0f, 1.0f);
        Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
        // mShaderProgram.begin(); // 已過(guò)時(shí), 請(qǐng)使用bind方法替換
        mShaderProgram.bind();
        mShaderProgram.setUniformMatrix("u_projectionViewMatrix", mCamera.combined);
        mMesh.render(mShaderProgram, GL30.GL_TRIANGLES);
        // mShaderProgram.end(); // 已過(guò)時(shí), 可以去掉
    }

    @Override
    public void dispose() {
        mShaderProgram.dispose();
        mMesh.dispose();
    }

    private void initCamera() {
        mCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        mCamera.near = 0.3f;
        mCamera.far = 1000f;
        mCamera.zoom = 0.005f; // 相機(jī)縮放級(jí)別, 值越大觀察范圍越大, 看到的圖形越小
        mCamera.position.set(0f, 0f, -5f);
        mCamera.lookAt(0, 0, 0);
        mCamera.update();
    }

    private void initShader() { // 初始化著色器程序
        String vertex = Gdx.files.internal("shaders/triangle_vertex.glsl").readString();
        String fragment = Gdx.files.internal("shaders/triangle_fragment.glsl").readString();
        mShaderProgram = new ShaderProgram(vertex, fragment);
    }

    private void initMesh() { // 初始化網(wǎng)格
        float[] vertices = {
            -0.5f, -0.5f, 0.0f,
            0.5f, -0.5f, 0.0f,
            0.0f, 0.5f, 0.0f,
        };
        short[] indices = {0, 1, 2};
        VertexAttribute vertexPosition = new VertexAttribute(Usage.Position, 3, "a_position");
        mMesh = new Mesh(true, vertices.length / 3, indices.length, vertexPosition);
        mMesh.setVertices(vertices);
        mMesh.setIndices(indices);
    }
}

說(shuō)明:這里設(shè)置的三角形底邊和高都為 1仅炊,即寬高比為 1: 1斗幼,我們期望繪制后的三角形寬高比也是 1 : 1,這時(shí)就需要通過(guò)相機(jī)進(jìn)行變換茂洒。

triangle_vertex.glsl

#version 300 es

in vec3 a_position;

uniform mat4 u_projectionViewMatrix;

void main() {
    gl_Position = u_projectionViewMatrix * vec4(a_position, 1.0);
}

說(shuō)明:這里通過(guò)正交相機(jī)的觀察矩陣和投影矩陣變換,實(shí)現(xiàn)模型寬高比的適配瓶竭,也可以對(duì)輸入坐標(biāo)的 y 值乘以屏幕寬高比督勺,作為 gl_Position.y 的值。

triangle_fragment.glsl

#version 300 es
precision mediump float; // 聲明float型變量的精度為mediump

out vec4 fragColor;

void main() {
    fragColor = vec4(0, 1, 0, 0);
}

運(yùn)行效果如下斤贰,可以看到智哀,繪制后的三角形寬高比也是 1 : 1。

聲明:本文轉(zhuǎn)自【libGDX】使用Mesh繪制三角形荧恍。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末瓷叫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子送巡,更是在濱河造成了極大的恐慌摹菠,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骗爆,死亡現(xiàn)場(chǎng)離奇詭異次氨,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)摘投,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門煮寡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人犀呼,你說(shuō)我怎么就攤上這事幸撕。” “怎么了外臂?”我有些...
    開封第一講書人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵坐儿,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我宋光,道長(zhǎng)挑童,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任跃须,我火速辦了婚禮站叼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘菇民。我一直安慰自己尽楔,他們只是感情好投储,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著阔馋,像睡著了一般玛荞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上呕寝,一...
    開封第一講書人閱讀 51,198評(píng)論 1 299
  • 那天勋眯,我揣著相機(jī)與錄音,去河邊找鬼下梢。 笑死客蹋,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的孽江。 我是一名探鬼主播讶坯,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼晌纫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼焰扳!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起苇羡,我...
    開封第一講書人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤这刷,失蹤者是張志新(化名)和其女友劉穎婉烟,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體暇屋,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡隅很,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了率碾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片叔营。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖所宰,靈堂內(nèi)的尸體忽然破棺而出绒尊,到底是詐尸還是另有隱情,我是刑警寧澤仔粥,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布婴谱,位于F島的核電站,受9級(jí)特大地震影響躯泰,放射性物質(zhì)發(fā)生泄漏谭羔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一麦向、第九天 我趴在偏房一處隱蔽的房頂上張望瘟裸。 院中可真熱鬧,春花似錦诵竭、人聲如沸话告。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)沙郭。三九已至佛呻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間病线,已是汗流浹背吓著。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留送挑,地道東北人绑莺。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像让虐,于是被迫代替她去往敵國(guó)和親紊撕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子罢荡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容