OpenGL shader笔记

OpenGL shader笔记

目录

OpenGL shader笔记

uniform

varying

访问顶点

访问顶点--颜色

访问顶点属性--法线  gl_Normal

访问顶点--纹理坐标

attribute

in 与 out

Layout 关键字的使用

多个shader

attribute数组数据的使用

attribute结构体数据的使用

uniform结构体和数组的使用

block快实现多个shader共享数据

out  共享变量

block之内存布局

无数据绘制-常量数组的使用  gl_VertexID

深入理解gl_FragCoord内置变量的作用

纹理动画

纹理帧动画

纹理帧动画GPU实现

  • https://www.khronos.org/registry/OpenGL-Refpages/
  • 着色器程序先编译链接好,然后启用,使用完毕后调用glUseProgram(0);因为OpenGL是状态机,会保存状态。
  • 将顶点数据传入显卡缓存区,着色器使用完后 glDisableClientState
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3,GL_FLOAT,sizeof(Vertex),rect);
glColorPointer(3,GL_FLOAT,sizeof(Vertex),&rect[0].r);
  • 调用着色器干活:
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);

uniform

  • 全局变量
const char* vs  =   "void main()\
                    {\
                        gl_Position = ftransform();\
                    }";
const char* ps  =   "uniform vec4 _color;\
                    void main()\
                    {\
                        gl_FragColor = _color;\
                    }";
createProgram(vs, ps);

_color  =   glGetUniformLocation(_program,"_color");
  • 设置值:
 glUniform4f(_shader._color,0,1,0,1);

varying

  • 着色器之间传递数据
const char* vs  =   "uniform vec4 _color;\
                    varying vec4 outColor;\
                    void main()\
                    {\
                        outColor    =   _color;\
                        gl_Position =   ftransform();
                    }";
const char* ps  = " varying vec4 outColor;\
                    void main()\
                    {\
                        gl_FragColor = outColor;\
                    }";
createProgram(vs, ps);

_color  =   glGetUniformLocation(_program,"_color");

访问顶点

  •  gl_ModelViewProjectionMatrix * gl_Vertex
  • 模型视图投影矩阵 乘以 顶点矩阵 (均为内置变量)
const char* vs  =   "uniform vec4 _color;\
                    varying vec4 outColor;\
                    void main()\
                    {\
                        outColor    =   _color;\
                        gl_Position =   gl_ModelViewProjectionMatrix * gl_Vertex;\
                        //gl_Position =   ftransform();\
                    }";
const char* ps  = " varying vec4 outColor;\
                    void main()\
                    {\
                        gl_FragColor = outColor;\
                    }";

访问顶点--颜色

  • 一个顶点支持多个颜色
  • gl_Color  gl_SecondaryColor 内置变量
const char* vs  =   "varying    vec4    outColor0;\
                    varying     vec4    outColor1;\
                    void main()\
                    {\
                        outColor0   =   gl_Color;\
                        outColor1   =   gl_SecondaryColor;\
                        gl_Position =   gl_ModelViewProjectionMatrix * gl_Vertex;\
                    }";
const char* ps  =   "varying    vec4    outColor0;\
                    varying     vec4    outColor1;\
                    void main()\
                    {\
                        gl_FragColor    =   (outColor1  + outColor0);\
                    }";
  • 使用:
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_SECONDARY_COLOR_ARRAY);

_shader.begin();

glVertexPointer(        3,  GL_FLOAT,   sizeof(Vertex),     rect);
glColorPointer(         4,  GL_UNSIGNED_BYTE,   sizeof(Vertex),     &rect[0].r0);
glSecondaryColorPointer(4,  GL_UNSIGNED_BYTE,   sizeof(Vertex),     &rect[0].r1);

glDrawArrays(GL_TRIANGLE_STRIP,0,4);

_shader.end();

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_SECONDARY_COLOR_ARRAY);

访问顶点属性--法线  gl_Normal

const char* vs  =   "varying vec4 outColor;\
                    void main()\
                    {\
                        outColor    =   vec4(gl_Normal,1);\
                        gl_Position =   gl_ModelViewProjectionMatrix * gl_Vertex;\
                    }";
const char* ps  =   "varying    vec4    outColor;\
                    void main()\
                    {\
                        gl_FragColor    =   outColor;\
                    }";
  • 使用:
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);

glVertexPointer(3, GL_FLOAT, sizeof(Vertex), rect);
glNormalPointer(GL_FLOAT, sizeof(Vertex), &rect[0].nx);

_shader.begin();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
_shader.end();

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);

访问顶点--纹理坐标

  • 关键词:
    • gl_TexCoord[0]  =   gl_MultiTexCoord0;
    • uniform     sampler2D   _texture;
    • vec4    color   =   texture2D(_texture, gl_TexCoord[0].st);  
  • glEnable(GL_TEXTURE_2D); //启用纹理0
  • glBindTexture(GL_TEXTURE_2D,_texure);//绑定纹理0
  • glUniform1i(_shader._texture,0);//给纹理0填充纹理数据
  • glTexCoordPointer(2,GL_FLOAT,   sizeof(Vertex), &rect[0].u); //告诉显卡纹理坐标
const char* vs  =   "uniform    vec4    _color;\
                    varying     vec4    outColor;\
                    void main()\
                    {\
                        outColor        =   _color;\
                        gl_TexCoord[0]  =   gl_MultiTexCoord0;\
                        gl_Position     =   gl_ModelViewProjectionMatrix * gl_Vertex;\
                    }";
const char* ps  =   "varying    vec4        outColor;\
                    uniform     sampler2D   _texture;\
                    void main()\
                    {\
                        vec4    color   =   texture2D(_texture,gl_TexCoord[0].st);\
                        gl_FragColor    =   color;\
                    }";
createProgram(vs, ps);

_color  =   glGetUniformLocation(_program,"_color");
_texture=   glGetUniformLocation(_program,"_texture");
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,_texure);

glUniform4f(_shader._color,1,1,1,1);
glUniform1i(_shader._texture,0);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3,  GL_FLOAT,   sizeof(Vertex), rect);
glTexCoordPointer(2,GL_FLOAT,   sizeof(Vertex), &rect[0].u);

_shader.begin();
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
_shader.end();

attribute

  • 关键词:
    • glGetAttribLocation   glEnableVertexAttribArray 
    • glVertexAttribPointer  glDisableVertexAttribArray
class   ShaderVertex :public GLSLProgram
{
public:
	typedef int     attribute;
public:
	uniform     _ucolor;
	attribute   _position;
	attribute   _color;
public:
	virtual void    initialize()
	{
		const char* vs = "attribute   vec3    _position;\n\
                             attribute   vec3    _color;\n\
                             varying     vec3    _outColor;\n\
                             void main()\n\
                             {\n\
                                _outColor   =   _color;\n\
                                gl_Position =   gl_ModelViewProjectionMatrix * vec4(_position,1.0);\n\
                             }";
		const char* ps = "uniform vec4 _color;\n\
                             varying     vec3    _outColor;\n\
                             void main()\n\
                             {\n\
                                gl_FragColor = vec4(_outColor,1);\n\
                             }";
		createProgram(vs, ps);

		_ucolor = glGetUniformLocation(_program, "_color");
		_position = glGetAttribLocation(_program, "_position");
		_color = glGetAttribLocation(_program, "_color");

	}
}
glUniform4f(_shader._ucolor, 0, 1, 0, 1);

glEnableVertexAttribArray(_shader._position);
glVertexAttribPointer(_shader._position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), rect);

glEnableVertexAttribArray(_shader._color);
glVertexAttribPointer(_shader._color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), &rect[0].r);

_shader.begin();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
_shader.end();
glDisableVertexAttribArray(_shader._position);
  • 【注】对于颜色
struct  Vertex
{
	float   x, y, z;
	unsigned char   r, g, b;
};
  • 其顶点数据为:
Vertex  rect[] =
{
	{10,    10,     0,  255,  0,  0},
	{110,   10,     0,  0,  255,  0},
	{10,    110,    0,  0,  0,  255},
	{110,   110,    0,  255,  0,  255},
};
  • 为了归一化,glVertexAttribPointer(_shader._color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), &rect[0].r);    使用 GL_TRUE,将0-255,转为着色器可识别的0-1的float类型

in 与 out

  • in  可以通过外部给当前阶段输入
  • out 当前阶段vs对下一阶段ps的输出
    • 下一阶段(ps)用in,变量名称类型保持不变
  • 注:这个阶段的输出,一定是下一个阶段的输入
    • 获取和使用还是和atrribute属性一样,建议使用 in out 做声明。
const char* vs  =   "#version 130\n\
                    in   vec3    _position;\n\
                    in   vec3    _color;\n\
                    out  vec3    _outColor;\n\
                    void main()\n\
                    {\n\
                        _outColor   =   _color;\n\
                        gl_Position =   gl_ModelViewProjectionMatrix * vec4(_position,1.0);\n\
                    }";
const char* ps  =   "in  vec3    _outColor;\n\
                    void main()\n\
                    {\n\
                        gl_FragColor = vec4(_outColor,1);\n\
                    }";
createProgram(vs, ps);

_color      =   glGetAttribLocation(_program,"_color");
_position   =   glGetAttribLocation(_program, "_position");
  • 注:
    • 返回值 _color为0  _position为1,这些就是程序当中用到的一些索引,通过这些索引给显卡或者这些变量传递值。
    • uniform是全局变量,每次只能传一个,而atrribute 可以传一个数组,数组大小是由,如glDrawArrays最后一个值决定,个数不定。

Layout 关键字的使用

  • _position  _color这些值是通过程序glGetAttribLocation去获取到的,有没有办法统一?
  • 可以不使用glGetAttribLocation获取,使用layout
layout(location = 0) in   vec3    _position;\n\
layout(location = 1) in   vec3    _color;\n\

这个里面location是多少,对应的glVertexAttribPointer第一个参数就给多少。

glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(Vertex),rect);
glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof(Vertex),&rect[0].r);
  • #version 330 core == #version 330  加不加core一样,除非加compatibility
  • #version 330 compatibility 兼容老的版本(gl_ModelViewProjectionMatrix)可用
  • 在新的版本中没有gl_ModelViewProjectionMatrix ,所有采用传入矩阵
  • 下面这些新的版本不提供了:
//! 指定以下的操作针对投影矩阵
glMatrixMode(GL_PROJECTION);
//! 将投影矩阵清空成单位矩阵
glLoadIdentity();
glOrtho(0,_width,_height,0,-100,100);
  • 自己创建矩阵传入着色器程序
CELL::matrix4   prj =   CELL::ortho<float>(0,_width,_height,0,-100,100);
glUniformMatrix4fv(_shader._mvp,1,GL_FALSE,prj.data());  //GL_FALSE 不做转置

Layout 关键字修饰out(至少需要410这个版本)

  • 之前 in 和 out 配合使用需要变量名称一样,现在只需要layout(location =  )中的值一致就可以了,名称不需要一致了
  • layout 值有上限 

Layout 关键字修饰uniform(至少需要430这个版本)

const char* vs  =   "#version 430 \n\
                    layout(location = 0) in     vec3    _position;\n\
                    layout(location = 1) in     vec3    _color;\n\
                    layout(location = 2) in     vec2    _uv;\n\
                    layout(location = 0) uniform mat4    _mvp;\n\
                    layout(location = 0) out    vec3    _outColor;\n\
                    layout(location = 1) out    vec2    _outUV;\n\
                    void main()\n\
                    {\n\
                        _outColor   =   _color;\n\
                        _outUV      =   _uv;\n\
                        gl_Position =   _mvp * vec4(_position,1.0);\n\
                    }";
const char* ps =    "#version 430 \n\
                    layout(location = 0)  in    vec3    _inColor;\n\
                    layout(location = 1)  in    vec2    _inUV;\n\
                    layout(location = 1) uniform sampler2D   _tex;\n\
                    void main()\n\
                    {\n\
                        vec4    color = texture2D(_tex,_inUV);\n\
                        gl_FragColor = color * vec4(_inColor,1);\n\
                    }";
struct  Vertex
{
    float   x,y,z;
    float   r,g,b;
    float   u,v;
};


_shader.begin();
glUniform1i(_shader._tex,0);
glUniformMatrix4fv(0,1,GL_FALSE,prj.data());

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(Vertex),rect);
glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof(Vertex),&rect[0].r);
glVertexAttribPointer(2,2,GL_FLOAT,GL_FALSE,sizeof(Vertex),&rect[0].u);

glDrawArrays(GL_TRIANGLE_STRIP,0,4);

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
_shader.end();

多个shader

_shader.begin();
{
    glUniform1i(_shader._tex, 0);
    glUniformMatrix4fv(0, 1, GL_FALSE, prj.data());

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), rect);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), &rect[0].r);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &rect[0].u);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);
}

_shader.end();


_shader1.begin();
{
    glUniformMatrix4fv(0, 1, GL_FALSE, prj.data());

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), rect);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), &rect[0].r);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &rect[0].u);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);
}
_shader1.end();

优化:链接完生成可执行程序后删除中间文件

//链接程序  
glLinkProgram(_program);

glGetProgramiv(_program, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
{
    glGetProgramInfoLog(_program, sizeof(compileLog), 0, compileLog);
    break;
}
result = true;
if (_vHandle != -1)
{
    glDeleteShader(_vHandle);
    _vHandle    =   -1;
}
if (_pHandle != -1)
{
    glDeleteShader(_pHandle);
    _pHandle    =   -1;
}

attribute数组数据的使用

  • 例如:颜色和位置合并为一个数组
const char* vs  =   "#version 430 \n\
                    layout(location = 0) in     vec3    _posAndColor[4];\n\
                    layout(location = 1) in     vec2    _uv;\n\
                    layout(location = 0) uniform mat4   _mvp;\n\
                    layout(location = 0) out    vec3    _outColor;\n\
                    layout(location = 1) out    vec2    _outUV;\n\
                    void main()\n\
                    {\n\
                        _outColor   =   _posAndColor[1] + _posAndColor[2] + _posAndColor[3];\n\
                        _outUV      =   _uv;\n\
                        gl_Position =   _mvp * vec4(_posAndColor[0],1.0);\n\
                    }";

//获取
_position   =   glGetAttribLocation(_program,"_posAndColor[0]");
_color      =   glGetAttribLocation(_program,"_posAndColor[1]");
_uv         =   glGetAttribLocation(_program,"_uv");
  • layout(location = 0 in     vec3    _posAndColor[4]
    • 如果使用过程中只使用了两个,那么编译时就会优化掉未使用的两个,则uv为2,如果_posAndColor[4]四个都使用,则uv为4。
  • 如果使用layout,要会算下一个layout的索引值。
  • 所有的属性值加起来不能超过16个

attribute结构体数据的使用

  • 不能直接通过结构体名称获取结构体,需要通过结构体字段获取
    •  _position   =   glGetAttribLocation(_program,"_vert");   //_position 为 -1
const char* vs  =   "#version 430 \n\
                    struct VertAttr\n\
                    {\n\
                        vec3 _pos;\n\
                        vec3 _color;\n\
                        float _test[4];\n\
                    };\n\
                    in     VertAttr _vert;\n\
                    in     vec2     _uv;\n\
                    layout(location = 0) uniform mat4   _mvp;\n\
                    layout(location = 0) out    vec3    _outColor;\n\
                    layout(location = 1) out    vec2    _outUV;\n\
                    void main()\n\
                    {\n\
                        _outColor   =   _vert._color * _vert._test[0] * _vert._test[1] * _vert._test[2]  *_vert._test[3];\n\
                        _outUV      =   _uv;\n\
                        gl_Position =   _mvp * vec4(_vert._pos,1.0);\n\
                    }";
const char* ps =    "#version 430 \n\
                    layout(location = 0)  in    vec3    _inColor;\n\
                    layout(location = 1)  in    vec2    _inUV;\n\
                    layout(location = 1) uniform sampler2D   _tex;\n\
                    void main()\n\
                    {\n\
                        vec4    color = texture2D(_tex,_inUV);\n\
                        gl_FragColor = color * vec4(_inColor,1);\n\
                    }";
					
_position   =   glGetAttribLocation(_program,"_vert._pos");		  //0			
_color      =   glGetAttribLocation(_program,"_vert._color");	  //1			
_color      =   glGetAttribLocation(_program,"_vert._test[0]");	  //2	 		
_uv         =   glGetAttribLocation(_program,"_uv");		      //6			
  • 注:VertAttr 占6个索引,如果其中某些在着色器程序的代码中没有使用,就会被编译器优化掉。    

uniform结构体和数组的使用

  • uniform最多有1024个
  • 传100个矩阵给GPU也是耗时的,将矩阵数据直接存储到显卡当中,直接访问,使用UBO技术
const char* vs  =   "#version 430 \n\
                    struct VertAttr\n\
                    {\n\
                        vec3 _pos;\n\
                        vec3 _color;\n\
                    };\n\
                    struct MVP\n\
                    { \n\
                        mat4  _mat;\n\
                        float _scaler;\n\
                    };\n\
                    in     VertAttr _vert;\n\
                    in     vec2     _uv;\n\
                    uniform MVP     _mvp;\n\
                    layout(location = 0) out    vec3    _outColor;\n\
                    layout(location = 1) out    vec2    _outUV;\n\
                    void main()\n\
                    {\n\
                        _outColor   =   _vert._color * _mvp._scaler;\n\
                        _outUV      =   _uv;\n\
                        gl_Position =   _mvp._mat * vec4(_vert._pos,1.0);\n\
                    }";

_mvp        =   glGetUniformLocation(_program,"_mvp._mat");   //从内存拷贝到显存,需要消耗CPU资源
GLuint s    =   glGetUniformLocation(_program,"_mvp._scaler");

block快实现多个shader共享数据

  • 解决频繁的的从内存拷贝数据到显存
  • 在不同多个shader之间共享一个变量(前面uniform是全局变量,只是针对程序之间的)
  • 块声明,类似结构体
uniform/in/out  MVP
{ 
    mat4  _mat;
}mvp;
  • 块的名称:MVP    变量名称:mvp
  • 不能用 glGetUniformLocation 访问,得用 glGetUniformBlockIndex,参数是块的名称(如MVP)
  • 不能像之前  glUniformMatrix4fv(0,1,GL_FALSE,prj.data()); 直接传值
  • 需要声明缓冲区

const char* vs  =   "#version 430 \n\
                    struct VertAttr\n\
                    {\n\
                        vec3 _pos;\n\
                        vec3 _color;\n\
                    };\n\
                    uniform MVP\n\
                    { \n\
                        mat4  _mat;\n\
                    }mvp;\n\
                    in     VertAttr _vert;\n\
                    in     vec2     _uv;\n\
                    layout(location = 0) out    vec3    _outColor;\n\
                    layout(location = 1) out    vec2    _outUV;\n\
                    void main()\n\
                    {\n\
                        _outColor   =   _vert._color;\n\
                        _outUV      =   _uv;\n\
                        gl_Position =   mvp._mat * vec4(_vert._pos,1.0);\n\
                    }";
const char* ps =    "#version 430 \n\
                    layout(location = 0)  in    vec3    _inColor;\n\
                    layout(location = 1)  in    vec2    _inUV;\n\
                    layout(location = 1) uniform sampler2D   _tex;\n\
                    void main()\n\
                    {\n\
                        vec4    color = texture2D(_tex,_inUV);\n\
                        gl_FragColor = color * vec4(_inColor,1);\n\
                    }";
createProgram(vs, ps);

//_mvp        =   glGetUniformLocation(_program,"mvp._mat");
_mvp        =   glGetUniformBlockIndex(_program,"MVP");
_tex        =   glGetUniformLocation(_program,"_tex");
_position   =   glGetAttribLocation(_program,"_vert._pos");
_color      =   glGetAttribLocation(_program,"_vert._color");
_uv         =   glGetAttribLocation(_program,"_uv");
GLuint          _ubo;

// 创建uniform buffer object    【绑定进行操作后解绑(每次只能操作一块数据)】
glGenBuffers(1,&_ubo);   //这个buffer不在任何显卡中间,只是一个名称
glBindBuffer(GL_UNIFORM_BUFFER,_ubo);  //指明buffer类型为GL_UNIFORM_BUFFER
glBufferData(GL_UNIFORM_BUFFER,sizeof(CELL::matrix4),0,GL_DYNAMIC_DRAW); //分配空间  GL_DYNAMIC_DRAW 动态向buffer传数据
glBindBuffer(GL_UNIFORM_BUFFER,0);//用完之后绑定为0,避免对后续操作产生影响

//缓存区填充投影矩阵数据
CELL::matrix4   prj =   CELL::ortho<float>(0,_width,_height,0,-100,100);
glBindBuffer(GL_UNIFORM_BUFFER,_ubo);
glBufferSubData(GL_UNIFORM_BUFFER,0,sizeof(CELL::matrix4),prj.data());

//绑定点这个数字作为 shader中的block 和内存中创建的buffer的映射桥梁
glUniformBlockBinding(_shader._program,_shader._mvp,1); //绑定点的值,可以任意指定一个数字(0,1,2....)
//告诉uniform block 数据从哪里来,从绑定点来,绑定点数据从_ubo来
glBindBufferBase(GL_UNIFORM_BUFFER,1,_ubo); //绑定点和创建的buffer关联起来 

out  共享变量

  • 在vs和ps之间做共享变量,但是不能在attribute也就是属性变量中使用它
out    block
{
    vec3    _color; 
    vec2    _uv; 
}Out;
  • 在vs和PS之间共享block变量
const char* vs  =   "#version 430 \n\
                    struct VertAttr\n\
                    {\n\
                        vec3 _pos;\n\
                        vec3 _color;\n\
                    };\n\
                    uniform MVP\n\
                    { \n\
                        mat4  _mat;\n\
                    }mvp;\n\
                    in      VertAttr _vert;\n\
                    in      vec2     _uv;\n\
                    out     block\n\
                    {\n\
                        vec3    _color; \n\
                        vec2    _uv; \n\
                    }Out;\n\
                    void main()\n\
                    {\n\
                        Out._color  =   _vert._color;\n\
                        Out._uv     =   _uv;\n\
                        gl_Position =   mvp._mat * vec4(_vert._pos,1.0);\n\
                    }";
const char* ps =    "#version 430 \n\
                    in     block\n\
                    {\n\
                        vec3    _color; \n\
                        vec2    _uv; \n\
                    }In;\n\
                    layout(location = 1) uniform sampler2D   _tex;\n\
                    void main()\n\
                    {\n\
                        vec4    color = texture2D(_tex,In._uv);\n\
                        gl_FragColor = color * vec4(In._color,1);\n\
                    }";
  • 注:对于in      VertAttr _vert;   in      vec2     _uv;这种后面通过glGetUniformLocation,glGetAttribLocation,获取的变量不能声明为block。

block之内存布局

  • 如果block存在矩阵,布尔值,整型等,会存在内存布局问题
  • 目前存在这样几种
    • shared​(默认), packed​(可选), std140​(版本140), and std430
    • 重点第一种和std140
  • std140:
ayout (std140) uniform ExampleBlock
{
    			//base alignment  aligned offset
    float value;     	// 4    // 0 
    vec3 vector;     	// 16  // 16  (must be multiple of 16)
    mat4 matrix;    	 // 16  // 32  (column 0)
                     		// 16  // 48  (column 1)
                    		 // 16  // 64  (column 2)
                     		// 16  // 80  (column 3)
    float values[3]; 	// 16  // 96  (values[0])
                     		// 16  // 112 (values[1])
                    	 	// 16  // 128 (values[2])
    bool boolean;    	// 4   // 144
    int integer;     	// 4   // 148
};

const char* vs  =   "#version 430 \n\
                    struct VertAttr\n\
                    {\n\
                        vec3 _pos;\n\
                        vec3 _color;\n\
                    };\n\
                    layout(std140) uniform MVP\n\
                    { \n\
                        mat4    _prj;\n\
                        mat4    _view;\n\
                        mat4    _model;\n\
                        float   _iData;\n\
                        float   _fData;\n\
                        float   _data[2];\n\
                        float   _bData;\n\
                    }mvp;\n\
                    in      VertAttr _vert;\n\
                    in      vec2     _uv;\n\
                    out     block\n\
                    {\n\
                        vec3    _color; \n\
                        vec2    _uv; \n\
                    }Out;\n\
                    void main()\n\
                    {\n\
                        Out._color  =   _vert._color;\n\
                        Out._uv     =   _uv;\n\
                        Out._uv     *=  mvp._iData;\n\
                        Out._uv     *=  mvp._fData;\n\
                        Out._uv     *=  mvp._bData;\n\
                        Out._uv     *=  mvp._data[0];\n\
                        Out._uv     *=  mvp._data[1];\n\
                        gl_Position =   mvp._prj* mvp._view * mvp._model* vec4(_vert._pos,1.0);\n\
                    }";
const char* ps =    "#version 430 \n\
                    in     block\n\
                    {\n\
                        vec3    _color; \n\
                        vec2    _uv; \n\
                    }In;\n\
                    layout(location = 1) uniform sampler2D   _tex;\n\
                    void main()\n\
                    {\n\
                        vec4    color = texture2D(_tex,In._uv);\n\
                        gl_FragColor = color * vec4(In._color,1);\n\
                    }";
createProgram(vs, ps);

//获取块
_mvp        =   glGetUniformBlockIndex(_program,"MVP");

//获取块大小
GLint   blockSize;
glGetActiveUniformBlockiv(_program, _mvp,GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);

//获取字段信息
char*   names[]     =   {"MVP._prj","MVP._view","MVP._model","MVP._iData","MVP._fData","MVP._data","MVP._bData"};
GLuint  indexs[7]   =   {0};
glGetUniformIndices(_program,7,names,indexs);

//获取字段偏移信息
GLint offset[7];
glGetActiveUniformsiv(_program,7, indexs, GL_UNIFORM_OFFSET, offset);
_tex        =   glGetUniformLocation(_program,"_tex");
_position   =   glGetAttribLocation(_program,"_vert._pos");
_color      =   glGetAttribLocation(_program,"_vert._color");
_uv         =   glGetAttribLocation(_program,"_uv");

无数据绘制-常量数组的使用  gl_VertexID

const char* vs  =   "#version 130\n\
                    uniform mat4    _mvp;\n\
                    const vec3      _pos[4]=    vec3[](\n\
                                                vec3(10,10,0),\n\
                                                vec3(410,10,0),\n\
                                                vec3(10,410,0),\n\
                                                vec3(410,410,0));\n\
                    void main()\n\
                    {\n\
                        gl_Position =   _mvp * vec4(_pos[gl_VertexID],1.0);\n\
                    }";
const char* ps  =   "void main()\n\
                    {\n\
                        gl_FragColor = vec4(1,0,0,1);\n\
                    }";
_mvp        =   glGetUniformLocation(_program,"_mvp");
_shader.begin();
glUniformMatrix4fv(_shader._mvp,1,GL_FALSE,prj.data());
glDrawArrays(GL_TRIANGLE_STRIP,0,4);    //gl_VertexID 取值0-3
_shader.end();

深入理解gl_FragCoord内置变量的作用

  • gl_FragCoord.x 屏幕坐标 左下角为0,0。
  • discard 返回后面流水线不执行。
  • 画一个图形画了两次,一次正面,一次背面。
const char* vs  =   "#version 130\n\
                    uniform mat4    _mvp;\n\
                    const vec3      _pos[4] = vec3[](\n\
                    vec3(10,    10,     0),\n\
                    vec3(410,   10,     0),\n\
                    vec3(10,    410,    0),\n\
                    vec3(410,   410,    0));\n\
                    void main()\n\
                    {\n\
                        gl_Position =   _mvp * vec4(_pos[gl_VertexID],1.0);\n\
                    }";
const char* ps  =   "void main()\n\
                    {\n\
                        if(gl_FragCoord.x > 100) discard;\n\
                        //glEnable(GL_CULL_FACE);\n\
                        //glCullFace(GL_BACK);\n\
                        gl_FragColor = gl_FrontFacing ? vec4(1,0,0,1) : vec4(0,1,0,1);\n\
                    }";
createProgram(vs, ps);

_mvp        =   glGetUniformLocation(_program,"_mvp");
virtual void    onInitGL()
{
    glewInit();
    _shader.initialize();
	
	//裁剪背面
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
}

//旋转观察
virtual void    render()
{
static  float   angle   =   0;
angle   +=  0.1f;
    CELL::matrix4   matRot;
    matRot.rotateYXZ(angle,angle,angle);
    CELL::matrix4   prj =   CELL::ortho<float>(0,_width,_height,0,-100,100);
    CELL::matrix4   mvp =   prj * matRot;
    _shader.begin();
    glUniformMatrix4fv(_shader._mvp,1,GL_FALSE,mvp.data());
    glDrawArrays(GL_TRIANGLE_STRIP,0,4);
    _shader.end();
}

纹理动画

class   ShaderVertex :public GLSLProgram
{
public:
    uniform     _mvp;
    uniform     _texture;
    uniform     _uvOffset;
    attribute   _pos;
    attribute   _uv;
public:
    virtual void    initialize()
    {
        const char* vs  =   "#version 130\n\
                            uniform mat4    _mvp;\n\
                            in  vec3    _pos;\n\
                            in  vec2    _uv;\n\
                            out vec2    _outUV;\n\
                            void main()\n\
                            {\n\
                                _outUV  =   _uv;\n\
                                gl_Position =   _mvp * vec4(_pos,1.0);\n\
                            }";
        const char* ps  =   "uniform sampler2D _texture;\n\
                            uniform vec2    _uvOffset;\n\
                            in vec2    _outUV;\n\
                            void main()\n\
                            {\n\
                                gl_FragColor = texture2D(_texture,_outUV + _uvOffset);\n\
                            }";
        createProgram(vs, ps);

        _mvp        =   glGetUniformLocation(_program,"_mvp");
        _texture    =   glGetUniformLocation(_program,"_texture");
        _uvOffset   =   glGetUniformLocation(_program,"_uvOffset");
        _pos        =   glGetAttribLocation(_program,"_pos");
        _uv         =   glGetAttribLocation(_program,"_uv");
    }
}
ShaderVertex    _shader;
GLuint          _texure;
CELL::float2    _uvOffset;


//启用纹理
glEnable(GL_TEXTURE_2D);

//创建纹理
unsigned    createTexture(int w, int h, const void* data, GLenum type)
{
    unsigned    texId;
    glGenTextures(1, &texId);
    glBindTexture(GL_TEXTURE_2D, texId);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    glTexImage2D(GL_TEXTURE_2D, 0, type, w, h, 0, type, GL_UNSIGNED_BYTE, data);
    return  texId;
}

_texure =   createTextureFromImage(resPath);


_uvOffset.x +=  0.01f;
_uvOffset.y -=  0.01f;
CELL::matrix4   prj =   CELL::ortho<float>(0,_width,_height,0,-100,100);
//绑定纹理
glBindTexture(GL_TEXTURE_2D,_texure);

_shader.begin();
glUniformMatrix4fv(_shader._mvp,1,GL_FALSE,prj.data());

//传入纹理数据 
glUniform1i(_shader._texture,0);
glUniform2f(_shader._uvOffset,_uvOffset.x,_uvOffset.y);
glVertexAttribPointer(_shader._pos,3,   GL_FLOAT,GL_FALSE,sizeof(Vertex),rect);
glVertexAttribPointer(_shader._uv,2,    GL_FLOAT,GL_FALSE,sizeof(Vertex),&rect[0].u);

glDrawArrays(GL_TRIANGLE_STRIP,0,4);
_shader.end();

纹理帧动画

_hasElasped += fElapsed;     //累计运行多少时间
Vertex  rect[] =
{
	{10,    10,     0,  0,  0},
	{410,   10,     0,  1,  0},
	{10,    410,    0,  0,  1},
	{410,   410,    0,  1,  1},
};

CELL::matrix4   prj = CELL::ortho<float>(0, _width, _height, 0, -100, 100);
glBindTexture(GL_TEXTURE_2D, _texure);
//_hasElasped 是double类型,取值如2.123325
int     frame = int(_hasElasped * 16) % 16; //_hasElasped * 16  _hasElasped秒总共播放了多少帧,模16计算当前为哪帧
//int     frame   =   int(_hasElasped * 12)%16; 
float2  uvSize(0.25f, 0.25f);  //每张纹理大小
int     row = frame / 4;  //哪一行 
int     col = frame % 4;  //哪一列

for (size_t i = 0; i < 4; ++i)  //缩小UV,遍历原纹理,把原纹理的一部分贴到目标区域
{
	rect[i].u *= 0.25f;
	rect[i].v *= 0.25f;

	rect[i].u += 0.25 * col;   //计算列位置
	rect[i].v += 0.25 * row;   //计算行位置
}

_shader.begin();
glUniformMatrix4fv(_shader._mvp, 1, GL_FALSE, prj.data());
//给shader传值
glUniform1i(_shader._texture, 0);
glUniform2f(_shader._uvOffset, _uvOffset.x, _uvOffset.y);
glVertexAttribPointer(_shader._pos, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), rect);
glVertexAttribPointer(_shader._uv, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &rect[0].u);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
_shader.end();

纹理帧动画GPU实现

_hasElasped += fElapsed;
Vertex  rect[] =
{
	{10,    10,     0,  0,  1},
	{410,   10,     0,  1,  1},
	{10,    410,    0,  0,  0},
	{410,   410,    0,  1,  0},
};

CELL::matrix4   prj = CELL::ortho<float>(0, _width, _height, 0, -100, 100);
glBindTexture(GL_TEXTURE_2D, _texure);

int     frame = int(_hasElasped * 16) % 16;
_shader.begin();
glUniformMatrix4fv(_shader._mvp, 1, GL_FALSE, prj.data());
glUniform1i(_shader._texture, 0);
glUniform3f(_shader._animInfor, 4, 4, frame); //当前帧编号,这里4, 4指4纹理贴图4行4列
glVertexAttribPointer(_shader._pos, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), rect);
glVertexAttribPointer(_shader._uv, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &rect[0].u);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
_shader.end();
const char* vs = "#version 130\n\
                    uniform mat4    _mvp;\n\
                    // x = col,y = row,z = frame\n\
                    uniform vec3    _animInfor;\n\
                    in  vec3    _pos;\n\
                    in  vec2    _uv;\n\
                    out vec2    _outUV;\n\
                    void main()\n\
                    {\n\
                        float uS    =   1.0/_animInfor.x; // 纹理总宽单位1,每列占比多少\n\
                        float vS    =   1.0/_animInfor.y; // 纹理总长单位1,每行占比多少\n\
                        int  col    =   int(_animInfor.z)%int(_animInfor.x);\n\
                        int  row    =   int(_animInfor.z)/int(_animInfor.y);\n\
                        _outUV      =   _uv * vec2(uS,vS);\n\
                        _outUV.x    +=  float(col) * uS;\n\
                        _outUV.y    +=  float(row) * vS;\n\
                        gl_Position =   _mvp * vec4(_pos,1.0);\n\
                    }";
const char* ps = "uniform sampler2D _texture;\n\
                    in vec2    _outUV;\n\
                    void main()\n\
                    {\n\
                        gl_FragColor = texture2D(_texture,_outUV);\n\
                    }";
createProgram(vs, ps);

_mvp = glGetUniformLocation(_program, "_mvp");
_texture = glGetUniformLocation(_program, "_texture");
_animInfor = glGetUniformLocation(_program, "_animInfor");
_pos = glGetAttribLocation(_program, "_pos");
_uv = glGetAttribLocation(_program, "_uv");

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值