OpenGL学习笔记(十六)混合和面剔除

首先要做的就是通过根据贴图的alpha值渲染一些草在地面上。
老样子还是先是顶点着色器

#version 330 core
out vec2 TextureCoord;
out vec4 vertexColor;
layout (location=0) in vec3 aPos;
layout (location=1) in vec3 aColor;
layout (location=2) in vec2 aTextureCoord;//纹理坐标
uniform mat4 modelMat;//模型矩阵
uniform mat4 viewMat;//视角矩阵
uniform mat4 projMat;//投影
void main()
{
   gl_Position=projMat*viewMat*modelMat*vec4(aPos.x,aPos.y,aPos.z,1.0f);
   vertexColor=vec4(aColor,1.0f);
   TextureCoord=aTextureCoord;
}

片段着色器

#version 330 core
out vec4 FragColor;
in vec2 TextureCoord;
uniform sampler2D ourTexture;//纹理


void main()
{
vec4 texColor = texture(ourTexture, TextureCoord);
    if(texColor.a < 0.1)//alpha值小于0.1就抛弃
        discard;
    FragColor = texColor;
}

形状和位置的数组

float transparentVertices[] = {
	// positions         // texture Coords (swapped y coordinates because texture is flipped upside down)
	0.0f,  0.5f,  0.0f,  0.0f,  0.0f,
	0.0f, -0.5f,  0.0f,  0.0f,  1.0f,
	1.0f, -0.5f,  0.0f,  1.0f,  1.0f,

	0.0f,  0.5f,  0.0f,  0.0f,  0.0f,
	1.0f, -0.5f,  0.0f,  1.0f,  1.0f,
	1.0f,  0.5f,  0.0f,  1.0f,  0.0f
};

glm::vec3 grass_pos[]=
{
	glm::vec3(-1.5f, 0.0f, -0.48f),
	glm::vec3(1.5f, 0.0f, 0.51f),
	glm::vec3(0.0f, 0.0f, 0.7f),
	glm::vec3(-0.3f, 0.0f, -2.3f),
	glm::vec3(-1.0f, 0.0f, -0.314f),
	glm::vec3(1.0f, 0.0f, 0.51f),
	glm::vec3(2.23f, 0.0f, 0.7f),
	glm::vec3(-1.3f, 0.0f, -2.3f),
	glm::vec3(-0.5f, 0.0f, -0.48f),
	glm::vec3(2.5f, 0.0f, 1.1f),
	glm::vec3(1.0f, 0.0f, 0.78f),
	glm::vec3(-0.9f, 0.0f, -2.3f),
	glm::vec3(0.5f, 0.0f, -0.6f)
};

然后是申请对应的VAO和VBO

	GLuint transparentVBO, transparentVAO;
	glGenVertexArrays(1, &transparentVAO);
	glGenBuffers(1, &transparentVBO);
	glBindVertexArray(transparentVAO);
	glBindBuffer(GL_ARRAY_BUFFER, transparentVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(transparentVertices), transparentVertices, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(2);

加载纹理图片

unsigned int texbufferC;
	texbufferC = Load_Texture("grass.png", GL_RGBA, GL_RGBA, 2);

开始绘制

for (int i = 0; i < sizeof(grass_pos) / sizeof(grass_pos[0]); i++)
		{
			glBindVertexArray(transparentVAO);//应用透明VAO
			glm::mat4 modelMat;
			modelMat = glm::translate(modelMat,grass_pos[i]);//定义位置
			glActiveTexture(GL_TEXTURE2);//加载和绑定纹理
			glBindTexture(GL_TEXTURE_2D, texbufferC);
			shader.setInt("ourTexture", 2);//传输纹理号给片段着色器
			shader.setMat4("modelMat", modelMat);//设置模型矩阵
			glDrawArrays(GL_TRIANGLES,0,6);//根据模型行数决定这里的数值
		}

绘制结果:
在这里插入图片描述
其中的

			glActiveTexture(GL_TEXTURE2);
			glBindTexture(GL_TEXTURE_2D, texbufferC);

是可以去掉的,因为前面已经绑定过纹理编号了。

现在再来写写半透明的窗子。
先开启混合

glEnable(GL_BLEND);//开始混合
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//混合函数设置,源颜色向量的alpha做源因子,1-alpha做目标因子

再使用vector装一下窗口位置。

vector<glm::vec3> windows_pos =
	{
		 glm::vec3(-1.5f, 0.0f, -0.48f),
			glm::vec3(1.5f, 0.0f, 0.51f),
			glm::vec3(0.0f, 0.0f, 0.7f),
			glm::vec3(-0.3f, 0.0f, -2.3f),
			glm::vec3(0.5f, 0.0f, -0.6f)
	};

然后再用map做一个窗口与相机距离之间的排序。

std::map<float, glm::vec3>sorted;//map相当于字典
for (unsigned int i = 0; i < windows_pos.size(); i++)
{
float distance = glm::length(myCamera->Position - windows_pos[i]);//通过相机位置计算先后顺序
sorted[distance] = windows_pos[i];
}

最后渲染这些窗口

glBindVertexArray(transparentVAO);
		for (std::map<float, glm::vec3>::reverse_iterator it = sorted.rbegin(); it != sorted.rend(); ++it)
		{
			modelMat = glm::mat4(1.0f);
			modelMat = glm::translate(modelMat, it->second);
			shader.setInt("ourTexture", 2);
			shader.setMat4("modelMat", modelMat);
			glDrawArrays(GL_TRIANGLES, 0, 6);
		}

最后结果:
在这里插入图片描述
记住:

glEnable(GL_DEPTH_TEST);//开启深度测试
	glEnable(GL_BLEND);//开始混合
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//混合函数设置,源颜色向量的alpha做源因子,1-alpha做目标因子

这些开启什么模式的东西,必须在 glfwMakeContextCurrent(window);之后,否则就相当于没有开启。

放在glfwMakeContextCurrent(window);之前的结果。
在这里插入图片描述

面剔除
面剔除就是不渲染立方体后面不能看见的面,可以节省50%及以上的片段着色器性能。对于想前面的草,窗,地面这些非闭合物体需要关闭面剔除。


	glEnable(GL_CULL_FACE);//开启面剔除
	glCullFace(GL_BACK);//只剔除后面的
glDisable(GL_CULL_FACE);//关闭面剔除

如果在渲染非闭合物体时,没有关闭面剔除,就会导致
在这里插入图片描述
渲染出来的箱子中空,地面消失了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值