LayaShader3D 之 动态显隐模型

思路

1、随便实现一个着色模型。
2、然后传入 世界坐标Y值。
3、根据Y值 在偏元着色器,舍弃,不需要的片元。

代码直接全部贴了。

测试主逻辑代码

	test(): void {
		//加载IDE指定的场景
		let scene: Laya.Scene3D = Laya.stage.addChild(new Laya.Scene3D()) as any;
		let camera = new Laya.Camera();
		let light = new Laya.DirectionLight();
		let sphere = new Laya.MeshSprite3D(Laya.PrimitiveMesh.createSphere(5));

		let mat = new ChangeVisibleMat();

		scene.addChild(sphere);
		scene.addChild(camera);
		scene.addChild(light);
		light.transform.localPosition = new Laya.Vector3(50, 25, 15);
		light.transform.lookAt(sphere.transform.position, new Laya.Vector3(0, 1, 0));
		camera.transform.position = new Laya.Vector3(15, 15, 15);
		camera.transform.lookAt(sphere.transform.position, new Laya.Vector3(0, 1, 0));
		camera.farPlane = 100;
		Laya.timer.frameLoop(1, this, () => {
			sphere.transform.localRotationEulerY += 0.005;
		})

		Laya.loader.load("res/dimian_04.jpg", Laya.Handler.create(this, () => {
			let tex = Laya.loader.getRes("res/dimian_04.jpg");
			mat.texture = tex;
			let direction = new Laya.Vector3();
			light.transform.getForward(direction);
			direction.setValue(direction.x * -1, direction.y * -1, direction.z * -1);
			mat.directionLight = direction;
			mat.colorLight = light.color.clone();
			// mat.borderColor = new Laya.Vector3(0.5, 0.5, 0.5)
			// let mat = new Laya.BlinnPhongMaterial();
			sphere.meshRenderer.material = mat;
			Laya.timer.loop(100, this, () => {
				mat.visibleY += 0.01;
			})
		}));
	}

材质mat代码

export default class ChangeVisibleMat extends Laya.Material {
    private PHONE_TEXTURE = Laya.Shader3D.propertyNameToID("u_Texture");
    private DIRECTION_LIGHT = Laya.Shader3D.propertyNameToID("u_DirectionLight_");
    private COLOR_LIGHT = Laya.Shader3D.propertyNameToID("u_ColorLight_");
    private Y = Laya.Shader3D.propertyNameToID("u_y");

    constructor() {
        super();
        this.setShaderName("ChangeVisibleShader");
        this._shaderValues.setNumber(this.Y, 0);
    }


    set visibleY(Y: number) {
        this._shaderValues.setNumber(this.Y, Y);
    }

    get visibleY(): number {
        return this._shaderValues.getNumber(this.Y);
    }


    set directionLight(direction: Laya.Vector3) {
        this._shaderValues.setVector3(this.DIRECTION_LIGHT, direction);
    }

    get directionLight(): Laya.Vector3 {
        return this._shaderValues.getVector3(this.DIRECTION_LIGHT);
    }

    set colorLight(color: Laya.Vector3) {
        this._shaderValues.setVector3(this.COLOR_LIGHT, color);
    }

    get colorLight(): Laya.Vector3 {
        return this._shaderValues.getVector3(this.COLOR_LIGHT);
    }

    set texture(tex) {
        this._shaderValues.setTexture(this.PHONE_TEXTURE, tex);
    }


}

shader文件

import PhoneVs from "./ChangeVisibleShaderVS.vs";
import PhoneFs from "./ChangeVisibleShaderFS.fs";

export default class ShaderChangeVisible {
    initShader(): void {
        //所有的attributeMap属性
        var attributeMap = {
            'a_Position': Laya.VertexMesh.MESH_POSITION0,
            'a_Normal': Laya.VertexMesh.MESH_NORMAL0,
            'a_Texcoord': Laya.VertexMesh.MESH_TEXTURECOORDINATE0,
            'a_BoneWeights': Laya.VertexMesh.MESH_BLENDWEIGHT0,
            'a_BoneIndices': Laya.VertexMesh.MESH_BLENDINDICES0
        };
        //所有的uniform属性
        var uniformMap = {
            'u_Bones': Laya.Shader3D.PERIOD_CUSTOM,//绑定
            'u_CameraPos': Laya.Shader3D.PERIOD_CAMERA,
            'u_DirectionLight_': Laya.Shader3D.PERIOD_MATERIAL,
            'u_ColorLight_': Laya.Shader3D.PERIOD_MATERIAL,
            'u_MvpMatrix': Laya.Shader3D.PERIOD_SPRITE,
            'u_WorldMat': Laya.Shader3D.PERIOD_SPRITE,
            'u_Texture': Laya.Shader3D.PERIOD_MATERIAL,
            'u_y': Laya.Shader3D.PERIOD_MATERIAL,
        };
        var customShader = Laya.Shader3D.add("ChangeVisibleShader");
        var subShader = new Laya.SubShader(attributeMap, uniformMap);
        customShader.addSubShader(subShader);
        let a = subShader.addShaderPass(PhoneVs, PhoneFs);
        a.renderState.cull = Laya.RenderState.CULL_NONE;
    }

}

fs

#ifdef FSHIGHPRECISION
  precision highp float;
#else
  precision mediump float;
#endif
#include "Lighting.glsl";
varying vec2 v_Texcoord;

uniform vec3 u_DirectionLight_;
uniform vec3 u_ColorLight_;
uniform vec3 u_BoderColor;
uniform float u_y;

varying vec3 v_Normal;
uniform sampler2D u_Texture;
uniform vec3 u_CameraPos;
varying vec3 v_PositionWorld;

     
void main() 
{
    //环境光
    vec3 ambColor = texture2D(u_Texture,v_Texcoord).xyz;
    // //高光
    float cosValue = max(0.0,dot(v_Normal,u_DirectionLight_));
    vec3 specular  = texture2D(u_Texture,v_Texcoord).xyz*pow(cosValue,5.0);
    // //漫反射
    vec3 diffuse =  texture2D(u_Texture,v_Texcoord).xyz*cosValue;
    vec3 color = ambColor*0.15 + diffuse*0.5 + specular*1.5;
    if(u_y < 0.0001){
      gl_FragColor = vec4(color,1.0);
    }else{
      if(v_PositionWorld.y<u_y){
        gl_FragColor = vec4(color,1.0);
      }else{
       discard;
      }
    }
  
}

vs


#include "Lighting.glsl";
attribute vec4 a_Position;
attribute vec2 a_Texcoord;
attribute vec3 a_Normal;
uniform mat4 u_MvpMatrix;
uniform mat4 u_WorldMat;
// uniform float u_y;
varying vec2 v_Texcoord;
varying vec3 v_Normal;
#ifdef BONE
    attribute vec4 a_BoneIndices;
    attribute vec4 a_BoneWeights;
    const int c_MaxBoneCount = 24;//数量
    uniform mat4 u_Bones[c_MaxBoneCount];//骨骼
#endif
varying vec3 v_PositionWorld;
void main()
{
    #ifdef BONE
        mat4 skinTransform=mat4(0.0);
        skinTransform += u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;
        skinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;
        skinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;
        skinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;
        vec4 position = skinTransform * a_Position;
        gl_Position=u_MvpMatrix * position;
        mat3 worldMat=mat3(u_WorldMat * skinTransform);
    #else 
        gl_Position=u_MvpMatrix * a_Position ;
        mat3 worldMat=mat3(u_WorldMat);
    #endif

    v_Texcoord=a_Texcoord;
    v_Normal=worldMat*a_Normal;

    #ifdef BONE
        v_PositionWorld=(u_WorldMat*position).xyz;
    #else
        v_PositionWorld=(u_WorldMat*a_Position).xyz;
    #endif


}

加载shader

import ShaderChangeVisible from "./ChangeVisibleShader/ShaderChangeVisible";

export default class ShaderMgr {
    private static _Inst: ShaderMgr = null;
    public static get Inst(): ShaderMgr {
        if (ShaderMgr._Inst == null) ShaderMgr._Inst = new ShaderMgr();
        return ShaderMgr._Inst;
    }

    initShader(): void {
        //shader工具
        //边缘发光
        //
        new ShaderChangeVisible().initShader();
    }
}

效果如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要控制Cesium的primitive的显隐,可以使用Cesium库中的setShow方法或JavaScript的style.display属性。如果你使用Cesium库,可以通过调用primitive的setShow方法来隐藏或显示它们。例如,要隐藏一个名为myPrimitive的primitive,可以使用myPrimitive.setShow(false)。 如果你不使用Cesium库,可以使用JavaScript的style.display属性来控制primitive的显隐。例如,要隐藏一个名为myPrimitive的primitive,可以使用myPrimitive.style.display = 'none'。 此外,Cesium还提供了统一的要素拾取查询机制,可以轻松实现对primitive的拾取操作。你可以通过Cesium.Scene中的拾取API来实现。例如,你可以使用viewer.scene.pick方法来获取鼠标位置下的拾取对象,然后根据需求进行处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [cesium中控制primitives显隐](https://blog.csdn.net/weixin_35750953/article/details/129066952)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Cesium 高性能扩展之DrawCommand(三):显隐和点选](https://blog.csdn.net/BMSS_91/article/details/122575164)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值