OpenGLES(七)-GLSL案例:纹理颜色混合
首先放出效果
效果图
原图:
原图
通过对比可以看出纹理和颜色进行了混合效果,下面就放出实现过程.
- vsh
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
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放出最核心的代码
//初始化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];
- 与之前的纹理加载相比,代码上只是多传了一组颜色值,别无其他区别