opengl透明效果&将模型点击放置在另一个模型之上

这篇博客探讨了OpenGL中的混合技术如何实现物体透明度,以及如何使用丢弃片段来处理不需要透明的部分,例如在渲染草时仅显示纹理的可见部分。通过修改纹理加载、片段着色器及使用`discard`指令,可以实现精确控制图像的显示。同时,文中给出了代码示例,展示了如何在点击事件中获取模型坐标并进行渲染,以达到预期效果。
摘要由CSDN通过智能技术生成

opengl高级opengl中的混合这一章

  • 最好还是看官网文章

  • OpenGL中,混合(Blending)通常是实现物体透明度(Transparency)的一种技术。透明就是说一个物体(或者其中的一部分)不是纯色(Solid Color)的,它的颜色是物体本身的颜色和它背后其它物体的颜色的不同强度结合。一个有色玻璃窗是一个透明的物体,玻璃有它自己的颜色,但它最终的颜色还包含了玻璃之后所有物体的颜色。这也是混合这一名字的出处,我们混合(Blend)(不同物体的)多种颜色为一种颜色。所以透明度能让我们看穿物体。

  • **丢弃片段:**有些图片并不需要半透明,只需要根据纹理颜色值,显示一部分,或者不显示一部分,没有中间情况。比如说草,如果想不太费劲地创建草这种东西,你需要将一个草的纹理贴在一个2D四边形(Quad)上,然后将这个四边形放到场景中。然而,草的形状和2D四边形的形状并不完全相同,所以你只想显示草纹理的某些部分,而忽略剩下的部分。不希望看到草的方形图像,而是只显示草的部分,并能看透图像其余的部分。我们想要丢弃(Discard)显示纹理中透明部分的片段,不将这些片段存储到颜色缓冲中。

  • 加载有alpha值的纹理,我们并不需要改很多东西,stb_image在纹理有alpha通道的时候会自动加载,但我们仍要在纹理生成过程中告诉OpenGL,我们的纹理现在使用alpha通道了:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  • 保证你在片段着色器中获取了纹理的全部4个颜色分量,而不仅仅是RGB分量:
void main()
{
    // FragColor = vec4(vec3(texture(texture1, TexCoords)), 1.0);
    FragColor = texture(texture1, TexCoords);
}
  • 去除白边GLSL给了我们discard命令,一旦被调用,它就会保证片段不会被进一步处理,所以就不会进入颜色缓冲。有了这个指令,我们就能够在片段着色器中检测一个片段的alpha值是否低于某个阈值,如果是的话,则丢弃这个片段,就好像它不存在一样:

主要修改

  • 有很多直接看代码库代码即可
  • 纹理
  • 添加新的图片
  • 新的model,将坐标直接放到model里边变量以及变量map;注意这里边一样要给文件函数参数前添加const
	glm::mat4 modelMatrix;
	glm::vec3 worldPosition;	
glm::vec3 modelPos;
//生成map和map迭代器
map<string, Model> _models;
map<string, Model>::iterator _modelsIter;
  • 新的frag文件用于加载草的纹理
  • 新的mesh函数
  • 增加setshader函数避免重复设置
void setShader(Shader* shader)
{
    shader->useShader();
    shader->setMat4("projection", projection);
    shader->setMat4("view", view);
    shader->setVec4("lightPos", cubePositions[1].r, cubePositions[1].g, cubePositions[1].b, 1);
    shader->setVec3("viewPos", camera.Position.r, camera.Position.g, camera.Position.b);
    shader->setVec3("front", camera.Front.r, camera.Front.g, camera.Front.b);
    shader->setVec3("lightColor", 1.0f, 1.0f, 1.0f);
}
  • 点击之后获得模型的坐标然后再进行混合:倒回到模型坐标modelPos
            for (_modelsIter = _models.begin(); _modelsIter != _models.end(); _modelsIter++)
            {
                float _distance = glm::distance(_modelsIter->second.worldPosition + glm::vec3(0, 7.5, 0), glm::vec3(wolrdPostion));
                if (_distance < 7.5)
                {
                    modelPos = glm::inverse(_modelsIter->second.modelMatrix) * wolrdPostion;
                    modelSelected = _modelsIter->first;
                    cout << _modelsIter->first << "模型被选中..." << endl;
                }

            }
  • 然后在点击之后进行渲染的时候有一个渲染草
                model = glm::translate(model, modelPos);
                caoShader.setMat4("model", model);
                cao.Draw(caoShader);
  • 效果:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值