您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
8. program渲染程序初始化给shader传递顶点和材质顶点数据~1
发布时间:2021-06-07 16:26:37编辑:雪饮阅读()
顶点坐标的程序的渲染和材质坐标程序的渲染,主要区别于顶点坐标比材质坐标多了一个z轴。
主要流程是创建渲染程序,加入对应着色器、链接程序、激活指定属性。
具体实例: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);
/////////////////////////////////////////////////////////////
//创建渲染程序
GLint program = glCreateProgram();
if(program == 0)
{
LOGD("glCreateProgram failed!");
return;
}
//渲染程序中加入着色器代码
glAttachShader(program,vsh);
glAttachShader(program,fsh);
//链接程序
glLinkProgram(program);
GLint status = 0;
glGetProgramiv(program,GL_LINK_STATUS,&status);
if(status != GL_TRUE)
{
LOGD("glLinkProgram failed!");
return;
}
//使用程序对象program作为当前渲染状态的一部分
glUseProgram(program);
LOGD("glLinkProgram success!");
/////////////////////////////////////////////////////////////
//加入三维顶点数据两个三角形组成正方形,顶点信息,参数顺序“Z”字形右下到左上
static float vers[] = {
1.0f,-1.0f,0.0f,
-1.0f,-1.0f,0.0f,
1.0f,1.0f,0.0f,
-1.0f,1.0f,0.0f,
};
//获取顶点坐标,根据可以名称,这里是aPosition,对应定义于上面的vertexShader中
GLuint apos = (GLuint)glGetAttribLocation(program,"aPosition");
//启用指定属性
glEnableVertexAttribArray(apos);
/*传递顶点
* size:一个点有多少个数据,例如一个坐标是x,y,z则size为3
* 存储格式GL_FLOAT
* 反向向量没有,则使用GL_FALSE
* stride:每个值的间隔,这里总共有3个数据,每个数据为4个字节,则总共12个字节
* */
glVertexAttribPointer(apos,3,GL_FLOAT,GL_FALSE,12,vers);
//加入材质坐标数据,同样"Z"字形,右下到左上,只是材质坐标没有z轴
static float txts[] = {
1.0f,0.0f ,
0.0f,0.0f,
1.0f,1.0f,
0.0,1.0
};
GLuint atex = (GLuint)glGetAttribLocation(program,"aTexCoord");
glEnableVertexAttribArray(atex);
glVertexAttribPointer(atex,2,GL_FLOAT,GL_FALSE,8,txts);
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);
/////////////////////////////////////////////////////////////
//创建渲染程序
GLint program = glCreateProgram();
if(program == 0)
{
LOGD("glCreateProgram failed!");
return;
}
//渲染程序中加入着色器代码
glAttachShader(program,vsh);
glAttachShader(program,fsh);
//链接程序
glLinkProgram(program);
GLint status = 0;
glGetProgramiv(program,GL_LINK_STATUS,&status);
if(status != GL_TRUE)
{
LOGD("glLinkProgram failed!");
return;
}
//使用程序对象program作为当前渲染状态的一部分
glUseProgram(program);
LOGD("glLinkProgram success!");
/////////////////////////////////////////////////////////////
//加入三维顶点数据两个三角形组成正方形,顶点信息,参数顺序“Z”字形右下到左上
static float vers[] = {
1.0f,-1.0f,0.0f,
-1.0f,-1.0f,0.0f,
1.0f,1.0f,0.0f,
-1.0f,1.0f,0.0f,
};
//获取顶点坐标,根据可以名称,这里是aPosition,对应定义于上面的vertexShader中
GLuint apos = (GLuint)glGetAttribLocation(program,"aPosition");
//启用指定属性
glEnableVertexAttribArray(apos);
/*传递顶点
* size:一个点有多少个数据,例如一个坐标是x,y,z则size为3
* 存储格式GL_FLOAT
* 反向向量没有,则使用GL_FALSE
* stride:每个值的间隔,这里总共有3个数据,每个数据为4个字节,则总共12个字节
* */
glVertexAttribPointer(apos,3,GL_FLOAT,GL_FALSE,12,vers);
//加入材质坐标数据,同样"Z"字形,右下到左上,只是材质坐标没有z轴
static float txts[] = {
1.0f,0.0f ,
0.0f,0.0f,
1.0f,1.0f,
0.0,1.0
};
GLuint atex = (GLuint)glGetAttribLocation(program,"aTexCoord");
glEnableVertexAttribArray(atex);
glVertexAttribPointer(atex,2,GL_FLOAT,GL_FALSE,8,txts);
env->ReleaseStringUTFChars(url_,url);
}
关键字词:program,shader,顶点坐标,材质坐标