标签:
package com.cumt.shape;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import com.cumt.openglesrectangle.R;
import com.cumt.utils.ShaderHelper;
import com.cumt.utils.TextResourceReader;
import android.content.Context;
import android.opengl.GLES20;
import android.opengl.Matrix;
public class Square {
private Context context;
//float类型的字节数
private static final int BYTES_PER_FLOAT = 4;
// 数组中每个顶点的坐标数
static final int COORDS_PER_VERTEX = 2;
/*------------------第一步: 修改顶点数据-------------------------*/
//矩形顶点坐标
static float squareCoords[] = { //以三角形扇的形式绘制
-0.5f, 0.5f , // top left
0.5f, 0.5f , // top right
0.5f, -0.5f , // bottom right
-0.5f, -0.5f }; // bottom left
private FloatBuffer vertexBuffer;
//------------第一个是顶点着色器的变量名,第二个是片段着色器的变量名
private static final String A_POSITION = "a_Position";
private static final String U_COLOR = "u_Color";
private static final String U_MATRIX = "u_Matrix";
//------------获得program的ID的含义类似的
private int uColorLocation;
private int aPositionLocation;
private int uMatrixLocation;
private int program;//保存program的id
/*------------------第二步: 修改顶点个数-------------------------*/
private static final int POSITION_COMPONENT_COUNT = 4;
float[] projectionMatrix = new float[16];//变换矩阵
public Square(Context context) {
this.context = context;
vertexBuffer = ByteBuffer
.allocateDirect(squareCoords.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
// 把坐标们加入FloatBuffer中
vertexBuffer.put(squareCoords);
// 设置buffer,从第一个坐标开始读
vertexBuffer.position(0);
getProgram();
uColorLocation = GLES20.glGetUniformLocation(program, U_COLOR);
aPositionLocation = GLES20.glGetAttribLocation(program, A_POSITION);
uMatrixLocation = GLES20.glGetUniformLocation(program, U_MATRIX);
GLES20.glVertexAttribPointer(aPositionLocation, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false, 0, vertexBuffer);
GLES20.glEnableVertexAttribArray(aPositionLocation);
}
//获取program
private void getProgram(){
//获取顶点着色器文本
String vertexShaderSource = TextResourceReader
.readTextFileFromResource(context, R.raw.simple_vertex_shader);
//获取片段着色器文本
String fragmentShaderSource = TextResourceReader
.readTextFileFromResource(context, R.raw.simple_fragment_shader);
//获取program的id
program = ShaderHelper.buildProgram(vertexShaderSource, fragmentShaderSource);
GLES20.glUseProgram(program);
}
//设置正交投影矩阵
public void projectionMatrix(int width,int height){
final float aspectRatio = width > height ?
(float) width / (float) height :
(float) height / (float) width;
if(width > height){
Matrix.orthoM(projectionMatrix, 0, -aspectRatio, aspectRatio, -1f, 1f, -1f, 1f);
}else{
Matrix.orthoM(projectionMatrix, 0, -1f, 1f, -aspectRatio, aspectRatio, -1f, 1f);
}
}
//以GL_LINE_LOOP方式绘制
public void draw(){
GLES20.glUniformMatrix4fv(uMatrixLocation, 1, false, projectionMatrix, 0);
GLES20.glUniform4f(uColorLocation, 0.0f, 0.0f, 1.0f, 1.0f);
/*------------------第三步: 修改绘制方式-------------------------*/
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, POSITION_COMPONENT_COUNT);
}
}
package com.cumt.render;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import com.cumt.shape.Square;
import android.content.Context;
import android.opengl.GLSurfaceView.Renderer;
import android.util.Log;
import static android.opengl.GLES20.glClear;
import static android.opengl.GLES20.glClearColor;
import static android.opengl.GLES20.glViewport;
import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
public class MyRender implements Renderer {
private Context context;
public MyRender(Context context){
this.context = context;
}
//定义矩形对象
Square square;
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Log.w("MyRender","onSurfaceCreated");
// TODO Auto-generated method stub
//First:设置清空屏幕用的颜色,前三个参数对应红绿蓝,最后一个对应alpha
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
square = new Square(context);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
Log.w("MyRender","onSurfaceChanged");
// TODO Auto-generated method stub
//Second:设置视口尺寸,即告诉opengl可以用来渲染的surface大小
glViewport(0,0,width,height);
square.projectionMatrix(width, height);
}
public void onDrawFrame(GL10 gl) {
Log.w("MyRender","onDrawFrame");
// TODO Auto-generated method stub
//Third:清空屏幕,擦除屏幕上所有的颜色,并用之前glClearColor定义的颜色填充整个屏幕
glClear(GL_COLOR_BUFFER_BIT);
square.draw();
}
}//simple_vertex_shader.glsl
uniform mat4 u_Matrix;
attribute vec4 a_Position;
void main()
{
gl_Position = u_Matrix * a_Position;
} package com.cumt.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.util.Log;
public class TextureHelper {
public static final String TAG = "TextureHelper";
public static int loadTexture(Context context,int resourceId){
/*
* 第一步 : 创建纹理对象
*/
final int[] textureObjectId = new int[1];//用于存储返回的纹理对象ID
GLES20.glGenTextures(1,textureObjectId, 0);
if(textureObjectId[0] == 0){//若返回为0,,则创建失败
if(LoggerConfig.ON){
Log.w(TAG,"Could not generate a new Opengl texture object");
}
return 0;
}
/*
* 第二步: 加载位图数据并与纹理绑定
*/
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;//Opengl需要非压缩形式的原始数据
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),resourceId, options);
if(bitmap == null){
if(LoggerConfig.ON){
Log.w(TAG,"ResourceId:"+resourceId+"could not be decoded");
}
GLES20.glDeleteTextures(1, textureObjectId, 0);
return 0;
}
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,textureObjectId[0]);//通过纹理ID进行绑定
/*
* 第三步: 设置纹理过滤
*/
//设置缩小时为三线性过滤
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_LINEAR_MIPMAP_LINEAR);
//设置放大时为双线性过滤
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
/*
* 第四步: 加载纹理到Opengl并返回ID
*/
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
return textureObjectId[0];
}
}
//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;
} 其中 a_TextureCoordinates 用于接收纹理的坐标数据,v_TextureCoordinates用于将纹理数据传递给片段着色器,因为纹理有两个分量 S与 T 所以使用vec2类型。//texture_fragment_shader.glsl
precision mediump float;
uniform sampler2D u_TextureUnit;
varying vec2 v_TextureCoordinates;
void main()
{
gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);
}//矩形顶点坐标 与 纹理坐标
static float squareCoords[] = { //以三角形扇的形式绘制
//x y s t
-0.5f, 0.5f , 0 , 0 , // top left
0.5f, 0.5f , 1 , 0 ,// top right
0.5f, -0.5f , 1 , 1 ,// bottom right
-0.5f, -0.5f , 0 , 1}; // bottom left
package com.cumt.shape;
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.glUniform1i;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import com.cumt.openglesrectangle.R;
import com.cumt.utils.ShaderHelper;
import com.cumt.utils.TextResourceReader;
import com.cumt.utils.TextureHelper;
import android.content.Context;
import android.opengl.GLES20;
import android.opengl.Matrix;
public class Square {
private Context context;
//float类型的字节数
private static final int BYTES_PER_FLOAT = 4;
// 数组中每个顶点的坐标数
static final int COORDS_PER_VERTEX = 2;
/*------------------修改顶点数据 ,加入顶点对应的纹理坐标-------------------------*/
//矩形顶点坐标 与 纹理坐标
static float squareCoords[] = { //以三角形扇的形式绘制
//x y s t
-0.5f, 0.5f , 0 , 0 , // top left
0.5f, 0.5f , 1 , 0 ,// top right
0.5f, -0.5f , 1 , 1 ,// bottom right
-0.5f, -0.5f , 0 , 1}; // bottom left
private FloatBuffer vertexBuffer;
private static final int VERTEX_COUNTS = 4;//顶点坐标数
private static final int POSITION_COMPONENT_COUNT = 2; //一个顶点坐标含有的元素个数
private static final int TEXTURE_COORDIANTES_COMPONENT_COUNT = 2; //一个纹理坐标含有的元素个数
//因为我们的顶点数据和纹理坐标数据放在了一起 ,所以在使用glVertexAttribPointer等函数时,其中的stride参数就需要传入了,
//用于高速着色器应该如何读取坐标值 ,比如这里我们的着色器读取坐标时,设置从位置 0开始读,读取x , y后就会跳过 s t 接着读取 x y
//这就是通过传入stride参数实现的
private static final int STRIDE = (POSITION_COMPONENT_COUNT + TEXTURE_COORDIANTES_COMPONENT_COUNT)
* BYTES_PER_FLOAT;
//------------第一个是顶点着色器的变量名,第二个是片段着色器的变量名
private static final String A_POSITION = "a_Position";
private static final String U_MATRIX = "u_Matrix";
private static final String A_TEXTURE_COORDINATES = "a_TextureCoordinates";//纹理
private static final String U_TEXTURE_UNIT = "u_TextureUnit";//纹理
private int aPositionLocation;
private int uMatrixLocation;
private int uTextureUnitLocation;
private int aTextureCoordinates;
private int program;//保存program的id
private int texture;
float[] projectionMatrix = new float[16];//变换矩阵
public Square(Context context) {
this.context = context;
vertexBuffer = ByteBuffer
.allocateDirect(squareCoords.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
// 把坐标们加入FloatBuffer中
vertexBuffer.put(squareCoords);
// 设置buffer,从第一个坐标开始读
vertexBuffer.position(0);
getProgram();
aPositionLocation = GLES20.glGetAttribLocation(program, A_POSITION);
uMatrixLocation = GLES20.glGetUniformLocation(program, U_MATRIX);
aTextureCoordinates = GLES20.glGetAttribLocation(program, A_TEXTURE_COORDINATES);
uTextureUnitLocation = GLES20.glGetAttribLocation(program, U_TEXTURE_UNIT);
texture = TextureHelper.loadTexture(context, R.drawable.umei);
// Set the active texture unit to texture unit 0.
glActiveTexture(GL_TEXTURE0);
// Bind the texture to this unit.
glBindTexture(GL_TEXTURE_2D, texture);
// Tell the texture uniform sampler to use this texture in the shader by
// telling it to read from texture unit 0.
glUniform1i(uTextureUnitLocation, 0);
//传入顶点坐标和纹理坐标
GLES20.glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT,
GLES20.GL_FLOAT, false, STRIDE, vertexBuffer);
GLES20.glEnableVertexAttribArray(aPositionLocation);
//设置从第二个元素开始读取,因为从第二个元素开始才是纹理坐标
vertexBuffer.position(POSITION_COMPONENT_COUNT);
GLES20.glVertexAttribPointer(aTextureCoordinates, TEXTURE_COORDIANTES_COMPONENT_COUNT,
GLES20.GL_FLOAT, false, STRIDE, vertexBuffer);
GLES20.glEnableVertexAttribArray(aTextureCoordinates);
}
//获取program
private void getProgram(){
//获取顶点着色器文本
String vertexShaderSource = TextResourceReader
.readTextFileFromResource(context, R.raw.texture_vertex_shader);
//获取片段着色器文本
String fragmentShaderSource = TextResourceReader
.readTextFileFromResource(context, R.raw.texture_fragment_shader);
//获取program的id
program = ShaderHelper.buildProgram(vertexShaderSource, fragmentShaderSource);
GLES20.glUseProgram(program);
}
//设置正交投影矩阵
public void projectionMatrix(int width,int height){
final float aspectRatio = width > height ?
(float) width / (float) height :
(float) height / (float) width;
if(width > height){
Matrix.orthoM(projectionMatrix, 0, -aspectRatio, aspectRatio, -1f, 1f, -1f, 1f);
}else{
Matrix.orthoM(projectionMatrix, 0, -1f, 1f, -aspectRatio, aspectRatio, -1f, 1f);
}
}
//以GL_LINE_LOOP方式绘制
public void draw(){
GLES20.glUniformMatrix4fv(uMatrixLocation, 1, false, projectionMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, VERTEX_COUNTS);
}
}标签:
原文地址:http://blog.csdn.net/cassiepython/article/details/51635744