[OpenGL ES] 正交投影
在OpenGL中就需要用到矩形來改變頂點座標的範圍,最後再歸一化就可以了。
頂點著色器中新增矩陣
vertex_shader_m.glsl
attribute vec4 v_Position;
attribute vec2 f_Position;
varying vec2 ft_Position;
uniform mat4 u_Matrix;
void main() {
ft_Position = f_Position;
gl_Position = v_Position * u_Matrix;
}
然後根據圖形寬高和螢幕寬高計算(?)的長度
orthoM(float[] m, int mOffset, float left, float right, float bottom, float top, float near, float far)
Matrix.orthoM(matrix, 0, -width / ((height / 702f * 526f)), width / ((height / 702f * 526f)), -1f, 1f, -1f, 1f);
Matrix.orthoM(matrix, 0, -1, 1, - height / ((width / 526f * 702f)), height / ((width / 526f * 702f)), -1f, 1f);
使用
GLES20.glUniformMatrix4fv(umatrix, 1, false, matrix, 0);
GGLTextureRender
package com.example.opengldemo;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import android.util.Log;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
public class GGLTextureRender implements MyGLSurfaceView.MyGLRender {
private Context context;
//頂點座標
private final float[] vertexData = {
-1f, -1f,
1f, -1f,
-1f, 1f,
1f, 1f
};
//紋理座標
private final float[] fragmentData = {
//fbo座標
0f, 0f,
1f, 0f,
0f, 1f,
1f, 1f
// 0f, 1f,
// 1f, 1f,
// 0f, 0f,
// 1f, 0f
};
private FloatBuffer vertexBuffer;
private FloatBuffer fragmentBuffer;
public GGLTextureRender(Context context) {
this.context = context;
fboRender = new FboRender(context);
vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
.put(vertexData);
vertexBuffer.position(0);
fragmentBuffer = ByteBuffer.allocateDirect(fragmentData.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
.put(fragmentData);
fragmentBuffer.position(0);
}
private int program;
private int vPosition;
private int fPosition;
private int textureid;
private int sampler;
private int vboId;
private int fboId;
private int imgTextureId;
private FboRender fboRender;
/**************************正交投影-START*********************************************/
private int umatrix;
private float[] matrix = new float[16];
/**************************正交投影-END***********************************************/
@Override
public void onSufaceCreated() {
fboRender.onCreate();
/**************************正交投影-START*********************************************/
//更換shader
String vertexSource = GShaderUtil.getRawResource(context, R.raw.vertex_shader_m);
/**************************正交投影-END***********************************************/
String fragmentSource = GShaderUtil.getRawResource(context, R.raw.fragment_shader);
program = GShaderUtil.createProgram(vertexSource, fragmentSource);
if (program > 0) {
//頂點座標
vPosition = GLES20.glGetAttribLocation(program, "v_Position");
//紋理座標
fPosition = GLES20.glGetAttribLocation(program, "f_Position");
sampler = GLES20.glGetUniformLocation(program,"sTexture");
/**************************正交投影-START*********************************************/
//獲取矩陣
umatrix = GLES20.glGetUniformLocation(program,"u_Matrix");
/**************************正交投影-END***********************************************/
int [] vbos = new int[1];
GLES20.glGenBuffers(1, vbos, 0);
vboId = vbos[0];
//繫結
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
//分配記憶體
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexData.length*4 + fragmentData.length*4,
null,GLES20. GL_STATIC_DRAW);
//快取到視訊記憶體
GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0, vertexData.length * 4, vertexBuffer);
GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, vertexData.length * 4, fragmentData.length*4,
fragmentBuffer);
//解綁
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
int [] fbos = new int[1];
GLES20.glGenBuffers(1, fbos, 0);
fboId = fbos[0];
//繫結
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER,fboId);
//生成紋理
int[] textureIds = new int[1];
GLES20.glGenTextures(1, textureIds, 0);
textureid = textureIds[0];
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureid);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glUniform1i(sampler, 0);
//設定環繞過濾方法
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);
//設定FBO分配記憶體大小
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 900, 1600, 0,
GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
//把紋理繫結到FBO
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
GLES20.GL_TEXTURE_2D, textureid, 0);
//檢查FBO繫結是否成功
if(GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER) != GLES20.GL_FRAMEBUFFER_COMPLETE){
Log.e("godv", "fbo error");
}else {
Log.e("godv", "fbo success");
}
//解綁紋理
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
//解綁
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
imgTextureId = loadTexture(R.drawable.androids);
}
}
@Override
public void onSufaceChanged(int width, int height) {
//900 * 1600
GLES20.glViewport(0,0,width,height);
fboRender.onChange(width, height);
/**************************正交投影-START*********************************************/
if (width > height){
Matrix.orthoM(matrix, 0, -width / ((height / 702f * 526f)),
width / ((height / 702f * 526f)), -1f, 1f, -1f, 1f);
}else {
Matrix.orthoM(matrix, 0, -1, 1, - height / ((width / 526f * 702f)),
height / ((width / 526f * 702f)), -1f, 1f);
}
/**************************正交投影-END***********************************************/
}
@Override
public void onDrawFrame() {
//繫結FBO 離屏渲染 =0關掉
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboId);
//清屏
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
//使用顏色清屏
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
//使用program
GLES20.glUseProgram(program);
/**************************正交投影-START*********************************************/
//使用
GLES20.glUniformMatrix4fv(umatrix, 1, false, matrix, 0);
/**************************正交投影-END***********************************************/
//繫結FBO紋理id
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, imgTextureId);
//繫結VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
//使用頂點座標
GLES20.glEnableVertexAttribArray(vPosition);
//傳0 從VBO中取值
GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 8, 0);
GLES20.glEnableVertexAttribArray(fPosition);
//VBO
GLES20.glVertexAttribPointer(fPosition, 2, GLES20.GL_FLOAT, false, 8,
vertexData.length * 4);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
//解綁
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
//解綁VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
//解綁FBO
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
fboRender.onDraw(textureid);
}
/*
返回圖片資料的紋理
*/
private int loadTexture(int src){
//建立紋理
int[] textureIds = new int[1];
GLES20.glGenTextures(1, textureIds, 0);
//繫結紋理
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[0]);
//設定環繞過濾方法
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);
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),src);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
//解綁
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
return textureIds[0];
}
}
相關文章
- OpenGL/OpenGL ES 初探
- OpenGL 與 OpenGL ES
- OpenGL ES 入門
- OpenGL ES on iOS — AssimpiOS
- OpenGL ES SDK for Android - 6Android
- OpenGL ES SDK for Android - 2Android
- OpenGL/OpenGL ES入門:紋理初探 - 常用API解析API
- Opengl ES之踩坑記
- OpenGL ES 壓縮紋理
- OpenGL ES on iOS — 光照進階iOS
- Opengl ES之YUV資料渲染
- OpenGL ES專案總結一
- OpenGL ES 學習資源分享
- OpenGL/OpenGL ES入門: 影象渲染實現以及渲染問題
- OpenGL/OpenGL ES入門: 渲染流程以及固定儲存著色器
- OpenGL/OpenGL ES 入門:基礎變換 - 初識向量/矩陣矩陣
- 使用 OpenGL ES 實現全景播放器播放器
- Android OpenGL ES 系列連載:(07)Transform FeedbackAndroidORM
- Android OpenGL ES 系列連載:(14)粒子(Particles)Android
- [FFmpeg + OpenGL + OpenSL ES]音視訊同步- 8
- 詳解 OpenGL ES 2.x 渲染流程
- 使用 iOS OpenGL ES 實現長腿功能iOS
- OpenGL ES 高階進階:紋理陣列陣列
- Android OpenGL ES 開發(二):繪製圖形Android
- Android平臺OpenGL ES/Assimp/OpenCV/GLM整合說明AndroidOpenCV
- OpenGL ES 2.0學習(一)入門知識點
- OpenGL/OpenGL ES入門: 紋理應用 - 紋理座標及案例解析(金字塔)
- Android音視訊(六) 使用OpenGL ES 3.0預覽CameraAndroid
- 一文詳解 OpenGL ES 紋理顏色混合
- Android OpenGL ES 2.0 手把手教學(6)- 紋理Android
- Android OpenGL ES 2.0 手把手教學(1)- Hello World!Android
- FFmpeg+OpenGL ES+OpenSL ES打造Android視訊播放器課程總結Android播放器
- 一文詳解 OpenGL ES 3.x 渲染管線
- Android OpenGL ES 2.0 手把手教學(5)- 繪製模式Android模式
- 學習OpenGL ES之繪製三角形
- 從顯示一張圖片開始學習OpenGL ES
- OpenGL ES 實現頭部形變和頭部晃動效果
- 以OpenGL/ES視角介紹gfx-hal(Vulkan) Framebuffer介面使用