1.纹理坐标(UV纹理坐标)
1.1可以通过调整纹理坐标或者通过拉伸或压扁纹理本身来适应被绘制的形状
1.2计算机图像默认坐标
2.opengl纹理过滤模式
参考:http://blog.youkuaiyun.com/pizi0475/article/details/49740879
3.纹理绘制
纹理不会被直接绘制,它们要被绑定到纹理单元,然后把这些纹理单元传递给着色器。通过在纹理单元中把纹理切来窃取,我们还可以在场景中绘制不同的纹理,但是过分的切换可能使性能下降,我们也能同时使用多个纹理单元绘制几个纹理。
4.主要代码
//片段着色器/res/raw/texture_fragment_shader.glsl
precision mediump float;
uniform sampler2D u_TextureUnit;
varying vec2 v_TextureCoordinates;
void main()
{
gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);
}
//顶点着色器/res/raw/texture_vertex_shader.glsl
uniform mat4 u_Matrix;
attribute vec4 a_Position;
attribute vec2 a_TextureCoordinates;
varying vec2 v_TextureCoordinates;
void main()
{
v_TextureCoordinates = a_TextureCoordinates;
gl_Position = u_Matrix * a_Position;
}
package com.example.firstopengl.util;
import static android.opengl.GLES20.GL_LINEAR;
import static android.opengl.GLES20.GL_LINEAR_MIPMAP_LINEAR;
import static android.opengl.GLES20.GL_TEXTURE_2D;
import static android.opengl.GLES20.GL_TEXTURE_MAG_FILTER;
import static android.opengl.GLES20.GL_TEXTURE_MIN_FILTER;
import static android.opengl.GLES20.glBindTexture;
import static android.opengl.GLES20.glDeleteTextures;
import static android.opengl.GLES20.glGenTextures;
import static android.opengl.GLES20.glGenerateMipmap;
import static android.opengl.GLES20.glTexParameteri;
import static android.opengl.GLUtils.texImage2D;
import com.example.firstopengl.LoggerConfig;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
public class TextureHelper {
private static final String TAG = "TestureHelper";
/**
* 加载纹理
* @param context
* @param resourceId 资源id
* @return 纹理数据
*/
public static int loadTexture(Context context, int resourceId){
final int[] textureObjectIds = new int[1];
glGenTextures(1, textureObjectIds, 0);
if(textureObjectIds[0] == 0){
if(LoggerConfig.ON){
Log.w(TAG, "不能创建纹理对象");
}
return 0;
}
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;//图像原始数据
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
if(bitmap==null){
if(LoggerConfig.ON){
Log.w(TAG, "资源不能被加载");
}
glDeleteTextures(1, textureObjectIds, 0);
return 0;
}
//绑定纹理,才可进行对纹理操作
glBindTexture(GL_TEXTURE_2D, textureObjectIds[0]);
//opengl纹理过滤模式 http://blog.youkuaiyun.com/pizi0475/article/details/49740879
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//加载位图数据到纹理
texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
//生成MIP贴图
glGenerateMipmap(GL_TEXTURE_2D);
//解除纹理绑定
glBindTexture(GL_TEXTURE_2D, 0);
return textureObjectIds[0];
}
}
package com.example.firstopengl.programs;
import static android.opengl.GLES20.GL_TEXTURE0;
import static android.opengl.GLES20.GL_TEXTURE_2D;
import static android.opengl.GLES20.glActiveTexture;
import static android.opengl.GLES20.glBindTexture;
import static android.opengl.GLES20.glGetAttribLocation;
import static android.opengl.GLES20.glGetUniformLocation;
import static android.opengl.GLES20.glUniform1i;
import static android.opengl.GLES20.glUniformMatrix4fv;
import com.example.firstopengl.R;
import android.content.Context;
public class TextureShaderProgram extends ShaderProgram{
//Uniform locations
private final int uMatrixLocation;
private final int uTextureUnitLocation;
//Attribute locations
private final int aPositionLocation;
private final int aTextureCoordinatesLocation;
public TextureShaderProgram(Context context) {
// TODO Auto-generated constructor stub
super(context, R.raw.texture_vertex_shader, R.raw.texture_fragment_shader);
uMatrixLocation = glGetUniformLocation(program, U_MATRIX);
uTextureUnitLocation = glGetUniformLocation(program, U_TEXTURE_UNIT);
aPositionLocation = glGetAttribLocation(program, A_POSITION);
aTextureCoordinatesLocation = glGetAttribLocation(program, A_TEXTURE_COORDINATES);
}
/**
* 设置着色器uniform变量
* @param matrix
* @param textureId
*/
public void setUniforms(float[] matrix, int textureId){
glUniformMatrix4fv(uMatrixLocation, 1, false, matrix, 0);
//激活纹理单元0
glActiveTexture(GL_TEXTURE0);
//绑定纹理单元
glBindTexture(GL_TEXTURE_2D, textureId);
//传递纹理单元0
glUniform1i(uTextureUnitLocation, 0);
}
public int getPositionAttributeLocation(){
return aPositionLocation;
}
public int getTextureCoodinatesAttributeLocation() {
return aTextureCoordinatesLocation;
}
}
package com.example.firstopengl;
import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
import static android.opengl.GLES20.glClear;
import static android.opengl.GLES20.glClearColor;
import static android.opengl.GLES20.glViewport;
import static android.opengl.Matrix.multiplyMM;
import static android.opengl.Matrix.perspectiveM;
import static android.opengl.Matrix.rotateM;
import static android.opengl.Matrix.setIdentityM;
import static android.opengl.Matrix.translateM;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import com.example.firstopengl.objs.Mallet;
import com.example.firstopengl.objs.Table;
import com.example.firstopengl.programs.ColorShaderProgram;
import com.example.firstopengl.programs.TextureShaderProgram;
import com.example.firstopengl.util.TextureHelper;
import android.content.Context;
import android.opengl.GLSurfaceView.Renderer;
public class MyRenderer implements Renderer {
private final Context context;
//投影矩阵
private final float[] projectionMatrix = new float[16];
//模型矩阵
private final float[] modelMatrix = new float[16];
//objs
private Table table;
private Mallet mallet;
//着色器程序
private TextureShaderProgram textureProgram;
private ColorShaderProgram colorProgram;
//纹理
private int texture;
public MyRenderer(Context context) {
// TODO Auto-generated constructor stub
this.context = context;
}
// 绘制每一帧时,GLSurfaceView调用(suface创建后)
@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
// 清除屏幕颜色
glClear(GL_COLOR_BUFFER_BIT);
//绘制table
textureProgram.useProgram();
textureProgram.setUniforms(projectionMatrix, texture);
table.bindData(textureProgram);
table.draw();
//绘制mallet
colorProgram.useProgram();
colorProgram.setUniforms(projectionMatrix);
mallet.bindData(colorProgram);
mallet.draw();
}
// suface视图大小改变时,GLSurfaceView调用(suface创建后)
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
//创建透视投影矩阵
perspectiveM(projectionMatrix, 0, 45, (float)width/(float)height, 1f, 10f);
//利用模型矩阵移动和旋转物体
setIdentityM(modelMatrix, 0);
translateM(modelMatrix, 0, 0f, 0f, -2.5f);
rotateM(modelMatrix, 0, -60f, 1f, 0f, 0f);
//透视投影矩阵与模型矩阵相乘赋值给projectionMatrix
final float[] temp = new float[16];
multiplyMM(temp, 0, projectionMatrix, 0, modelMatrix, 0);
System.arraycopy(temp, 0, projectionMatrix, 0, temp.length);
}
// suface创建时,GLSurfaceView调用
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
// 清空屏幕的颜色
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
table = new Table();
mallet = new Mallet();
textureProgram = new TextureShaderProgram(context);
colorProgram = new ColorShaderProgram(context);
texture = TextureHelper.loadTexture(context, R.drawable.ic_launcher);
}
}