2D网格渲染器

一、简介

2D网格渲染器(Mesh2DRender)用于在2D场景中显示和渲染2D网格,支持纹理渲染,可以设置渲染颜色,还可以添加自定义的材质,接收2D光照效果。开发者可以用来创建复杂的2D图形效果,支持自定义网格形状,适合制作需要精确网格控制的2D游戏元素。

在游戏开发中,2D网格渲染器能够在2D游戏中实现更复杂和精细的视觉效果。例如,制作带有特殊光照效果的2D角色,创建复杂形态的 2D物体,实现复杂的2D特效。

总之,这个组件能够帮助开发者突破传统2D渲染的限制,创造出更加丰富和独特的效果。

二、在LayaAir-IDE中使用

在LayaAir-IDE中,创建一个sprite,在sprite上添加2D网格渲染器组件,如动图2-1所示。

2-1

(动图2-1)

添加后的组件属性如图2-2所示,

2-2

(图2-2)

其中渲染图层接受光照属性都与光照相关,具体用法参考2D灯光的文档。下面分别介绍其它的属性:

2.1 材质

2D网格渲染器支持添加自定义的材质,在LayaAir-IDE中,创建默认的材质为基础2D渲染(BaseRender2D),如图2-3所示,

2-3

(图2-3)

将材质添加到2D网格渲染器中的材质属性上,开发者也可以更改这个shader模版,自定义效果。

2Dshader的使用请查看文档自定义2D着色器

如图2-4所示,使用自定义的Shader实现了一个渐变的效果,

2-4

(图2-4)

此shader的代码如下,

Shader3D Start
{
    type:Shader3D,
    name:baseRender2D,
    enableInstancing:true,
    supportReflectionProbe:true,
    shaderType:2,
    uniformMap:{
        u_gradientDirection: {type: Vector2, default:[1,1]},    // 渐变方向
        u_gradientStartColor: {type:Vector4, default:[1,1,1,1]},       // 渐变起始颜色
        u_gradientEndColor: {type:Vector4, default:[1,1,1,1]}        // 渐变结束颜色    
    },
    attributeMap: {
        a_position: Vector4,
        a_color: Vector4,
        a_uv: Vector2,
    },
    defines: {
        BASERENDER2D: { type: bool, default: true }
    }
    shaderPass:[
        {
            pipeline:Forward,
            VS:baseRenderVS,
            FS:baseRenderPS
        }
    ]
}
Shader3D End

GLSL Start
#defineGLSL baseRenderVS

    #define SHADER_NAME baseRender2D

    #include "Sprite2DVertex.glsl";

    void main() {
        vec4 pos;
        //先计算位置,再做裁剪
        getPosition(pos);
        vertexInfo info;
        getVertexInfo(info);

        v_texcoord = info.uv;
        v_color = info.color;

        #ifdef LIGHT_AND_SHADOW
            lightAndShadow(info);
        #endif

        gl_Position = pos;
    }

#endGLSL

#defineGLSL baseRenderPS
    #define SHADER_NAME baseRender2D
    #if defined(GL_FRAGMENT_PRECISION_HIGH) 
    precision highp float;
    #else
    precision mediump float;
    #endif

    #include "Sprite2DFrag.glsl";

    void main()
    {
        clip();
        vec4 textureColor = texture2D(u_baseRender2DTexture, v_texcoord);

        // 计算渐变因子
        float gradientFactor = dot(v_texcoord, normalize(u_gradientDirection)) * 0.5 + 0.5;

        // 混合渐变颜色
        vec4 gradientColor = mix(u_gradientStartColor, u_gradientEndColor, gradientFactor);
        textureColor *= gradientColor;

        #ifdef LIGHT_AND_SHADOW
            lightAndShadow(textureColor);
        #endif

        textureColor = transspaceColor(textureColor);
        setglColor(textureColor);
    }

#endGLSL
GLSL End

2.2 网格

2D网格可以通过两种方式进行创建。一种方法是LayaAir-IDE内置的方法,如图2-5所示,在项目资源面板中,在需要创建网格的图片上右键,选择“创建2D网格”即可。

2-5

(图2-5)

另一种方法是通过代码创建的方法,参考第三节中generateCircleVerticesAndUVgenerateRectVerticesAndUV的代码。

2.3 纹理与颜色

纹理的选择不一定要与创建网格时选择的图片相同。例如,创建网格使用的是图2-6中的图片,

2-6

(图2-6)

纹理可以使用图2-7中的图片,

2-7

(图2-7)

最终的效果如图2-8所示,

2-8

(图2-8)

还可以更改颜色,效果如图2-9所示,

2-9

(图2-9)

三、通过代码使用

在LayaAir-IDE中新建一个脚本,添加到Scene2D节点后,加入下述代码,实现一个2D网格渲染器的效果:

const { regClass, property } = Laya;

@regClass()
export class Mesh2DRender extends Laya.Script {

    @property({type: Laya.Sprite})
    private layaMonkey: Laya.Sprite;

    //组件被启用后执行,例如节点被添加到舞台后
    onEnable(): void {
        Laya.loader.load("resources/layabox.png", Laya.Loader.IMAGE).then(() => {
            this.setMesh2DRender();
        });
    }

    // 配置2D网格渲染器
    setMesh2DRender(): void {
        let mesh2Drender = this.layaMonkey.getComponent(Laya.Mesh2DRender);
        // 添加网格
        mesh2Drender.sharedMesh = this.generateCircleVerticesAndUV(100, 100);
        let tex = Laya.loader.getRes("resources/layabox.png");
        mesh2Drender.texture = tex;
        // mesh2Drender.color = new Laya.Color(0.8, 0.15, 0.15, 1);
        // mesh2Drender.lightReceive = true;
    }

    /**
     * 生成一个圆形2D网格
     * @param radius 圆的半径
     * @param numSegments 圆被分割的段数,段数越多圆越平滑
     */
    private generateCircleVerticesAndUV(radius: number, numSegments: number): Laya.Mesh2D {
        // 2π
        const twoPi = Math.PI * 2;
        // 顶点数组
        let vertexs = new Float32Array((numSegments + 1) * 5);
        // 索引数组
        let index = new Uint16Array((numSegments + 1) * 3);
        var pos = 0;

        // 生成圆周上的顶点
        for (let i = 0; i < numSegments; i++, pos += 5) {
            const angle = twoPi * i / numSegments;
            // 计算顶点坐标
            var x = vertexs[pos + 0] = radius * Math.cos(angle);
            var y = vertexs[pos + 1] = radius * Math.sin(angle);
            vertexs[pos + 2] = 0; // z坐标始终为0(2D)
            // 计算UV坐标
            vertexs[pos + 3] = 0.5 + x / (2 * radius); // 将x从[-radius, radius]映射到[0,1]
            vertexs[pos + 4] = 0.5 + y / (2 * radius); // 将y从[-radius, radius]映射到[0,1]
        }
        //圆心
        vertexs[pos] = 0;
        vertexs[pos + 1] = 0;
        vertexs[pos + 2] = 0;
        vertexs[pos + 3] = 0.5;
        vertexs[pos + 4] = 0.5;

        // 生成三角形索引
        for (var i = 1, ibIndex = 0; i < numSegments; i++, ibIndex += 3) {
            index[ibIndex] = i;
            index[ibIndex + 1] = i - 1;
            index[ibIndex + 2] = numSegments;
        }
        // 处理最后一个三角形:连接最后一个顶点、第一个顶点和圆心
        index[ibIndex] = numSegments - 1;
        index[ibIndex + 1] = 0;
        index[ibIndex + 2] = numSegments;
        // 顶点声明
        var declaration = Laya.VertexMesh2D.getVertexDeclaration(["POSITION,UV"], false)[0];
        let mesh2D = Laya.Mesh2D.createMesh2DByPrimitive([vertexs], [declaration], index, Laya.IndexFormat.UInt16, [{ length: index.length, start: 0 }]);
        return mesh2D;
    }
}

最终的效果如图3-1所示,

3-1

(图3-1)

示例中给出的是一个圆形的网格,下面再给出一个矩形网格的写法,

    /**
     * 生成一个矩形2D网格
     * @param width 矩形的宽度
     * @param height 矩形的高度
     */
    private generateRectVerticesAndUV(width: number, height: number): Laya.Mesh2D {
        const vertices = new Float32Array(4 * 5);
        const indices = new Uint16Array(2 * 3);
        let index = 0;
        vertices[index++] = 0;
        vertices[index++] = 0;
        vertices[index++] = 0;
        vertices[index++] = 0;
        vertices[index++] = 0;

        vertices[index++] = width;
        vertices[index++] = 0;
        vertices[index++] = 0;
        vertices[index++] = 1;
        vertices[index++] = 0;

        vertices[index++] = width;
        vertices[index++] = height;
        vertices[index++] = 0;
        vertices[index++] = 1;
        vertices[index++] = 1;

        vertices[index++] = 0;
        vertices[index++] = height;
        vertices[index++] = 0;
        vertices[index++] = 0;
        vertices[index++] = 1;

        index = 0;
        indices[index++] = 0;
        indices[index++] = 1;
        indices[index++] = 3;

        indices[index++] = 1;
        indices[index++] = 2;
        indices[index++] = 3;

        const declaration = Laya.VertexMesh2D.getVertexDeclaration(["POSITION,UV"], false)[0];
        const mesh2D = Laya.Mesh2D.createMesh2DByPrimitive([vertices], [declaration], indices, Laya.IndexFormat.UInt16, [{ length: indices.length, start: 0 }]);
        return mesh2D;
    }

只需替换示例代码中的generateCircleVerticesAndUV即可,效果如图3-2所示。

3-2

(图3-2)

Copyright ©Layabox 2025 all right reserved,powered by LayaAir Engine更新时间: 2025-01-08 21:33:09

results matching ""

    No results matching ""