libGDX:灯光效果实现一(实现一个点光源)
国内的libGDX文章很少,特别是libGDX实现灯光效果,所以就开始总结灯光效果的实现
1.Box2dLights库功能简介
库版本:1.5
目前Box2dLights提供了以下几种灯光效果模拟
- PointLight:点光源,就是中心点发光,向周围辐射,所以这个光源模拟的效果总是圆形的
- ConeLight:圆锥光源,也是从一点发光,但是光照角度和范围可以控制,像手电筒或投影仪那种
- DirectionalLight:模拟无限远的光源,光照效果不会随着距离和方向变弱,所以经常用来模拟阳光
- ChainLight:链式灯光,我们可以通过定义顶点更灵活的控制灯光模拟形状(比如让一个自定义的Body周围发光)
绿色的框 是为了方便看到Body位置,使用Box2DDebugRenderer渲染的
工欲善其事,必先利其器,工具集合
gdx-setup.jar
1. 从libGDX官网下载项目生成工具
https://libgdx.com/wiki/start/setup
2.配置项目
Output folder和Android SDK设置自己的,扩展库选择Box2d和Box2dlights,然后生成项目
3.配置ApplicationConfiguration,初始化ApplicationListener
由于是演示项目,所以直接使用系统创建好的Activity实现类
public class AndroidLauncher extends AndroidApplication {@Overrideprotected void onCreate (Bundle savedInstanceState) {super.onCreate(savedInstanceState);AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();config.a = 8;config.r = 8;config.g = 8;config.b = 8;initialize(new PointLightTest(), config);}
}
initialize的第一个参数后面的每个例子都会改成需要的那个类
4.创建一个PointLight
public class PointLightTest implements ApplicationListener {/** the camera **/OrthographicCamera camera;RayHandler rayHandler;World world;@Overridepublic void create() {// 1. 创建正交投影相机,这里设置的视口直接就是屏幕大小camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());// 2.把相机放到屏幕中心 这两步是为了更直观的看到映射后的效果,不用去计算灯光位置什么// 的,都放到中心显示camera.position.set(Gdx.graphics.getWidth() / 2f,Gdx.graphics.getHeight() / 2f, 0);// 3.更新相机camera.update();// 4.创建物理世界world = new World(new Vector2(0, -10), true);// 5.创建光束处理器(核心)rayHandler = new RayHandler(world);// 6.创建一个点光源new PointLight(rayHandler, 100, Color.RED, 150f, Gdx.graphics.getWidth() / 2f, Gdx.graphics.getHeight() / 2f);}@Overridepublic void resize(int width, int height) {camera.viewportWidth = width;camera.viewportHeight = height;camera.update();}@Overridepublic void render() {Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);world.step(1/60f, 8, 3);rayHandler.setCombinedMatrix(camera);rayHandler.updateAndRender();}@Overridepublic void pause() {}@Overridepublic void resume() {}@Overridepublic void dispose() {rayHandler.dispose();}
}
点光源的参数
- rayHandler:我们创建的RayHandler对象
- rays:光束个数,数量越大效果越逼真,但是性能消耗也越大,推荐最大不超过128
- color:灯光颜色
- distance 灯光的辐射距离,越大,灯光辐射的越远
- x:灯光在world中的横向中心点
- y:灯光在world中的纵向中心点
5.创建一个ConeLight
public class ConeLightTest implements ApplicationListener {/** the camera **/OrthographicCamera camera;RayHandler rayHandler;World world;@Overridepublic void create() {camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());camera.position.set(Gdx.graphics.getWidth() / 2f,Gdx.graphics.getHeight() / 2f, 0);camera.update();world = new World(new Vector2(0, -10), true);rayHandler = new RayHandler(world);new ConeLight(rayHandler, 100, Color.RED, 500f, Gdx.graphics.getWidth() / 2f, Gdx.graphics.getHeight() / 2f, 90, 60);}@Overridepublic void resize(int width, int height) {camera.viewportWidth = width;camera.viewportHeight = height;camera.update();}@Overridepublic void render() {Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);world.step(1 / 60f, 8, 3);rayHandler.setCombinedMatrix(camera);rayHandler.updateAndRender();}@Overridepublic void pause() {}@Overridepublic void resume() {}@Overridepublic void dispose() {rayHandler.dispose();}
}
和点光源一样的配置,将AndroidLauncher的initialize参数改为ConeLightTest,ConeLight的参数和点光源差不多,多了2个参数
- directionDegree: 光源方向,逆时针为正方向 示例代码设置的90,0的话就是向右
- coneDegree: 锥形光的跨越角度 示例代码设置的60
6. 创建一个DirectionalLight
public class DirectionalLightTest implements ApplicationListener {/** the camera **/OrthographicCamera camera;RayHandler rayHandler;World world;protected Body body;protected Box2DDebugRenderer mWorldDebugger;private int viewportWidth = 0;private int viewportHeight = 0;@Overridepublic void create() {viewportWidth = Gdx.graphics.getWidth();viewportHeight = Gdx.graphics.getHeight();camera = new OrthographicCamera(viewportWidth, viewportHeight);camera.position.set( viewportWidth/ 2f,viewportHeight/ 2f, 0);camera.update();world = new World(new Vector2(0, -10), true);mWorldDebugger = new Box2DDebugRenderer();makeBody();rayHandler = new RayHandler(world);new DirectionalLight(rayHandler, 100, Color.WHITE, 0);}private void makeBody() {CircleShape ballShape = new CircleShape();ballShape.setRadius(50f);FixtureDef fixtureDef = new FixtureDef();fixtureDef.shape = ballShape;BodyDef bodyDef = new BodyDef();bodyDef.type = BodyDef.BodyType.StaticBody;bodyDef.position.x = viewportWidth/ 2f;bodyDef.position.y = viewportHeight / 2f;body = world.createBody(bodyDef);body.createFixture(fixtureDef);ballShape.dispose();}@Overridepublic void resize(int width, int height) {camera.viewportWidth = width;camera.viewportHeight = height;camera.update();}@Overridepublic void render() {Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);world.step(1 / 60f, 8, 3);rayHandler.setCombinedMatrix(camera);rayHandler.updateAndRender();mWorldDebugger.render(world, camera.combined);}@Overridepublic void pause() {}@Overridepublic void resume() {}@Overridepublic void dispose() {rayHandler.dispose();}
}
看到上面的效果图,可能很多疑问,这是什么鬼。
这个光源比较特殊,他就是无限长的光,参数也比较少
- rayHandler: 和之前一样,RayHandler对象
- rays:光束个数
- color:灯光颜色 示例设置的白色
directionDegree:灯光照射角度,逆时针为正方向
这个光源设置后,如果画面上没有其他东西,就显示一个白屏,这就是这个光的特性,各处都照亮,所以一个屏幕都是白色,所以需要加上一个参照物,也就是示例代码和之前的多了一个body,光线照到body,然后被body遮挡就会显示阴影,也就成了上面示意图的模样,如果设置角度90,阴影就是朝上。
7.创建一个ChainLight
public class ChainLightTest implements ApplicationListener {/** the camera **/OrthographicCamera camera;RayHandler rayHandler;World world;protected Body body;protected Box2DDebugRenderer mWorldDebugger;private int viewportWidth = 0;private int viewportHeight = 0;private ChainLight chainLight;private float bodyWidth = 50;private float bodyHeight = 50;@Overridepublic void create() {RayHandler.setGammaCorrection(true);viewportWidth = Gdx.graphics.getWidth();viewportHeight = Gdx.graphics.getHeight();camera = new OrthographicCamera(viewportWidth, viewportHeight);camera.position.set( viewportWidth/ 2f,viewportHeight/ 2f, 0);camera.update();world = new World(new Vector2(0, -10), true);mWorldDebugger = new Box2DDebugRenderer();makeBody();rayHandler = new RayHandler(world);rayHandler.setAmbientLight(Color.GRAY);float[] vertices = new float[] {-bodyWidth / 2, -bodyHeight / 2,bodyWidth / 2, -bodyHeight / 2,bodyWidth / 2, bodyHeight / 2,-bodyWidth / 2, bodyHeight / 2,-bodyWidth / 2, -bodyHeight / 2};chainLight = new ChainLight(rayHandler, 100, Color.WHITE, 500, -1,vertices);chainLight.attachToBody(body, 0);}private void makeBody() {PolygonShape ballShape = new PolygonShape();ballShape.setAsBox(bodyWidth / 2, bodyHeight / 2);FixtureDef fixtureDef = new FixtureDef();fixtureDef.shape = ballShape;BodyDef bodyDef = new BodyDef();bodyDef.type = BodyDef.BodyType.StaticBody;bodyDef.position.x = viewportWidth/ 2f;bodyDef.position.y = viewportHeight / 2f;body = world.createBody(bodyDef);body.createFixture(fixtureDef);ballShape.dispose();}@Overridepublic void resize(int width, int height) {camera.viewportWidth = width;camera.viewportHeight = height;camera.update();}@Overridepublic void render() {Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);world.step(1 / 60f, 8, 3);rayHandler.setCombinedMatrix(camera);rayHandler.updateAndRender();mWorldDebugger.render(world, camera.combined);}@Overridepublic void pause() {}@Overridepublic void resume() {}@Overridepublic void dispose() {rayHandler.dispose();}
}
ChainLight参数不一样的是
- rayDirection: 源码示例给的是1和-1 这个值其实代表发光角度,也可以设置其他数
- chain: 顶点数组
ChainLight根据顶点确定发光体形状,rayDirection和chain的简单规律是
>> 1.1 如果是逆时针加入顶点 -1代表外部发光 1代表内部发光
>> 1.2 如果是顺时针加入顶点 -1代表内部发光 1代表外部发光
ChainLight比较特殊是必须依附于Body,Body决定了他的位置,示例是让一个正方形Body外围发光,顶点按照逆时针顺序添加。
唯一不接的一点是明明最后将原点设置为最后一个顶点,但是左下角却没有发光,不晓得是不是这个库的BUG
如果想定义圆形发光,比矩形麻烦点,需要很多个顶点,这些顶点连线形成这个圆形
RayHandler还有很多属性可以设置来加强模拟效果,可以多出尝试
注意:
- 如果没有调用RayHandler的serAmbinetLight设置环境光,而且开启了RayHandler模拟的话,界面是会一团黑的,你界面上绘制其他Actor是看不见的,除非有光照到他们
- 除了DirectionalLight,其他灯光都可以attachToBody
文章参考资料
- https://github.com/libgdx/box2dlights
libGDX:灯光效果实现一(实现一个点光源)相关推荐
- Opengl-阴影(分为定向光的和点光源的)
前言 我们模拟了光照,发现真的很厉害,加上天空盒子,再加上反射感觉很逼真,但是看着看着你会发现..不对,没影子.是的,光和影分不开的,有光的地方就会有影子,这才是真实的道理.怎么模拟影子呢?这就要用到 ...
- Opengl-光照-基本光照-投光物-多光源(现实世界的光可不只有太阳也并不只有一个)
前言 相信大家看过各种发光的道具,手电筒?看到过吧?灯泡看到过吧?除了太阳生活中还有各种灯红酒绿的地方(说错了)等着你去看啊 各种光源 平行光-太阳或者很远处的光都可以叫做平行光 平行光的光的方向是一 ...
- 4.3、Libgdx启动类和配置
(原文:http://www.libgdx.cn/topic/45/4-3-libgdx%E5%90%AF%E5%8A%A8%E7%B1%BB%E4%B8%8E%E9%85%8D%E7%BD%AE) ...
- OpenGL在frag着色器中模拟点光源
在3D世界中,模拟点光源实现对墙壁的光照.效果还是非常不错的. 思路如下: 准备一张墙壁图像. 自动生成墙壁的法线纹理. 模拟点光源. 添加漫反射. 随着时间变换进行规律性移动. 代码如下: #iCh ...
- OpenGL 点光源的多遍阴影贴图
OpenGL点光源的多遍阴影贴图 OpenGL点光源的多遍阴影贴图简介 源代码剖析 主要源代码 OpenGL点光源的多遍阴影贴图简介 我们学习了阴影贴图的基础知识-第一次从光源位置通过使用光方向作为视 ...
- OpenGL 点光源阴影Point Shadows
OpenGL点光源阴影Point Shadows 点光源阴影Point Shadows简介 生成深度立方体贴图 光空间的变换 深度着色器 万向阴影贴图 显示立方体贴图深度缓冲 PCF 点光源阴影Poi ...
- unity 烘焙参数 设置_Unity通用渲染管线(URP)系列(九)——点光源和聚光灯
200+篇教程总入口,欢迎收藏: 放牛的星星:[教程汇总+持续更新]Unity从入门到入坟--收藏这一篇就够了zhuanlan.zhihu.com 本文重点内容: 1.支持更多类型的灯光 2.包含实 ...
- Three.js - 光源使用详解1(环境光 AmbientLight、点光源 PointLint)
Three.js 中有许多不同种类的光源,每种光源都有特别的行为和用法.下面通过一个系列文章介绍它们的用法. 一.THREE.AmbientLight(环境光) 1,基本介绍 在创建 THREE.Am ...
- WPF 3D 点光源学习
先画一个平面,物体具有黄色的材质:不添加灯光,显示如下, 加入一个点光源,位置(1,1,1).颜色白色,如下,照亮了物体,看到物体的材质: 点光源是从斜上方照过来的, 如果光源为绿色,则如下, 点光源 ...
最新文章
- Matlab与线性代数 -- 矩阵的秩
- python精简笔记(五)——函数式编程
- 【转】如何用Redis做LRU-Cache
- [elixir观察] GenStage 与 Flow
- nginx出现404和403错误
- tcc读写文本txt文件
- tinyxml 读取文本节点_在Windows下使用TinyXML-2读取UTF-8编码包含中文字符的XML文件...
- lnmp 清除mysql日志,军哥LNMP 如何关闭 Mysql 日志,并且删除 mysql-bin.0000*日志文件...
- Hadoop HDFS 的 Java API 操作方式
- Azkaban流2.0
- (void __user *)arg 中__user的作用
- windows无法新建计算机对象,教您activex部件不能创建对象怎么解决
- 浏览器网页自动刷新脚本
- 论文笔记: FSA-Net
- Rimworld Mod制作教程7 comp组件
- 网站中木马病毒了怎么办
- 有人说:世间唯一无刺的玫瑰,就是朋友。
- vue 用key拿对象value_基于vue--key值的特殊用处详解
- IOS 最新邓白氏编码申请
- ios15.0.1正式版耗电吗 ios15.0.1正式版值得升级吗