首先是两个坐标系
假如现在有一张图片,是通过纹理坐标系绘制出来的,图片的左上角(0,0),左下角(0,1),
那么我需要把纹理坐标系和顶点坐标系对齐, 那么要把纹理坐标系中(0,0)这个点,放到顶点坐标系中的(-1,0)这个点.
相应的要把纹理坐标系的(0,1)这个点,放到顶点坐标系中(-1,-1)这个点. 后面以此类推
具体做法: 先把OpenGL 需要展示的区域画出来(就是整个屏幕),再按照上面的做法 把纹理坐标系贴到顶点坐标系中.
vertex_shader.glsl
attribute vec4 av_Position;
attribute vec2 af_Position;
varying vec2 v_texPo;
void main() {
v_texPo = af_Position;
gl_Position = av_Position;
}
注: attribute 只能在vertex中使用
varying 用于vertex和fragment之间传递值
fragment_shader.glsl
precision mediump float;
varying vec2 v_texPo;
uniform sampler2D sTexture;
void main() {
gl_FragColor=texture2D(sTexture, v_texPo);
}
注: uniform 用于在application中向vertex和fragment中传递值。
1、加载shader和生成program过程不变
2、创建和绑定纹理:
GLES20.glGenTextures(1, textureId, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureid);
glGenTextures 就是创建纹理 参数.1 是创建多少个纹理 texturId 是个整形的数组. 0 是从0开始
glBindTexture 绑定纹理 把生成的textrueId 生成的纹理绑定到GL_TEXTURE_2D 上
3、设置环绕和过滤方式
环绕(超出纹理坐标范围):
(s == x t == y GL_REPEAT 重复)
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
过滤(纹理像素映射到坐标点):(缩小、放大:GL_LINEAR线性)
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
4、设置图片
(bitmap)
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
5、绑定顶点坐标和纹理坐标
6、绘制图形
按照前面文章
https://blog.csdn.net/liudao7994/article/details/84136584
绘制四边形 实际上的点 按照 v1 v2 v3 v4 绘制
在顶点坐标系中就是
//顶点坐标
private final float[] vertexData={
-1f,-1f,
1f,-1f,
-1f,1f,
1f,1f
};
但是纹理坐标系和顶点坐标系不一样 需要对应起来所以纹理坐标系是
//纹理坐标
private final float[] textureData={
0f,1f,
1f,1f,
0f,0f,
0f,1f
};
其他代码:
package com.xyyy.www.opengldemo;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
/**
* @author liuml
* @explain 渲染图片
* @time 2018/11/15 11:19
*/
public class XYRenderImage implements GLSurfaceView.Renderer {
private Context context;
//顶点坐标
private final float[] vertexData={
-1f,-1f,
1f,-1f,
-1f,1f,
1f,1f
};
//纹理坐标 正常
// private final float[] textureData={
// 0f,1f,
// 1f,1f,
// 0f,0f,
// 1f,0f
// };
//纹理坐标 倒立
private final float[] textureData={
1f,0f,
0f,0f,
1f, 1f,
0f, 1f
};
private FloatBuffer vertexBuffer;//顶点buffer
private FloatBuffer textureBuffer;//纹理buffer
private int program;
private int avPosition;//顶点坐标
private int afPosition;//纹理坐标
private int textureId;//纹理id保存
// private int afColor;
public XYRenderImage(Context context){
this.context = context;
vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
.put(vertexData);
vertexBuffer.position(0);
textureBuffer = ByteBuffer.allocateDirect(textureData.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
.put(textureData);
textureBuffer.position(0);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
String vertexSource = XYShaderUtil.readRawText(context, R.raw.img_vertex_shader);
String fragmentSource = XYShaderUtil.readRawText(context, R.raw.img_fragment_shader);
program = XYShaderUtil.createProgram(vertexSource, fragmentSource);
if (program > 0) {
avPosition = GLES20.glGetAttribLocation(program, "av_Position");
afPosition = GLES20.glGetAttribLocation(program, "af_Position");
//创建纹理
int[] textureIds = new int[1];
GLES20.glGenTextures(1, textureIds, 0);
if (textureIds[0] == 0) {
return;
}
textureId = textureIds[0];
//绑定
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
//设置参数 环绕(超出纹理坐标范围):
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
//过滤(纹理像素映射到坐标点
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
// BitmapFactory.Options options = new BitmapFactory.Options();
// options.inScaled = false;
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.test);
if (bitmap == null) {
return;
}
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
bitmap = null;
}
}
@Override
public void onSurfaceChanged(GL10 gl, int width,int height) {
//绘制区域
GLES20.glViewport(0,0,width,height);
}
@Override
public void onDrawFrame(GL10 gl) {
//清屏缓冲区
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
//利用颜色清屏
GLES20.glClearColor(1.0f,1.0f,1.0f,1.0f);
//让program可用
GLES20.glUseProgram(program);
//顶点坐标
GLES20.glEnableVertexAttribArray(avPosition);
GLES20.glVertexAttribPointer(avPosition, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
//纹理坐标
GLES20.glEnableVertexAttribArray(afPosition);
GLES20.glVertexAttribPointer(afPosition, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}
}
效果:
引用: https://blog.csdn.net/ywl5320/article/details/81161147