OpenGLES(七)-GLSL案例:纹理颜色混合OpenGLES(七)-GLSL案例:纹理颜色混合

2021-08-09 11:18:50 浏览数 (1)

OpenGLES(七)-GLSL案例:纹理颜色混合

首先放出效果

效果图

原图:

原图

通过对比可以看出纹理和颜色进行了混合效果,下面就放出实现过程.

  1. vsh
代码语言:javascript复制
attribute vec4 position;
attribute vec4 positionColor;
attribute vec2 textureCoord;

varying lowp vec2 varyingTexCoord;
varying vec4 varyingColor;

void main() {
    varyingColor = positionColor;
    varyingTexCoord = textureCoord;
    gl_Position = position;
}
  • 由于片元着色器无法接受外部的顶点数据和顶点颜色,当然可以通过uniform关键词,直接将混合颜色传入片元着色器。
  • fsh
代码语言:javascript复制
precision highp float;
varying lowp vec2 varyingTexCoord;
varying vec4 varyingColor;
uniform sampler2D colorMap;
uniform lowp float alpha;

void main() {
    vec4 vTexColor = texture2D(colorMap, varyingTexCoord);
    vec4 vColor = varyingColor;
    gl_FragColor = vTexColor * (1.0 - alpha)   vColor * alpha;
}
  • 可以看到在获取的纹理中的纹素之后并没有直接传递给内奸变量gl_FragColor,而是进行了计算vTexColor * (1.0 - alpha) vColor * alpha
  • 如果纹理和颜色都是不透明的,则无法进行混合,只会进行覆盖.所以我们自定义了一个透明度。
  • 这里的计算公式是根据OpenGL中的颜色混合参数得到的:glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA),如果对这个公式陌生可以看看这篇文章:OpenGL(七)- 渲染技巧:颜色混合
  • content、layer、renderbuffer、framebuffer、shader初始化,图片加载都与这篇文章一致.传送门
  • render放出最核心的代码
代码语言:javascript复制
    //初始化s顶点缓存区
    GLuint buffer;
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), &vertex, GL_DYNAMIC_DRAW);
    //将顶点数据传入着色器
    GLuint position = glGetAttribLocation(self.myProgram, "position");
    glEnableVertexAttribArray(position);
    glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat*)NULL   0);
    //将纹理坐标传入着色器
    GLuint texCoord = glGetAttribLocation(self.myProgram, "textureCoord");
    glEnableVertexAttribArray(texCoord);
    glVertexAttribPointer(texCoord, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat*)NULL   3);
    //将颜色传入着色器
    GLuint positionColor = glGetAttribLocation(self.myProgram, "positionColor");
    glEnableVertexAttribArray(positionColor);
    glVertexAttribPointer(positionColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat*)NULL   5);

    //加载纹理并传入片元着色器
    GLuint texture = [self loadImage];
    glActiveTexture(texture);
    glUniform1i(glGetUniformLocation(self.myProgram, "colorMap"), 0);
    glUniform1f(glGetUniformLocation(self.myProgram, "alpha"), 0.3);
    //使用索引绘图
    glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(indices[0]), GL_UNSIGNED_INT, indices);
    
    [self.myContent presentRenderbuffer:GL_RENDERBUFFER];
  • 与之前的纹理加载相比,代码上只是多传了一组颜色值,别无其他区别
如果想要了解索引绘图和顶点绘图的区别可以移步:OpenGLES(六)-综合案例:索引绘图(https://cloud.tencent.com/developer/article/1857995

完整DEMO地址: Github

0 人点赞