OpenGL系列之九:glsl着色器语言

目录

相关文章

OpenGL系列之一:OpenGL第一个程序
OpenGL系列之二:绘制三角形
OpenGL系列之三:三角形顶点增加颜色
OpenGL系列之四:绘制四边形
OpenGL系列之五:绘制点和线
OpenGL系列之六:绘制立方体
OpenGL系列之七:纹理贴图
OpenGL系列之八:立方体纹理贴图

实现效果

实现步骤

1.编写glsl文件

glsl是着色器语言,分为顶点着色器和片元着色器,具体的话我这也不过多介绍了,因为目前我也初学,可以参考以下连接:
https://gitcode.net/mirrors/wshxbqq/GLSL-Card?utm_source=csdn_github_accelerator
https://thebookofshaders.com/?lan=ch
http://www.tastones.com/stackoverflow/glsl/getting-started-with-glsl/first_ogl_4.0_glsl_shader_program/
这里我编写的比较简单,如下所示:
顶点着色器vertex.vert

#version 300 es //指定OpenglES 版本
//需要C代码传入的两个变量
layout(location = 0) in vec4 a_position;
layout(location = 1) in vec4 a_color;
//需要C代码传入的矩阵
uniform mat4   u_mat;
//输出的变量(给片元着色器使用)
out vec4   o_color;

void main(void)
{
    //可以通过这里修改颜色值来改变颜色
    o_color = vec4(a_color.r,a_color.g,a_color.b,a_color.a);
    gl_Position = u_mat * a_position;
}

片元着色器fragment.frag

#version 300 es //指定OpenglES 版本
//指定精度
precision mediump float;
//顶点着色器输出的,变量名需要相同
in vec4   o_color;
//片元着色器输出的,在本案例里就是渲染的颜色
out vec4 fragColor;


void main(void)
{
    fragColor = o_color;
}
2.加载glsl文件

这里进行了封装,基本都是固定的,基本就是加载、连接、设置变量等等,以后也可以直接使用,所以就不过多解释了。
CCOpenGLShader.h


#ifndef CCOPENGLES_CCOPENGLSHADER_H
#define CCOPENGLES_CCOPENGLSHADER_H

#include "CCGLPrimitivesDef.h"

class CCOpenGLShader {

public:
    CCOpenGLShader();
    ~CCOpenGLShader();

    void Bind();
    void Release();

    void InitShadersFromFile(AAssetManager*  pManager, const char* vShader,const char* fshader);

    void DisableAttributeArray(const char *name);
    void EnableAttributeArray(const char *name);
    void SetAttributeBuffer(const char* name,GLenum type, const void *values, int tupleSize, int stride = 0);

    void SetUniformValue(const char* name, int iValue);
    void SetUniformValue(const char* name, GLfloat fValue);
    void SetUniformValue(const char* name, glm::vec3 vecValue);
    void SetUniformValue(const char* name, glm::mat4 matValue);

private:
    int compileShader(AAssetManager*  m_pAssetManager,const char* sPath, GLint sType);
private:
    GLuint m_shaderProgram;
};


#endif //CCOPENGLES_CCOPENGLSHADER_H

CCOpenGLShader.cpp

#include "CCOpenGLShader.h"
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>

CCOpenGLShader::CCOpenGLShader()
{
    m_shaderProgram = 0;
}

CCOpenGLShader::~CCOpenGLShader()
{
}

void CCOpenGLShader::InitShadersFromFile(AAssetManager* pManager,const char* vPath, const char* fPath)
{
    GLuint  vertexId = 0;
    GLuint  fragId = 0;
    vertexId   = compileShader(pManager,vPath ,GL_VERTEX_SHADER);
    fragId     = compileShader(pManager,fPath ,GL_FRAGMENT_SHADER);

    char           message[512];
    int            status = 0;
    m_shaderProgram = glCreateProgram();
    if (vertexId != -1)
    {
        glAttachShader(m_shaderProgram, vertexId);
    }
    if (fragId != -1)
    {
        glAttachShader(m_shaderProgram, fragId);
    }
    glLinkProgram(m_shaderProgram);

    glGetProgramiv(m_shaderProgram, GL_LINK_STATUS, &status);
    if (!status)
    {
        glGetProgramInfoLog(m_shaderProgram, 512, NULL, message);
        LOGE("Get shaderProgram failed: %s",message);
    }
    glDeleteShader(vertexId);
    glDeleteShader(fragId);
}
int CCOpenGLShader::compileShader(AAssetManager*  pManager,const char* fName, GLint sType)
{
    AAsset* file = AAssetManager_open(pManager,fName, AASSET_MODE_BUFFER);
    size_t shaderSize = AAsset_getLength(file);
    char* sContentBuff = (char*)malloc(shaderSize);
    AAsset_read(file, sContentBuff, shaderSize);
    LOGD("SHADERS: %s",sContentBuff);
    unsigned int   shaderID = 0;
    char           message[512]={0};
    int            status = 0;

    shaderID = glCreateShader(sType);
    glShaderSource(shaderID, 1, &sContentBuff, (const GLint *)&shaderSize);
    glCompileShader(shaderID);

    glGetShaderiv(shaderID, GL_COMPILE_STATUS, &status);
    if (!status)
    {
        glGetShaderInfoLog(shaderID, 512, NULL, message);
        LOGF("Compile Shader Status failed: %s",message);
    }

    if(sContentBuff != NULL){
        free(sContentBuff);
        sContentBuff = NULL;
    }

    AAsset_close(file);

    return shaderID;
}


void CCOpenGLShader::Bind()
{
    glUseProgram(m_shaderProgram);
}

void CCOpenGLShader::Release()
{
    glUseProgram(0);
}

void CCOpenGLShader::SetUniformValue(const char* name, int iValue)
{
    glUniform1i(glGetUniformLocation(m_shaderProgram, name), iValue);

}

void CCOpenGLShader::SetUniformValue(const char* name, GLfloat fValue)
{
    glUniform1f(glGetUniformLocation(m_shaderProgram, name), fValue);
}

void CCOpenGLShader::SetUniformValue(const char* name, glm::vec3 vec3Value)
{
    glUniform3fv(glGetUniformLocation(m_shaderProgram, name), 1, glm::value_ptr(vec3Value));
}

void CCOpenGLShader::SetUniformValue(const char* name, glm::mat4 matValue)
{
    glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, name) , 1 , GL_FALSE , glm::value_ptr(matValue));
}

void CCOpenGLShader::EnableAttributeArray(const char *name)
{
    GLuint location = glGetAttribLocation(m_shaderProgram, name);
    glEnableVertexAttribArray(location);
}

void CCOpenGLShader::DisableAttributeArray(const char *name)
{
    GLuint location = glGetAttribLocation(m_shaderProgram, name);
    glDisableVertexAttribArray(location);
}

void CCOpenGLShader::SetAttributeBuffer(const char* name,GLenum type, const void *values, int tupleSize, int stride)
{
    GLuint location = glGetAttribLocation(m_shaderProgram, name);
    glVertexAttribPointer(location,tupleSize,type,GL_FALSE,stride,values);
}

加载的话是根据文件名,获取到Assets文件夹中的文件


extern "C"
JNIEXPORT void JNICALL
Java_com_itfitness_opengldemo_GLRender_ndkInitGL(JNIEnv *env, jobject thiz, jobject assets) {
    ccRender.initGL();
    AAssetManager *astManager = AAssetManager_fromJava (env, assets);
    ccRender.ccOpenGlShader.InitShadersFromFile(astManager,"vertex.vert","fragment.frag");
}

使用的话基本都是固定的步骤,这里就不贴全部代码了,如下绘制函数所示:

/**
 * 画三角
 */
void CCRender::drawTriangle() {

    CCFloat7 triangleVert[] ={
            {0,       0.5,    -3,  1,  0,  0,1.0},
            {-0.5,   -0.5,    -3,  0,  1,  0,1.0},
            {0.5,    -0.5,    -3,  0,  0,  1,1.0},
    };


    m_angle += 0.03f;

    glm::mat4x4  cubeMat;
    glm::mat4x4  cubeTransMat = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -3));
    glm::mat4x4  cubeRotMat = glm::rotate(glm::mat4(1.0f),m_angle,glm::vec3(0.0f, 0.0f, -3.0) );
    glm::mat4x4  cubeScaleMat = glm::scale(glm::mat4(1.0f),glm::vec3(0.3f, 0.2f, 0.3) );

    //透视投影矩阵,跟之前的glOrthof(-1,1,-1,1,0.1,1000);差不多意思,3.0glOrthof这个API没有了
    glm::mat4 projMat = glm::perspective(glm::radians(60.0f), (float)9/(float)18, 0.0f, 1000.0f);
    cubeMat = projMat * cubeRotMat;

    ccOpenGlShader.Bind();

    //这里的变量名与glsl中的一样
    //传递矩阵数据
    ccOpenGlShader.SetUniformValue("u_mat",cubeMat);
    //启动顶点变量
    ccOpenGlShader.EnableAttributeArray("a_position");
    //启动着色变量
    ccOpenGlShader.EnableAttributeArray("a_color");
    
    //为变量设置数据
    ccOpenGlShader.SetAttributeBuffer("a_position",GL_FLOAT,triangleVert,3,sizeof(CCFloat7));
    ccOpenGlShader.SetAttributeBuffer("a_color",GL_FLOAT,&triangleVert[0].r,4,sizeof(CCFloat7));

    glDrawArrays(GL_TRIANGLES,0,3);

    //关闭顶点变量
    ccOpenGlShader.DisableAttributeArray("a_position");
    //关闭着色变量
    ccOpenGlShader.DisableAttributeArray("a_color");

    ccOpenGlShader.Release();
}
3.注意事项

这里与之前的程序不同,使用了opengl es 3.0,其中有些API不能用了与之前程序相比删除了一些API的使用,然后在创建GLSurfaceView的时候也需要指定opengl es 的版本号

val glSurfaceView = GLSurfaceView(this)
glSurfaceView.setEGLContextClientVersion(3)
glSurfaceView.setRenderer(GLRender(this))

案例源码

https://gitee.com/itfitness/opengl-glsl

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容