LIBGDX版NEHE OPENGL- 7. Texture Filters, Lighting & Keyboard Control

来源:互联网 发布:帝国cms会员中心模板 编辑:程序博客网 时间:2024/04/29 04:15

Libgdx的TextureFilter

  首先废话说一说“纹理映射的方式”,一个128*128的图片,在渲染的时候,很可能会被放到一个256*256的方形区域显示,也有可能放到64*64的方形区域显示。所以,图片在缩小时,一些相象就丢失了,在放大时,就需要填充一些像素。

GL_TEXTURE_MIN_FILTER 指的是缩小的情况,而GL_TEXTURE_MAG_FILTER 指的是放大的情况。那OpenGL在这种情况下怎么处理呢?我们称之为纹理过滤方式:

  1. 最近点采样 GL_NEAREST-效果最差,速度快
  2. 线性纹理过滤(双线性过滤)GL_LINEAR-效果较好,计算量较大
  3. mipmap纹理过滤(三线性过滤) GL_LINEAR_MIPMAP_LINEAR-效果最好,计算量最大
  4. 各向异性过滤

更多关于这三种渲染方式的讲解看这里吧,http://blog.csdn.net/kkk328/article/details/7055934,我这只管怎么用就好了,要说一下,Libgdx所实现的OpenGL ES里,只支持前面三种。可以看一下Libgdx中关于TextureFilter的定义:

public enum TextureFilter {Nearest(GL10.GL_NEAREST), Linear(GL10.GL_LINEAR), MipMap(GL10.GL_LINEAR_MIPMAP_LINEAR), MipMapNearestNearest(GL10.GL_NEAREST_MIPMAP_NEAREST), MipMapLinearNearest(GL10.GL_LINEAR_MIPMAP_NEAREST), MipMapNearestLinear(GL10.GL_NEAREST_MIPMAP_LINEAR), MipMapLinearLinear(GL10.GL_LINEAR_MIPMAP_LINEAR);final int glEnum;TextureFilter (int glEnum) {this.glEnum = glEnum;}public boolean isMipMap () {return glEnum != GL10.GL_NEAREST && glEnum != GL10.GL_LINEAR;}public int getGLEnum () {return glEnum;}}

所以,三种类型的Texture就很好建立了:

Texture[] textureArray = new Texture[3];textureArray[0] = new Texture(imageFileHandle);textureArray[0].setFilter(TextureFilter.Nearest, TextureFilter.Nearest);textureArray[1] = new Texture(imageFileHandle);textureArray[1].setFilter(TextureFilter.Linear, TextureFilter.Linear);textureArray[2] = new Texture(imageFileHandle, true); // true 指明这里要使用mipmaptextureArray[2].setFilter(TextureFilter.MipMapLinearNearest,TextureFilter.Linear);

通过TextureFilter的定义可以看到,Libgdx可支持最多四种方式的MipMap, 高数好的可能会鄙视我了,Linear&Nearest最多就四种嘛。

MipMap(GL10.GL_LINEAR_MIPMAP_LINEAR), // 此种为默认的MipMap方式。等同于MinMapLinearLinear;

MipMapNearestNearest(GL10.GL_NEAREST_MIPMAP_NEAREST), 

MipMapLinearNearest(GL10.GL_LINEAR_MIPMAP_NEAREST), 

MipMapNearestLinear(GL10.GL_NEAREST_MIPMAP_LINEAR), 

MipMapLinearLinear(GL10.GL_LINEAR_MIPMAP_LINEAR);

我在学习TextureFilter的时候,Google到了一个好网站,名字为 Open GL Super Bible. 大家可以点去看看。当然,全英文。

Libgdx的Lighting:

在OpenGL中,最多支持8个光源。所以,Libgdx的GL10中,只能找到GL_LIGHT0 ~ GL_LIGHT7.

不好意思,我又要转帖了,这篇文章来自大龙的博客,对OpenGL ES的灯光做了不错的解释。

看完了大龙对灯光的介绍,再回来定义我们Libgdx里的光源:

// Ambient Light 环境光float[] ambientLight = {0.5f, 0.5f, 0.5f, 1.0f};// Diffuse Light 漫射光float[] diffuseLight = {1.0f, 1.0f, 1.0f, 1.0f};

光的问题先略过,等不及加上键盘处理了,这样就可以与画面有一些交互。

使用“L”键来开关灯,使用"F"键来切换filter类型,使用"鼠标滚轮"来放大缩小。

package com.kyugao.screen;import com.badlogic.gdx.Gdx;import com.badlogic.gdx.Input;import com.badlogic.gdx.InputProcessor;import com.badlogic.gdx.Screen;import com.badlogic.gdx.files.FileHandle;import com.badlogic.gdx.graphics.GL10;import com.badlogic.gdx.graphics.Mesh;import com.badlogic.gdx.graphics.PerspectiveCamera;import com.badlogic.gdx.graphics.Texture;import com.badlogic.gdx.graphics.Texture.TextureFilter;import com.badlogic.gdx.graphics.VertexAttribute;import com.badlogic.gdx.graphics.VertexAttributes.Usage;public class FilterLightingKeyboard implements Screen, InputProcessor {private Mesh squareMesh;private PerspectiveCamera camera;private Texture[] textureArray;private int filter = 0;private float xrot = 0, yrot = 0;private float xspeed = 20, yspeed = 20;// indicator for controlling the lightprivate boolean light;private boolean lp, fp;private float z = -5.0f;// Ambient Lightfloat[] ambientLight = { 0.5f, 0.5f, 0.5f, 1.0f };// Diffuse Lightfloat[] diffuseLight = { 1.0f, 1.0f, 1.0f, 1.0f };// Light Positionfloat[] position = { 0.0f, 0.0f, 2.0f, 1.0f };@Overridepublic void render(float delta) {camera.update();camera.apply(Gdx.graphics.getGL10());Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);Gdx.gl.glEnable(GL10.GL_DEPTH_TEST);Gdx.gl.glEnable(GL10.GL_TEXTURE_2D);drawGLScene();xrot += xspeed * delta; // 每秒钟转20度,计算在每一次render的时间差里,要转的角度。比如0.5秒,那就应该转10度。xrot %= 360;yrot += yspeed * delta;yrot %= 360;}private boolean drawGLScene() {Gdx.gl10.glPushMatrix();Gdx.gl10.glLoadIdentity();Gdx.gl10.glTranslatef(0.0f, 0.0f, z);Gdx.gl10.glRotatef(xrot, 1.0f, 0.0f, 0.0f);Gdx.gl10.glRotatef(yrot, 0.0f, 1.0f, 0.0f);textureArray[filter].bind();for (int i = 0; i < squareMesh.getMaxVertices() / 4; i++) {squareMesh.render(GL10.GL_TRIANGLE_FAN, i * 4, 4); // 正方形的6个面分别画出.}Gdx.gl10.glPopMatrix();return true;}@Overridepublic void show() {// init meshsquareMesh = new Mesh(true, 24, 24, new VertexAttribute(Usage.Position,3, "b_position"), new VertexAttribute(Usage.TextureCoordinates,2, "b_texture"));squareMesh.setVertices(new float[] {// Front face:-1f, 1.0f, 1.0f, 0f, 0f, // TL-1f, -1.0f, 1.0f, 0f, 1f, // BL1f, -1.0f, 1.0f, 1f, 1f, // BR1f, 1.0f, 1.0f, 1f, 0f, // TR// Top face:-1f, 1.0f, -1.0f, 0f, 0f, // LR-1f, 1.0f, 1.0f, 0f, 1f, // LN1f, 1.0f, 1.0f, 1f, 1f, // RN1f, 1.0f, -1.0f, 1f, 0f, // RR// Rear face1f, 1.0f, -1f, 0f, 0f, // TR1f, -1.0f, -1f, 0f, 1f, // BR-1f, -1.0f, -1f, 1f, 1f, // BL-1f, 1.0f, -1f, 1f, 0f, // TL// Bottom face-1f, -1.0f, 1f, 0f, 0f, // LN1f, -1.0f, 1f, 0f, 1f,// RN1f, -1.0f, -1f, 1f, 1f, // RR-1f, -1.0f, -1f, 1f, 0f, // LR// Left face-1f, 1.0f, -1f, 0f, 0f, // TR-1f, 1.0f, 1f, 0f, 1f, // TN-1f, -1.0f, 1f, 1f, 1f, // BN-1f, -1.0f, -1f, 1f, 0f, // BR// Right face1f, 1.0f, 1f, 0f, 0f, // TN1f, 1.0f, -1f, 1f, 0f, // TR1f, -1.0f, -1f, 1f, 1f, // BR1f, -1.0f, 1f, 0f, 1f // BN});squareMesh.setIndices(new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 });// init textureFileHandle imageFileHandle = Gdx.files.internal("data/Crate.bmp");textureArray = new Texture[3];textureArray[0] = new Texture(imageFileHandle);textureArray[0].setFilter(TextureFilter.Nearest, TextureFilter.Nearest);textureArray[1] = new Texture(imageFileHandle);textureArray[1].setFilter(TextureFilter.Linear, TextureFilter.Linear);textureArray[2] = new Texture(imageFileHandle, true);textureArray[2].setFilter(TextureFilter.MipMap, TextureFilter.Linear);// init lightGdx.gl.glEnable(GL10.GL_LIGHT1);Gdx.gl10.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, ambientLight, 0);Gdx.gl10.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, diffuseLight, 0);Gdx.gl10.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, position, 0);// Set input processorGdx.input.setInputProcessor(this);}@Overridepublic void hide() {}@Overridepublic void pause() {}@Overridepublic void resume() {}@Overridepublic void dispose() {}@Overridepublic void resize(int width, int height) {float aspectRatio = (float) width / (float) height;camera = new PerspectiveCamera(45, 2f * aspectRatio, 2f);}@Overridepublic boolean keyDown(int keycode) {if (keycode == Input.Keys.L && !lp) {lp = true;light = !light;if (light) {Gdx.gl.glEnable(GL10.GL_LIGHTING);} else {Gdx.gl.glDisable(GL10.GL_LIGHTING);}} else if (keycode == Input.Keys.F && !fp) {fp = true;filter = (filter + 1) % 3;}return false;}@Overridepublic boolean keyUp(int keycode) {if (keycode == Input.Keys.L && lp) {lp = false;} else if (keycode == Input.Keys.F && fp) {fp = false;}return false;}@Overridepublic boolean keyTyped(char character) {return false;}@Overridepublic boolean touchDown(int screenX, int screenY, int pointer, int button) {return false;}@Overridepublic boolean touchUp(int screenX, int screenY, int pointer, int button) {return false;}@Overridepublic boolean touchDragged(int screenX, int screenY, int pointer) {return false;}@Overridepublic boolean mouseMoved(int screenX, int screenY) {return false;}@Overridepublic boolean scrolled(int amount) {z += amount;return false;}}

上面代码,下面效果图:

缩小:


放大


放大到箱子里面:


使用mipmap的显示效果。(有点模糊)


原创粉丝点击