美文网首页LibGDX
LibGDX图形模块之着色器

LibGDX图形模块之着色器

作者: 天神Deity | 来源:发表于2017-09-24 23:33 被阅读15次

如果你想使用OpenGL ES 2.0,你应该知道一些着色器的基础知识。 Libgdx附带了一个标准着色器,它将通过SpriteBatch处理渲染内容。 但是,如果要在Opengl ES 2.0中渲染网格,您将必须自己提供一个有效的着色器。 基本上在Opengl ES 2.0中,一切都是用着色器渲染的。 这就是为什么它被称为可编程管道。 在着色器中徘徊的想法可能会吓倒一些使用ES 2.0的人,但是值得仔细去阅读,因为着色器允许您做一些非常不可思议的事情。 而理解基础实际上是很直观的。

What are shaders?

OpenGL中的着色器是用C语言编写的小程序,称为GLSL,它在GPU上运行,并处理渲染事物所需的数据。 着色器可以简单地被视为GPU上的处理阶段。 它接收一组输入,您可以执行一组操作,最后将其重新发送出去。 想像这样的功能参数和返回值。 通常在OpenGL ES 2.0中呈现某些内容时,数据将首先通过顶点着色器发送,然后通过Fragment着色器发送。

顶点着色器

顾名思义,顶点着色器负责对顶点执行操作。 更具体地说,程序的每次执行都在一个顶点上运行。 这是一个重要的理解。 在顶点着色器中所做的一切只发生在一个顶点上。
这是一个简单的顶点着色器:

attribute vec4 a_position;

uniform mat4 u_projectionViewMatrix;

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

那看起来不错,现在呢? 首先你有一个名为a_position的顶点属性。 这个属性是一个vec4,这意味着它是一个4维的向量。 在该样本中,它保存顶点的位置信息。
接下来你有u_projectionViewMatrix。 这是一个保存视图和投影变换数据的4x4矩阵。 如果这些术语对你来说模糊,我建议您阅读这些主题.理解它是非常有用的。
在main方法中,我们对顶点执行操作。 在这种情况下,着色器所有顶点位置与矩阵相乘并将其分配给gl_Position。 gl_Position是OpenGL中预定义的关键字,不能用于其他任何东西,只能通过处理的顶点。

Fragment shaders

片段着色器以与顶点着色器作用非常相似。 但是不是在顶点上处理它,而是为每个片段处理它一次。 为了简单起见,将片段看作一个像素。 现在您可能会注意到这是一个非常显着的区别。
假设三角形覆盖300像素的区域。 这个三角形的顶点着色器将被执行3次。 片段着色器虽然可执行300次。 所以当编写着色器时,请牢记这一点。 在片段着色器中所做的一切都将呈指数级增加!
这是一个非常基本的片段着色器:

void main(){
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

这个片段着色器将简单地渲染每个片段的颜色为纯红色。 gl_FragColor是另一个预定义的关键字。 它用于输出片段的最终颜色。 注意我们如何使用vec4(x,y,z,w)来定义着色器内的向量。 在这种情况下,矢量用于定义片段的颜色。

一个简单的Shader程序

现在我们对着色器的作用和工作原理有一个基本的了解,让我们在libgdx中创建一个Demo。 这是通过ShaderProgram类完成的。 ShaderProgram由顶点着色器和片段着色器组成。 您可以从文件加载,也可以传入字符串,并将着色器代码保存在java文件中。
这是着色器的设置:

String vertexShader = "attribute vec4 a_position;    \n" + 
                      "attribute vec4 a_color;\n" +
                      "attribute vec2 a_texCoord0;\n" + 
                      "uniform mat4 u_projTrans;\n" + 
                      "varying vec4 v_color;" + 
                      "varying vec2 v_texCoords;" + 
                      "void main()                  \n" + 
                      "{                            \n" + 
                      "   v_color = vec4(1, 1, 1, 1); \n" + 
                      "   v_texCoords = a_texCoord0; \n" + 
                      "   gl_Position =  u_projTrans * a_position;  \n"      + 
                      "}                            \n" ;
String fragmentShader = "#ifdef GL_ES\n" +
                        "precision mediump float;\n" + 
                        "#endif\n" + 
                        "varying vec4 v_color;\n" + 
                        "varying vec2 v_texCoords;\n" + 
                        "uniform sampler2D u_texture;\n" + 
                        "void main()                                  \n" + 
                        "{                                            \n" + 
                        "  gl_FragColor = v_color * texture2D(u_texture, v_texCoords);\n" +
                        "}";

这是相当标准的使用位置属性,颜色属性和纹理坐标属性的着色器设置。

这是libgdx自己的库中的属性列表,用于那些希望轻松地将着色器附加到SpriteBatchs和libgdx的其他部分的库中:
a_position
a_normal
a_color
a_texCoord, requires a number at the end, i.e. a_texCoord0, a_texCoord1, etc...
a_tangent
a_binormal
要创建ShaderProgram,我们执行以下操作:

ShaderProgram shader = new ShaderProgram(vertexShader, fragmentShader);

您可以通过shader.isCompiled()确保着色器正确编译。 编译日志可以使用shader.getLog()发出。
我们还创建一个匹配的网格并加载纹理:

mesh = new Mesh(true, 4, 6, VertexAttribute.Position(), VertexAttribute.ColorUnpacked(), VertexAttribute.TexCoords(0));
mesh.setVertices(new float[] 
{-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("data/bobrgb888-32x32.png"));

在render方法中,我们简单地调用shader.begin()并传递uniforms ,然后使用着色器渲染网格:

texture.bind();
shader.begin();
shader.setUniformMatrix("u_projTrans", matrix);
shader.setUniformi("u_texture", 0);
mesh.render(shader, GL20.GL_TRIANGLES);
shader.end();

就是这样!
OpenGL ES 2.0中的着色器的好处是,您可以使用一个巨大的着色器库。 在WebGL中完成的任何事情都可以轻松地移植到手机上运行。 去做个实验吧!

相关文章

  • LibGDX图形模块之着色器

    如果你想使用OpenGL ES 2.0,你应该知道一些着色器的基础知识。 Libgdx附带了一个标准着色器,它将通...

  • LibGDX图形模块之剖析

    本文介绍的实用工具可能会派上用场,以防遇到性能问题,并需要开始分析你的游戏。 FPSLogger FPSLogge...

  • LibGDX图形模块之Ninepatches

    本文介绍了NinePatch图像,如何创建它们以及如何在Libgdx上下文中使用它们。 在你开始之前 本指南适用于...

  • LibGDX图形模块之清屏

    要清除Libgdx中的屏幕与在常规OpenGL应用程序中清除屏幕是不同的。 唯一的区别在于如何访问OpenGL上下...

  • LibGDX图形模块之网格

    网格是一组顶点(和可选的索引)的组合,它们描述了用于渲染的几何图形。 顶点以顶点缓冲对象(VBOs)的形式保存在V...

  • LibGDX图形模块之截屏

    使用以下代码可以截屏:

  • LibGDX图形模块之视口

    当处理不同的屏幕时,通常需要决定采取何种策略来处理不同屏幕尺寸和宽高比.Camera 和Stage 支持不同的视口...

  • LibGDX图形模块之位图字体

    LibGdx使用位图文件(png)来渲染字体。 字体中的每个字形都具有相应的纹理区域。BitmapFont cla...

  • LibGDX图形模块开篇

    此页面需要重写。 介绍 图形模块提供有关当前设备显示和应用程序窗口的信息,以及有关当前OpenGL上下文的信息和访...

  • LibGDX图形模块之正交相机

    本页介绍了OrthographicCamera类和用法。 正交相机仅在2D环境中使用,因为它实现了平行(正投影)投...

网友评论

    本文标题:LibGDX图形模块之着色器

    本文链接:https://www.haomeiwen.com/subject/kqilextx.html