46.Mesh与Shader
标签:
it |
分类: libGDX开发教程 |
本文使用的libgdx是1.2.0版本,可能和最新版有一些不同地方。全文内容仅供参考。
第一个参数: 储存顶点的数据类型。
第二个参数: 数据元素的组成个数,范围
1 - 4。
第三个参数: 数据名称,也是在shader中使用该元素的“别名”,构建后可以修改。
:
第一个参数: 定义Mesh是否静态,对于那些不需要经常改动的Mesh,设置为静态可以提高OpenGL性能。
第二个参数: 顶点个数,范围
1 - 4。
第三个参数: 索引数,也就是libGDX绘制图形时,由哪个店开始绘制,绘制中各个顶点的绘制先后顺序。
第四个参数: 指定Mesh将会储存什么类型的数据,比如:
position ,color 等。
使用 GLSL
有如下好处:
1.设置顶点:setVertices(new
float[].....)
(1)前三个坐标代表三位坐标系的顶点坐标。(x,y,z)
(2)中间4个参数是代表颜色,RGBA。
(3)最后2个是纹理坐标。
3.设置索引:setIndices( new
short[] { 0, 1, 2, 2, 3, 0 })
很早之前在我的教程中,给大家讲解了有关于图元mesh的内容,但是并不是很详尽,仅仅是讲解了有关于图元的一些使用,那么今天我们就来讲解下libGDX中Mesh与Shader的内容,以为这个对于我们开发者来说,是很重要的,所以今天我们就来学习下它。关于此讲的视频教程,情点击链接进行观看:本集视频
1.VertexAttributes 类
如果要介绍Mesh的话,那么就必须要先讲解下VertexAttributes,他的意思是“顶点数据”,熟悉3D模型的同学,可能都了解,mesh其实不仅仅是平面2D的东西,在3D方面也是可以使用的。既然mesh是网格,那么他就需要有顶点来确定这个mesh,下面我们就来介绍下
vertexAttributes
---- 顶点数据。
PS:这个类了解就行,一般都是用他的内部类。
预定义名称:
libGDX是基于OpenGL的游戏引擎,这个mesh也是OpenGL带过来的,在OpenGL中规定我们在使用mesh的时候,必须先确定其中组成元素的属性。VertexAttributes 即顶点数据,它指定了每个顶点的各种属性数据。在OpenGL
ES1.0中,顶点属性有四个预定义的名字:position(位置),
normal(法线), color(颜色), 和 texture coordinates(纹理坐标)。在OpenGL
ES2.0中,用户必须定义“顶点属性的名字”,这个也是目前0.98版本libGDX中新增加的一项。
构造方法:
功能方法:(这里介绍的是较为常用的VertexAttributes的方法)
(1):内部类,常用,主要是其中集合了几个常用的预定义的名称,其实就是你要用它储存的数据类型,例如是位置型、颜色型等。
VertexAttributes.Usage (6): 返回的是一个int类型,找到顶点数据的个数。
size() VertexAttributes.Usage 类
这是一个内部类,比较常用,所以土豆这里特别拿出来讲解下。
功能方法:
(1)
: 颜色数据类型.
ColorPacked (2): 法线数据类型。(这个土豆也没用过,好像是翻译为“法线”)。
Normal 2.Mesh
类
图元的顶点是由VertexAttributes实例中所指定的各元素构成。在使用过程中VARM(帧存储器)和随机存储器mesh都是支持的。前者高性能是很优越的,如果硬件支持,它是首选。
图元用顶点和索引项来确定图形。每个顶点都拥有组成属性,比如位置,法线,颜色或纹理坐标。请注意,并非所有的这些属性必须在全部给定的。在使用OpenGL
ES 2.0绘制一个Mesh的时候,每个属性都有一个别名。别名用于顶点属性和shader属性绑定。着色器源和别名的属性必须完全匹配这个工作。图元可以与任何的OpenGL
ES 1.x或OpenGL ES 2.0的使用。
构造方法:
Mesh(boolean isStatic,
int maxVertices,
int maxIndices, VertexAttributes attributes)
功能方法:
(3):清除缓存。
clearAllMeshes(Application app) (7):
其中primitiveType指定绘制的形状, offset如果Mesh
使用了顶点缓存(vertex buffer) ,那么这个数就是起点,最后一个参数是指定索引的个数。
render(int primitiveType,
int offset,
int count) (8):设置mesh的索引数。
setIndices(short[] indices) 在图元mesh中,还有一些其他的方法,不过都是重复的方法,只是参数变化而已,这里土豆每个类型的方法拿出一个来讲解,大家可以根据这个,来学习其他的方法,都是顾名思义的,很简单的方法。
三、Shader
类
1.API定义:Shader(着色器),在OpenGL中的Shaders类似于一个小工具,它是使用GLSL语言写的(GLSL语言类似于C语言),Shaders是运行在GPU上用于呈现图形图像的东西。
2.原理:Shaders可以视为运行在GPU上面的一个stage,大家可以这么理解。如果想在OpenGL
ES 2.0渲染一些东西,渲染数据必须先通过顶点着色器,然后再通过片段着色器,才能完成渲染。
3.Vertex
shaders(顶点着色器):顾名思义,顶点着色器是负责执行顶点的操作。
4.Fragment
shaders(片段着色器):原理方法与定点着色器类似,但是不像定点着色器,片段着色器,我们可以理解为,对每一个像素进行处理,而不是处理每一个顶点。
三、GLSL
语言
1.
定义:OpenGL Shading Language 也称作
GLslang,是一个以C语言为基础的高阶着色语言。它是由 OpenGL ARB
所建立,提供开发者对绘图管线更多的直接控制,而无需使用汇编语言或硬件规格语言。
2.
优点:在渲染管线中的顶点(vertex)和片断(fragment)层次中,加入更具弹性的新功能。
达到在这个层次中,使用片断和顶点着色器的可编程性。
(1)具有跨平台的相容性,包括 Macintosh、Windows
和 Linux 等操作系统。
(2)所有支援 OpenGL
着色语言的绘图卡,都可以用来编写着色器。
(3)允许厂商为特定的绘图卡产生最佳化的代码。
3.语法定义
GLSL这里不做为重点理解,所以我们仅仅需要了解他的一些基本变量设置即可,有兴趣做着色编程的同学,可以自己去学习下。
如图:
四、参数详解
今天我们使用的实例,会涉及到一些复杂的数组设置,这里我讲解下有关于我们设置顶点属性的以为数组中变量代表的意思,以及设置索引顶点时的属性变量,是如何设置的。
http://s7/mw690/002I6kPggy6Mh0h5te606&690
2.纹理坐标:
(1)在二维纹理为中,规定纹理左下角的坐标为(0, 0),右上角的坐标为(1,
1)。
(2)于是纹理中的每一个像素的位置都可以用两个浮点数来表示(三维纹理会用三个浮点数,一维纹理则只用一个)。
(3)使用VertexAttribute.TexCoords(0)函数来指定纹理坐标.
如图:
(1)OpenGL中,使用Mesh绘制一个纹理,需要先绘制一个矩形区域,然后将纹理,以贴图的形式,贴在其上。
(2)贴图的过程中,我们需要将三维坐标系中的点绑定到纹理坐标系中的点。
(3)在绘制Mesh时,我们需要先绘制三角形,所有图形都是以三角形进行拼接而成的,所有需要设置索引点.
如图:
五、完整代码
(1)fragment.glsl代码。
#ifdef
GL_ES
precisionmediump float;
#endif
varyingvec4 v_color;
varyingvec2 v_texCoords;
uniformsampler2D u_texture;
voidmain()
{
gl_FragColor = v_color * texture2D(u_texture, v_texCoords);
}
precision
#endif
varying
varying
uniform
void
{
}
(2)vertex.glsl代码。
attribute vec4 a_position;
attributevec4 a_color;
attributevec2 a_texCoord0;
uniformmat4 u_worldView;
varyingvec4 v_color;
varyingvec2 v_texCoords;
voidmain()
{
v_color = vec4(1, 1, 1, 1);
v_texCoords = a_texCoord0;
gl_Position = u_worldView * a_position;
}
attribute
attribute
uniform
varying
varying
void
{
}
(3)MainGame代码
package com.androidgames.potato;
importcom.badlogic.gdx.ApplicationAdapter;
importcom.badlogic.gdx.Gdx;
importcom.badlogic.gdx.graphics.GL20;
importcom.badlogic.gdx.graphics.Mesh;
importcom.badlogic.gdx.graphics.Texture;
importcom.badlogic.gdx.graphics.VertexAttribute;
importcom.badlogic.gdx.graphics.VertexAttributes;
importcom.badlogic.gdx.graphics.glutils.ShaderProgram;
importcom.badlogic.gdx.math.Matrix4;
importcom.badlogic.gdx.math.Vector3;
publicclass MainGame extends ApplicationAdapter {
ShaderProgram shader;
Mesh mesh;
Texture texture;
Matrix4 matrix = new Matrix4();
@Override
public void create() {
String vertexShader = Gdx.files.internal("vertex.glsl").readString();
String fragmentShader = Gdx.files.internal("fragment.glsl").readString();
shader = new ShaderProgram(vertexShader, fragmentShader);
mesh = new Mesh(true, 4, 6, VertexAttribute.Position(),
VertexAttribute.ColorUnpacked(), VertexAttribute.TexCoords(0));
mesh.setVertices(new float[]{
//(x,y,z)坐标 + RGBA
+纹理坐标
-0.5f,-0.5f,0,1,1,1,1,0,1,
0.5f,-0.5f,0,1,1,1,1,1,1,
0.5f, 0.5f,0,1,1,1,1,1,0,
-0.5f,0.5f, 0,1,1,1,1,0,0
});
mesh.setIndices(new short[]{0,1,2,2,3,0});
texture = new Texture(Gdx.files.internal("map.png"));
}
Vector3 axis = new Vector3(0,0,1);
float angle = 0;
@Override
public void render() {
angle += Gdx.graphics.getDeltaTime() * 45;
matrix.setToRotation(axis, angle);
Gdx.gl20.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl20.glClearColor(0.2f, 0.2f, 0.2f, 1);
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D);
Gdx.gl20.glEnable(GL20.GL_BLEND);
Gdx.gl20.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
texture.bind();
shader.begin();
shader.setUniformMatrix("u_worldView", matrix);
mesh.
import
import
import
import
import
import
import
import
import
import
public

加载中…