您的位置:首页 > 运维架构

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

2013-04-22 18:30 429 查看
Libgdx的TextureFilter

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

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

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

各向异性过滤

更多关于这三种渲染方式的讲解看这里吧,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 指明这里要使用mipmap
textureArray[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 light
private boolean light;
private boolean lp, fp;
private float z = -5.0f;

// Ambient Light
float[] ambientLight = { 0.5f, 0.5f, 0.5f, 1.0f };
// Diffuse Light
float[] diffuseLight = { 1.0f, 1.0f, 1.0f, 1.0f };
// Light Position
float[] position = { 0.0f, 0.0f, 2.0f, 1.0f };

@Override
public 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;
}

@Override
public void show() {
// init mesh
squareMesh = 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, // BL
1f, -1.0f, 1.0f, 1f, 1f, // BR
1f, 1.0f, 1.0f, 1f, 0f, // TR
// Top face:
-1f, 1.0f, -1.0f, 0f, 0f, // LR
-1f, 1.0f, 1.0f, 0f, 1f, // LN
1f, 1.0f, 1.0f, 1f, 1f, // RN
1f, 1.0f, -1.0f, 1f, 0f, // RR
// Rear face
1f, 1.0f, -1f, 0f, 0f, // TR
1f, -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, // LN
1f, -1.0f, 1f, 0f, 1f,// RN
1f, -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 face
1f, 1.0f, 1f, 0f, 0f, // TN
1f, 1.0f, -1f, 1f, 0f, // TR
1f, -1.0f, -1f, 1f, 1f, // BR
1f, -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 texture
FileHandle 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 light
Gdx.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 processor
Gdx.input.setInputProcessor(this);
}

@Override
public void hide() {
}

@Override
public void pause() {
}

@Override
public void resume() {
}

@Override
public void dispose() {
}

@Override
public void resize(int width, int height) {
float aspectRatio = (float) width / (float) height;
camera = new PerspectiveCamera(45, 2f * aspectRatio, 2f);
}

@Override
public 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;
}

@Override
public boolean keyUp(int keycode) {
if (keycode == Input.Keys.L && lp) {
lp = false;
} else if (keycode == Input.Keys.F && fp) {
fp = false;
}
return false;
}

@Override
public boolean keyTyped(char character) {
return false;
}

@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
return false;
}

@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
return false;
}

@Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
return false;
}

@Override
public boolean mouseMoved(int screenX, int screenY) {
return false;
}

@Override
public boolean scrolled(int amount) {
z += amount;
return false;
}

}


上面代码,下面效果图:

缩小:



放大



放大到箱子里面:



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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: