glClearColor 和混合
Posted
技术标签:
【中文标题】glClearColor 和混合【英文标题】:glClearColor and blending 【发布时间】:2021-02-10 09:25:33 【问题描述】:我正在使用 GLFW、带有 VSCode 的 OpenGL 4.6 和 MinGW64 g++。我正在尝试使用glEnable(GL_BLEND);
和glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC1_ALPHA);
渲染透明纹理。虽然纹理确实在我的窗口上呈现,但 glClearColor() 似乎显着影响了混合。我对图形还是很陌生,所以我不确定如何正确渲染纹理,无论清晰的颜色设置为什么。另外,我需要为 2D 游戏启用深度吗? (shader.cpp 和 texture.cpp 取自 The Cherno 的 OpenGL 教程系列)
没有混合
与混合
具有混合和黑色透明色(所需混合)
main.cpp:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "GeometryUtil.h"
#include "Shader.h"
#include "Texture.h"
#include "Object.h"
#include <iostream>
#include <vector>
using namespace std;
int main()
if (!glfwInit()) // Initialise GLFW
cerr << "Failed to initialize GLFW" << endl;
return -1;
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window glfwCreateWindow(1280, 720, "2D GAME", NULL, NULL);
if (window == NULL)
cerr << "Failed to open GLFW window." << endl;
glfwTerminate();
return -1;
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
glfwMakeContextCurrent(window);
glewExperimental = true;
if (glewInit() != GLEW_OK)
cerr << "Failed to initialize GLEW" << endl;
glfwTerminate();
return -1;
cout << "OpenGL Version: " << glGetString(GL_VERSION) << endl;
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC1_ALPHA);
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
GLuint VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
Object object 608, 392;
vector<float> vectorData;
createQuad(object.getX(), object.getY(), vectorData);
static const GLfloat texCoords[8]
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f
;
GLuint VBOs[2];
glGenBuffers(2, VBOs);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
glBufferData(GL_ARRAY_BUFFER, vectorData.size() * sizeof(vectorData), &vectorData.front(), GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void *) 0);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void *) (2 * sizeof(GLfloat)));
glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(texCoords), texCoords, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
static const GLuint texIndex[6]
0, 1, 2,
1, 2, 3
;
GLuint indexBuffer;
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(texIndex), texIndex, GL_STATIC_DRAW);
glm::mat4 Projection glm::ortho(0.0f, 1280.0f, 0.0f, 720.0f, 0.0f, 1.0f);
glm::mat4 View glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 0));
glm::vec3 translationA glm::vec3(0, 0, 0);
glm::mat4 Model = glm::translate(glm::mat4(1.0f), translationA); // Model Matrix (Using Identity Matrix - Origin)
glm::mat4 mvp = Projection * View * Model;
Shader shader "shader/vertexShader.vert", "shader/fragmentShader.frag";
shader.bind();
shader.setUniformMat4f("MVP", mvp);
int sampler[] 0, 1;
shader.setUniform1iv("v_Textures", sampler, 2);
Texture texture "resources/sprites/test.png";
texture.bind();
while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glfwSwapBuffers(window);
glfwPollEvents();
glfwTerminate();
return 0;
纹理.cpp:
#define STB_IMAGE_IMPLEMENTATION
#include <GL/glew.h>
#include "Texture.h"
#include "stb_image.h"
#include <iostream>
Texture::Texture(const std::string &path)
: rendererID0, filePathpath, localBuffernullptr, width0, height0, bPP0
// stbi_set_flip_vertically_on_load(1);
localBuffer = stbi_load(path.c_str(), &width, &height, &bPP, 4);
if (localBuffer == nullptr)
std::cout << "Unable to load texture file: " << path << std::endl;
glGenTextures(1, &rendererID);
glBindTexture(GL_TEXTURE_2D, rendererID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, localBuffer);
unbind();
if (localBuffer)
stbi_image_free(localBuffer);
Texture::~Texture()
glDeleteTextures(1, &rendererID);
void Texture::bind(GLuint slot) const ;
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(GL_TEXTURE_2D, rendererID);
void Texture::unbind() const
glBindTexture(GL_TEXTURE_2D, 0);
顶点着色器:
#version 460 core
layout(location = 0) in vec3 vertexCoords;
layout(location = 1) in vec2 textureCoords;
layout(location = 2) in float textureIndex;
out vec2 v_TexCoords;
out float v_TexIndex;
uniform mat4 MVP;
void main()
gl_Position = MVP * vec4(vertexCoords, 1.0);
v_TexCoords = textureCoords;
v_TexIndex = textureIndex;
片段着色器:
#version 460 core
in vec2 v_TexCoords;
in float v_TexIndex;
uniform sampler2D v_Textures[2];
void main()
gl_FragColor = texture2D(v_Textures[int(v_TexIndex)], v_TexCoords);
【问题讨论】:
这是预期的结果。混合的工作方式是将您输出的颜色与缓冲区中已有的颜色混合。如果您的 C 字母的 alpha 值小于 1,它将与背景颜色组合,从而对其进行着色。这与 alpha-keying 不同,您可以根据值丢弃样本,但不将它们与缓冲区中已有的数据结合起来。 【参考方案1】:乍一看,一切都是正确的代码,是的,在GL_SRC_ALPHA
作为第一个参数的情况下,背景会影响混合。
问题是第二个参数应该是GL_ONE_MINUS_SRC_ALPHA
而不是GL_ONE_MINUS_SRC1_ALPHA
。在您的情况下,混合没有标准化,因此过多的绿色和全红色的值加起来就是黄色。
来源:https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendFuncSeparate.xhtml
【讨论】:
以上是关于glClearColor 和混合的主要内容,如果未能解决你的问题,请参考以下文章