您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
7. shader初始化完成并编译顶点和片元着色器代码~1
发布时间:2021-06-07 15:18:23编辑:雪饮阅读()
这次主要是封装一个初始化方法对之前创建的片元着色器和顶点着色器进行初始化。
大多数代码都是约定俗成的,没有什么可说的。然而对于一个头文件不得不说。
可以看到这个错误,GLint,如果把这里GLint修改为EGLint则可以解决部分,但是对于glCreateShader方法还是没有获取到。所以靠直觉是不行的。这里最重要的是缺少GLES2/gl2.h头文件。
那么具体的实现如:cpp/native-lib.cpp:
#include <jni.h>
#include <string>
#include <android/log.h>
#include <android/native_window_jni.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#define LOGD(...) __android_log_print(ANDROID_LOG_WARN,"testff",__VA_ARGS__)
//顶点着色器glsl ,一元运算符 # 常称为字符串化运算符,這裏用在宏定義上,則這裏的x會被展開為"x"字面量形式
#define GET_STR(x) #x
static const char *vertexShader = GET_STR(
attribute vec4 aPosition; //顶点坐标
attribute vec2 aTexCoord; //材质顶点坐标
varying vec2 vTexCoord; //输出的材质坐标
void main(){
vTexCoord = vec2(aTexCoord.x,1.0-aTexCoord.y);
gl_Position = aPosition;
}
);
//片元着色器,软解码和部分x86硬解码
static const char *fragYUV420P = GET_STR(
precision mediump float; //精度
varying vec2 vTexCoord; //顶点着色器传递的坐标
uniform sampler2D yTexture; //输入的材质(不透明灰度,单像素)
uniform sampler2D uTexture;
uniform sampler2D vTexture;
void main(){
vec3 yuv;
vec3 rgb;
yuv.r = texture2D(yTexture,vTexCoord).r;
//這裏一般減去0.5去做個四捨五入
yuv.g = texture2D(uTexture,vTexCoord).r - 0.5;
yuv.b = texture2D(vTexture,vTexCoord).r - 0.5;
//一個yuv轉rgb的公式
rgb = mat3(1.0, 1.0, 1.0,
0.0,-0.39465,2.03211,
1.13983,-0.58060,0.0)*yuv;
//输出像素颜色
gl_FragColor = vec4(rgb,1.0);
}
);
GLint InitShader(const char *code,GLint type)
{
//创建shader
GLint sh = glCreateShader(type);
if(sh == 0)
{
LOGD("glCreateShader %d failed!",type);
return 0;
}
//加载shader,最后一个参数代码长度,传0表示直接找到字符串的结尾
glShaderSource(sh,
1, //shader数量
&code, //shader代码
0); //代码长度
//编译shader
glCompileShader(sh);
//获取编译情况
GLint status;
glGetShaderiv(sh,GL_COMPILE_STATUS,&status);
if(status == 0)
{
LOGD("glCompileShader failed!");
return 0;
}
LOGD("glCompileShader success!");
return sh;
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_yuv_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}extern "C"
JNIEXPORT void JNICALL
Java_com_example_yuv_XPlay_Open(JNIEnv *env, jobject thiz, jstring url_, jobject surface) {
const char *url=env->GetStringUTFChars(url_,0);
LOGD("open url is %s",url);
//獲取原始窗口
ANativeWindow *nwin=ANativeWindow_fromSurface(env,surface);
//1 display創建和初始化
EGLDisplay display=eglGetDisplay(EGL_DEFAULT_DISPLAY);
if(display==EGL_NO_DISPLAY){
LOGD("eglGetDisplay failed!");
return;
}
if(EGL_TRUE!=eglInitialize(display,0,0)){
LOGD("eglInitialize failed");
return;
}
//2 surface
//2-1 surface窗口配置
//輸出配置
EGLConfig config;
EGLint configNum;
//c語言數組結束填充,這裏用EGL_NONE
EGLint configSpec[]={
EGL_RED_SIZE,8,
EGL_GREEN_SIZE,8,
EGL_BLUE_SIZE,8,
EGL_SURFACE_TYPE,EGL_WINDOW_BIT,
EGL_NONE
};
//EGL_TRUE的宏定義值為1
if(EGL_TRUE!=eglChooseConfig(display,configSpec,&config,1,&configNum)){
LOGD("eglChooseConfig failed!");
return;
}
//創建surface
EGLSurface winsurface=eglCreateWindowSurface(display,config,nwin,0);
if(winsurface==EGL_NO_SURFACE){
LOGD("eglCreateWindowSurface failed!");
return;
}
//3 context創建關聯的上下文
const EGLint ctxAttr[]={
EGL_CONTEXT_CLIENT_VERSION,2,EGL_NONE
};
//第三個參數是在多個上下文進行共享的時候用的,這裏用不到,所以就是設置為EGL_NO_CONTEXT,最後一個參數是接收一個版本信息
EGLContext context=eglCreateContext(display,config,EGL_NO_CONTEXT,ctxAttr);
if(context==EGL_NO_CONTEXT){
LOGD("eglCreateContext failed!");
}
//上下文關聯起來就可以進行數據的交換,第二和第三個函數是分別用來繪製、讀取的
if(EGL_TRUE!=eglMakeCurrent(display,winsurface,winsurface,context)){
LOGD("eglMakeCurrent failed!");
return;
}
LOGD("EGL Init Success");
//顶点和片元shader初始化
//顶点shader初始化 GL_VERTEX_SHADER表示顶点着色器
GLint vsh = InitShader(vertexShader,GL_VERTEX_SHADER);
//片元yuv420 shader初始化 GL_FRAGMENT_SHADER表示片段着色器或者片元着色器
GLint fsh = InitShader(fragYUV420P,GL_FRAGMENT_SHADER);
env->ReleaseStringUTFChars(url_,url);
}
#include <string>
#include <android/log.h>
#include <android/native_window_jni.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#define LOGD(...) __android_log_print(ANDROID_LOG_WARN,"testff",__VA_ARGS__)
//顶点着色器glsl ,一元运算符 # 常称为字符串化运算符,這裏用在宏定義上,則這裏的x會被展開為"x"字面量形式
#define GET_STR(x) #x
static const char *vertexShader = GET_STR(
attribute vec4 aPosition; //顶点坐标
attribute vec2 aTexCoord; //材质顶点坐标
varying vec2 vTexCoord; //输出的材质坐标
void main(){
vTexCoord = vec2(aTexCoord.x,1.0-aTexCoord.y);
gl_Position = aPosition;
}
);
//片元着色器,软解码和部分x86硬解码
static const char *fragYUV420P = GET_STR(
precision mediump float; //精度
varying vec2 vTexCoord; //顶点着色器传递的坐标
uniform sampler2D yTexture; //输入的材质(不透明灰度,单像素)
uniform sampler2D uTexture;
uniform sampler2D vTexture;
void main(){
vec3 yuv;
vec3 rgb;
yuv.r = texture2D(yTexture,vTexCoord).r;
//這裏一般減去0.5去做個四捨五入
yuv.g = texture2D(uTexture,vTexCoord).r - 0.5;
yuv.b = texture2D(vTexture,vTexCoord).r - 0.5;
//一個yuv轉rgb的公式
rgb = mat3(1.0, 1.0, 1.0,
0.0,-0.39465,2.03211,
1.13983,-0.58060,0.0)*yuv;
//输出像素颜色
gl_FragColor = vec4(rgb,1.0);
}
);
GLint InitShader(const char *code,GLint type)
{
//创建shader
GLint sh = glCreateShader(type);
if(sh == 0)
{
LOGD("glCreateShader %d failed!",type);
return 0;
}
//加载shader,最后一个参数代码长度,传0表示直接找到字符串的结尾
glShaderSource(sh,
1, //shader数量
&code, //shader代码
0); //代码长度
//编译shader
glCompileShader(sh);
//获取编译情况
GLint status;
glGetShaderiv(sh,GL_COMPILE_STATUS,&status);
if(status == 0)
{
LOGD("glCompileShader failed!");
return 0;
}
LOGD("glCompileShader success!");
return sh;
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_yuv_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}extern "C"
JNIEXPORT void JNICALL
Java_com_example_yuv_XPlay_Open(JNIEnv *env, jobject thiz, jstring url_, jobject surface) {
const char *url=env->GetStringUTFChars(url_,0);
LOGD("open url is %s",url);
//獲取原始窗口
ANativeWindow *nwin=ANativeWindow_fromSurface(env,surface);
//1 display創建和初始化
EGLDisplay display=eglGetDisplay(EGL_DEFAULT_DISPLAY);
if(display==EGL_NO_DISPLAY){
LOGD("eglGetDisplay failed!");
return;
}
if(EGL_TRUE!=eglInitialize(display,0,0)){
LOGD("eglInitialize failed");
return;
}
//2 surface
//2-1 surface窗口配置
//輸出配置
EGLConfig config;
EGLint configNum;
//c語言數組結束填充,這裏用EGL_NONE
EGLint configSpec[]={
EGL_RED_SIZE,8,
EGL_GREEN_SIZE,8,
EGL_BLUE_SIZE,8,
EGL_SURFACE_TYPE,EGL_WINDOW_BIT,
EGL_NONE
};
//EGL_TRUE的宏定義值為1
if(EGL_TRUE!=eglChooseConfig(display,configSpec,&config,1,&configNum)){
LOGD("eglChooseConfig failed!");
return;
}
//創建surface
EGLSurface winsurface=eglCreateWindowSurface(display,config,nwin,0);
if(winsurface==EGL_NO_SURFACE){
LOGD("eglCreateWindowSurface failed!");
return;
}
//3 context創建關聯的上下文
const EGLint ctxAttr[]={
EGL_CONTEXT_CLIENT_VERSION,2,EGL_NONE
};
//第三個參數是在多個上下文進行共享的時候用的,這裏用不到,所以就是設置為EGL_NO_CONTEXT,最後一個參數是接收一個版本信息
EGLContext context=eglCreateContext(display,config,EGL_NO_CONTEXT,ctxAttr);
if(context==EGL_NO_CONTEXT){
LOGD("eglCreateContext failed!");
}
//上下文關聯起來就可以進行數據的交換,第二和第三個函數是分別用來繪製、讀取的
if(EGL_TRUE!=eglMakeCurrent(display,winsurface,winsurface,context)){
LOGD("eglMakeCurrent failed!");
return;
}
LOGD("EGL Init Success");
//顶点和片元shader初始化
//顶点shader初始化 GL_VERTEX_SHADER表示顶点着色器
GLint vsh = InitShader(vertexShader,GL_VERTEX_SHADER);
//片元yuv420 shader初始化 GL_FRAGMENT_SHADER表示片段着色器或者片元着色器
GLint fsh = InitShader(fragYUV420P,GL_FRAGMENT_SHADER);
env->ReleaseStringUTFChars(url_,url);
}
最后编译运行输出中只要有“glCompileShader success!”输出即可。
关键字词:shader,gl2.h