十四、混合

news/2024/11/9 4:43:47/

第一部分 概念:

1) 引入

OpenGL ES 混合本质上是将 2 个片元的颜色进行调和,产生一个新的颜色。OpenGL ES 混合发生在片元通过各项测试之后,准备进入帧缓冲区的片元和原有的片元按照特定比例加权计算出最终片元的颜色值,不再是新(源)片元直接覆盖缓冲区中的(目标)片元。

在这里插入图片描述

2)应用

启用 OpenGL ES 混合使用 需要在绘画前启动glEnable(GL_BLEND);

然后通过 void glBlendFunc(GLenum sfactor, GLenum dfactor); 设置混合的方式,其中 sfactor 表示源因子,dfactor 表示目标因子。

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// GL_SRC_ALPHA 表示源因子取值为源颜色的 alpha
// GL_ONE_MINUS_SRC_ALPHA 表示目标因子取值为 1- alpha(源颜色的 alpha)// 操作符默认为 GL_FUNC_ADD ,即加权相加。
// 混合公式变成了 源颜色向量 × alpha + 目标颜色向量 × (1- alpha)

在这里插入图片描述

默认的操作符是加号,我们也可以通过void glBlendEquation(GLenum mode)接口来自定义设置。

GL_FUNC_ADD:默认的,彼此元素相加

GL_FUNC_SUBTRACT:彼此元素相减

GL_FUNC_REVERSE_SUBTRACT:彼此元素相减,但顺序相反

GL_MIN:混合结果的 4 个通道值分别取 2 元素中 4 个通道较小的值

GL_MAX:混合结果的 4 个通道值分别取 2 元素中 4 个通道较大的值

glBlendFuncSeperate为 RGB 和 alpha 通道各自设置不同的混合因子

//对 RGB 和 Alpha 分别设置 BLEND 函数

void glBlendFuncSeparate(GLenum srcRGB,GLenum dstRGB,GLenum srcAlpha,GLenum dstAlpha);

glBlendFuncSeperate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,GL_ONE, GL_ZERO);
上面就表示
混合结果颜色 RGB 向量 = 源颜色 RGB 向量 × alpha + 目标颜色 RGB 向量 × (1- alpha);
混合结果颜色 alpha = 源颜色 alpha × 1 + 目标颜色 alpha × 0;

这个也是默认为+号,但是可以通过glBlendEquationSeparate为 RGB 和 alpha 通道各自设置不同操作符。void glBlendEquationSeparate(GLenum modeRGB,GLenum modeAlpha);

另外需要格外注意的是,开启混合和深度测试绘制透明物体时,需要遵循物体距观察者(Camera)的距离,由远到近开始绘制,这样可以避免由于深度测试开启后(在透明物体后面)丢弃片元造成的奇怪现象。

第二部分 实践:

1)java部分

java部分在绘制部分都是跟之前一致的,只是因为混合使用到了图片的RGBA中A的维度,需要将32位的png图片在java端转换为具体的RGBA数据传递到JNI去。

NativeImpl.java

public class NativeImpl {。。。。//多出这个native接口public static native void native_SetImageDataWithIndex(int index, int width,int height, byte[] byteArray);
}

MyGLSurfaceView.java

public class MyGLSurfaceView extends GLSurfaceView implements ScaleGestureDetector.OnScaleGestureListener{public MyGLSurfaceView(Context context) {...//开始的时候就把内容主动传递到loadRGBAImage(R.drawable.board_texture,0);loadRGBAImage(R.drawable.floor,1);loadRGBAImage(R.drawable.window,2);}private Bitmap loadRGBAImage(int resId, int index) {InputStream is = this.getResources().openRawResource(resId);Bitmap bitmap;try {bitmap = BitmapFactory.decodeStream(is);if (bitmap != null) {int bytes = bitmap.getByteCount();ByteBuffer buf = ByteBuffer.allocate(bytes);bitmap.copyPixelsToBuffer(buf);byte[] byteArray = buf.array();renderer.setImageDataWithIndex(index, bitmap.getWidth(), bitmap.getHeight(), byteArray);}}finally{try{is.close();}catch(IOException e){e.printStackTrace();}}return bitmap;}...private class MyRenderer implements Renderer {...public void setImageDataWithIndex(int index, int width, int height, byte[] bytes) {NativeImpl.native_SetImageDataWithIndex(index, width, height, bytes);}}
}

2)C++部分

NativeGL.cpp

多出
std::vector<struct ImageTyep> vcImage;
/** Class:     com_example_nineblending_native_SetImageDataWithIndex* Method:    native_SetImageDataWithIndex* Signature: (III[B)V*/
JNIEXPORT void JNICALL native_SetImageDataWithIndex(JNIEnv *env, jobject instance, jint index, jint width, jint height, jbyteArray byteArray)
{struct ImageTyep itype;int len = env->GetArrayLength (byteArray);uint8_t* buf = new uint8_t[len];env->GetByteArrayRegion(byteArray, 0, len, reinterpret_cast<jbyte*>(buf));itype.data = buf;itype.width =width;itype.height = height;vcImage.push_back(itype);LOGD("native_SetImageDataWithIndex  width=%d height =  height", width, height);//env->DeleteLocalRef(byteArray);
}

Blending.h

//
// Created by CreatWall_zhouwen on 2023/5/15.
//#ifndef NINEBLENDING_BLENDING_H
#define NINEBLENDING_BLENDING_H
#include <GLES3/gl3.h>
#include <detail/type_mat.hpp>
#include <detail/type_mat4x4.hpp>
#include <vector>
#include <map>
#include "Const.h"
#define MATH_PI 3.1415926535897932384626433832802
#define RENDER_IMG_NUM 3
class Blending {
public:Blending();~Blending();void CreateProgram(const char *ver, const char *frag);void Draw();void getTexturedata(std::vector<struct ImageTyep> vcImagetemp);static Blending* GetInstance();static void DestroyInstance();void UpdateTransformMatrix(float rotateX, float rotateY, float scaleX, float scaleY);void UpdateMatrix(glm::mat4 &mvpMatrix, int angleXRotate, int angleYRotate, float scale, glm::vec3 transVec3, float ratio);void OnSurfaceChanged(int width, int height);
private:GLuint program;GLuint vertexShaderHandle;GLuint fragShaderHandle;GLuint m_TextureIds[RENDER_IMG_NUM];GLint m_SamplerLoc;GLint m_MVPMatLoc;GLuint m_VaoIds[3];GLuint m_VboIds[3];std::vector<struct ImageTyep> m_vcImage;glm::mat4 m_MVPMatrix;std::vector<glm::vec3> windowsTrans;std::map<GLfloat, glm::vec3> sorted;int m_AngleX;int m_AngleY;int Srceenwidth;int Srceenheight;
};#endif //NINEBLENDING_BLENDING_H

Blending.cpp

//
// Created by CreatWall_zhouwen on 2023/5/15.
//#include "Blending.h"
#include "Util.h"
#include "GLUtil.h"
#include <gtc/matrix_transform.hpp>
Blending* m_pContext = nullptr;
#define TAG "DRAWTEXTURE"
GLfloat boxVertices[] = {//position            //texture coord-0.5f, -0.5f, -0.5f,   0.0f, 0.0f,0.5f, -0.5f, -0.5f,   1.0f, 0.0f,0.5f,  0.5f, -0.5f,   1.0f, 1.0f,0.5f,  0.5f, -0.5f,   1.0f, 1.0f,-0.5f,  0.5f, -0.5f,   0.0f, 1.0f,-0.5f, -0.5f, -0.5f,   0.0f, 0.0f,-0.5f, -0.5f, 0.5f,    0.0f, 0.0f,0.5f, -0.5f, 0.5f,    1.0f, 0.0f,0.5f,  0.5f, 0.5f,    1.0f, 1.0f,0.5f,  0.5f, 0.5f,    1.0f, 1.0f,-0.5f,  0.5f, 0.5f,    0.0f, 1.0f,-0.5f, -0.5f, 0.5f,    0.0f, 0.0f,-0.5f,  0.5f,  0.5f,   1.0f, 0.0f,-0.5f,  0.5f, -0.5f,   1.0f, 1.0f,-0.5f, -0.5f, -0.5f,   0.0f, 1.0f,-0.5f, -0.5f, -0.5f,   0.0f, 1.0f,-0.5f, -0.5f,  0.5f,   0.0f, 0.0f,-0.5f,  0.5f,  0.5f,   1.0f, 0.0f,0.5f,  0.5f,  0.5f,   1.0f, 0.0f,0.5f,  0.5f, -0.5f,   1.0f, 1.0f,0.5f, -0.5f, -0.5f,   0.0f, 1.0f,0.5f, -0.5f, -0.5f,   0.0f, 1.0f,0.5f, -0.5f,  0.5f,   0.0f, 0.0f,0.5f,  0.5f,  0.5f,   1.0f, 0.0f,-0.5f, -0.5f, -0.5f,   0.0f, 1.0f,0.5f, -0.5f, -0.5f,   1.0f, 1.0f,0.5f, -0.5f,  0.5f,   1.0f, 0.0f,0.5f, -0.5f,  0.5f,   1.0f, 0.0f,-0.5f, -0.5f,  0.5f,   0.0f, 0.0f,-0.5f, -0.5f, -0.5f,   0.0f, 1.0f,-0.5f, 0.5f, -0.5f,    0.0f, 1.0f,0.5f, 0.5f, -0.5f,    1.0f, 1.0f,0.5f, 0.5f,  0.5f,    1.0f, 0.0f,0.5f, 0.5f,  0.5f,    1.0f, 0.0f,-0.5f, 0.5f,  0.5f,    0.0f, 0.0f,-0.5f, 0.5f, -0.5f,    0.0f, 1.0f,
};GLfloat flatVertices[] = {5.0f, -0.5f,  5.0f,  2.0f,  0.0f,-5.0f, -0.5f,  5.0f,  0.0f,  0.0f,-5.0f, -0.5f, -5.0f,  0.0f,  2.0f,5.0f, -0.5f,  5.0f,  2.0f,  0.0f,-5.0f, -0.5f, -5.0f,  0.0f,  2.0f,5.0f, -0.5f, -5.0f,  2.0f,  2.0f
};GLfloat windowVertices[] = {0.0f,  0.5f,  0.0f,  0.0f,  0.0f,0.0f, -0.5f,  0.0f,  0.0f,  1.0f,1.0f, -0.5f,  0.0f,  1.0f,  1.0f,0.0f,  0.5f,  0.0f,  0.0f,  0.0f,1.0f, -0.5f,  0.0f,  1.0f,  1.0f,1.0f,  0.5f,  0.0f,  1.0f,  0.0f
};Blending::Blending() {m_SamplerLoc = GL_NONE;m_MVPMatLoc = GL_NONE;m_AngleX = 0;m_AngleY = 0;Srceenwidth =  1080;Srceenheight = 2115;
}Blending::~Blending() {}void Blending::CreateProgram(const char *ver, const char *frag) {LOGD("CreateProgram Enter");// 编译链接用于离屏渲染的着色器程序program = CreateGLProgram(ver, frag, vertexShaderHandle, fragShaderHandle);if (program == GL_NONE){LOGD("FBOSample::Init m_ProgramObj == GL_NONE");return;}LOGD("CreateGLProgram Success");m_SamplerLoc = glGetUniformLocation(program, "s_TextureMap");m_MVPMatLoc = glGetUniformLocation(program, "u_MVPMatrix");//创建VBOglGenBuffers(3, m_VboIds);glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[0]);glBufferData(GL_ARRAY_BUFFER, sizeof(boxVertices), boxVertices, GL_STATIC_DRAW);glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[1]);glBufferData(GL_ARRAY_BUFFER, sizeof(flatVertices), flatVertices, GL_STATIC_DRAW);glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[2]);glBufferData(GL_ARRAY_BUFFER, sizeof(windowVertices), windowVertices, GL_STATIC_DRAW);//创建VAO并绑定VBOglGenVertexArrays(3, m_VaoIds);glBindVertexArray(m_VaoIds[0]);glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[0]);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (const void *) 0);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (const void *) (3* sizeof(GLfloat)));glBindBuffer(GL_ARRAY_BUFFER, GL_NONE);glBindVertexArray(GL_NONE);glBindVertexArray(m_VaoIds[1]);glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[1]);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (const void *) 0);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (const void *) (3* sizeof(GLfloat)));glBindBuffer(GL_ARRAY_BUFFER, GL_NONE);glBindVertexArray(GL_NONE);glBindVertexArray(m_VaoIds[2]);glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[2]);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (const void *) 0);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (const void *) (3* sizeof(GLfloat)));glBindBuffer(GL_ARRAY_BUFFER, GL_NONE);glBindVertexArray(GL_NONE);//创建纹理并绑定数据glGenTextures(RENDER_IMG_NUM, m_TextureIds);for (int i = 0; i < RENDER_IMG_NUM; ++i){glActiveTexture(GL_TEXTURE0 + i);glBindTexture(GL_TEXTURE_2D, m_TextureIds[i]);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_vcImage[i].width, m_vcImage[i].height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_vcImage[i].data);LOGD("width = %d, height = %d",m_vcImage[i].width, m_vcImage[i].height);glBindTexture(GL_TEXTURE_2D, GL_NONE);}//布局参数windowsTrans.push_back(glm::vec3(-1.5f,  0.0f, -0.48f));windowsTrans.push_back(glm::vec3( 1.5f,  0.0f,  0.51f));windowsTrans.push_back(glm::vec3( 0.0f,  0.0f,  0.7f));windowsTrans.push_back(glm::vec3(-0.3f,  0.0f, -2.3f));windowsTrans.push_back(glm::vec3( 0.5f,  0.0f, -0.6f));for (GLuint i = 0; i < windowsTrans.size(); i++){GLfloat distance = std::sqrt(std::pow(windowsTrans[i].x - 0.5f, 2.0f) + std::pow(windowsTrans[i].y - 1.0f, 2.0f) + std::pow(windowsTrans[i].z - 3.0f, 2.0f));sorted[distance] = windowsTrans[i];}
}void Blending::Draw() {float ratio = (float)Srceenwidth / Srceenheight;glClearColor(0.1f, 0.1f, 0.1f, 1.0f);glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glEnable(GL_DEPTH_TEST);//开启深度测试glEnable(GL_BLEND);//开启混合glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//源颜色向量 × alpha + 目标颜色向量 × (1- alpha)glUseProgram(program);glBindVertexArray(m_VaoIds[0]);// Bind the RGBA mapglActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, m_TextureIds[0]);glUniform1i(m_SamplerLoc, 0);UpdateMatrix(m_MVPMatrix, 0, 0, 1.0,  glm::vec3(-1.0f, 0.0f, -1.0f), ratio);glUniformMatrix4fv(m_MVPMatLoc, 1, GL_FALSE, &m_MVPMatrix[0][0]);glDrawArrays(GL_TRIANGLES, 0, 36);UpdateMatrix(m_MVPMatrix, 0, 0, 1.0,  glm::vec3(2.0f, 0.0f, 0.0f), ratio);glUniformMatrix4fv(m_MVPMatLoc, 1, GL_FALSE, &m_MVPMatrix[0][0]);glDrawArrays(GL_TRIANGLES, 0, 36);glBindVertexArray(0);glBindVertexArray(m_VaoIds[1]);// Bind the RGBA mapglActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, m_TextureIds[1]);glUniform1i(m_SamplerLoc, 0);UpdateMatrix(m_MVPMatrix, 0, 0, 1.0, glm::vec3(0.0f,  0.0f,  0.0f), ratio);glUniformMatrix4fv(m_MVPMatLoc, 1, GL_FALSE, &m_MVPMatrix[0][0]);glDrawArrays(GL_TRIANGLES, 0, 6);glBindVertexArray(0);glBindVertexArray(m_VaoIds[2]);// Bind the RGBA mapglActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, m_TextureIds[2]);glUniform1i(m_SamplerLoc, 0);for (auto it = sorted.rbegin(); it != sorted.rend(); ++it){UpdateMatrix(m_MVPMatrix, 0, 0 , 1.0, it->second, ratio);glUniformMatrix4fv(m_MVPMatLoc, 1, GL_FALSE, &m_MVPMatrix[0][0]);glDrawArrays(GL_TRIANGLES, 0, 6);}glBindVertexArray(0);glDisable(GL_DEPTH_TEST);glDisable(GL_BLEND);
}void Blending::getTexturedata(std::vector<struct ImageTyep> vcImagetemp) {m_vcImage = vcImagetemp;
}Blending *Blending::GetInstance() {if (m_pContext == nullptr){m_pContext = new Blending();}return m_pContext;
}void Blending::DestroyInstance() {if (m_pContext){delete m_pContext;m_pContext = nullptr;}
}void Blending::UpdateTransformMatrix(float rotateX, float rotateY, float scaleX, float scaleY) {m_AngleX = static_cast<int>(rotateX);m_AngleY = static_cast<int>(rotateY);
}void Blending::UpdateMatrix(glm::mat4 &mvpMatrix, int angleXRotate, int angleYRotate, float scale,glm::vec3 transVec3, float ratio) {LOGD("BlendingSample::UpdateMatrix angleX = %d, angleY = %d, ratio = %f", angleXRotate,angleYRotate, ratio);angleXRotate = angleXRotate % 360;angleYRotate = angleYRotate % 360;//转化为弧度角float radiansX = static_cast<float>(MATH_PI / 180.0f * angleXRotate);float radiansY = static_cast<float>(MATH_PI / 180.0f * angleYRotate);// Projection matrix//glm::mat4 Projection = glm::ortho(-ratio, ratio, -1.0f, 1.0f, 0.0f, 100.0f);//glm::mat4 Projection = glm::frustum(-ratio, ratio, -1.0f, 1.0f, 4.0f, 100.0f);glm::mat4 Projection = glm::perspective(45.0f, ratio, 0.1f, 100.f);// View matrixglm::mat4 View = glm::lookAt(glm::vec3(0.5, 1, 3), // Camera is at (0,0,1), in World Spaceglm::vec3(0, 0, 0), // and looks at the originglm::vec3(0, 1, 0)  // Head is up (set to 0,-1,0 to look upside-down));// Model matrixglm::mat4 Model = glm::mat4(1.0f);Model = glm::scale(Model, glm::vec3(scale, scale, scale));Model = glm::rotate(Model, radiansX, glm::vec3(1.0f, 0.0f, 0.0f));Model = glm::rotate(Model, radiansY, glm::vec3(0.0f, 1.0f, 0.0f));Model = glm::translate(Model, transVec3);mvpMatrix = Projection * View * Model;
}void Blending::OnSurfaceChanged(int width, int height) {Srceenwidth = width;Srceenheight = height;LOGD("OnSurfaceChanged Srceenwidth = %d, Srceenheight = %d, ratio = %f", Srceenwidth,Srceenheight);
}

#


http://www.ppmy.cn/news/258783.html

相关文章

Apache Solr 教程_编程入门自学教程_菜鸟教程-免费教程分享

教程简介 Apache Solr 是一个开源搜索服务器。Solr 是用 Java 语言开发的&#xff0c;主要基于 HTTP 和 Apache Lucene 实现。存储在 Apache Solr 中的资源存储为 Document 对象。 Apache Solr入门教程 - 从基本概念开始&#xff0c;简单易学地了解Apache Solr&#xff0c;其…

【springboot项目开发】文件上传与下载

目录 总体介绍 文件上传 介绍 文件上传的前端需求 文件上传的前端代码 文件上传的后端需求 文件上传的后端代码 文件下载 介绍 前端需求 前端代码 后端需求 后端代码 总体介绍 文件的上传和下载功能&#xff0c;是项目开发过程中比较常见的业务需求&#xff0c;我们…

Vue.js 中的 $refs 和 $emit 有什么关系?

Vue.js 中的 $refs 和 $emit 有什么关系&#xff1f; 在 Vue.js 中&#xff0c;$refs 和 $emit 都是非常常用的 API。$refs 用于访问组件、元素和子组件等&#xff0c;而 $emit 则用于在组件之间进行通信。本文将会从语法、使用方式、适用场景等方面进行介绍&#xff0c;并探讨…

惠普打印机驱动下载安装后不能使用,驱动人生解决方案

驱动人生收到很多用户咨询&#xff0c;新买的打印机应该如何安装驱动? 今天驱动人生就来给大家介绍一下打印机驱动的安装方法。 一、分辨打印机型号 先找到相应品牌的打印机&#xff0c;具体可以从对应品牌打印机的官网下载打印机驱动程序&#xff0c;或者使用万能驱动下载…

惠普HP Ink Tank 118 打印机驱动

惠普HP Ink Tank 118 打印机驱动是官方提供的一款打印机驱动&#xff0c;本站收集提供高速下载&#xff0c;用于解决打印机与电脑连接不了&#xff0c;无法正常使用的问题&#xff0c;本动适用于&#xff1a;Windows XP / Windows 7 / Windows 8 / Windows 10 32/64位操作系统。…

惠普HP Color Inkjet 1000 打印机驱动

惠普HP Color Inkjet 1000 打印机驱动是官方提供的一款打印机驱动&#xff0c;本站收集提供高速下载&#xff0c;用于解决打印机与电脑连接不了&#xff0c;无法正常使用的问题&#xff0c;本动适用于&#xff1a;Windows XP / Windows 7 / Windows 8 / Windows 10 32/64位操作…

惠普HP LaserJet Pro 400 M401d 打印机驱动

惠普HP LaserJet Pro 400 M401d 打印机驱动是官方提供的一款打印机驱动&#xff0c;本站收集提供高速下载&#xff0c;用于解决打印机与电脑连接不了&#xff0c;无法正常使用的问题&#xff0c;本动适用于&#xff1a;Windows XP / Windows 7 / Windows 8 / Windows 10 32/64位…

惠普HP Color Laser 150a 打印机驱动

惠普HP Color Laser 150a 打印机驱动是官方提供的一款打印机驱动&#xff0c;本站收集提供高速下载&#xff0c;用于解决打印机与电脑连接不了&#xff0c;无法正常使用的问题&#xff0c;本动适用于&#xff1a;Windows XP / Windows 7 / Windows 8 / Windows 10 32/64位操作系…