热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

LearnOpenGL_study光照贴图

漫反射贴图完整代码:https:github.comDXT00LearnOpenGL_studytreea9082da982458111eb505a22e92bcb

漫反射贴图

完整代码:https://github.com/DXT00/LearnOpenGL_study/tree/a9082da982458111eb505a22e92bcb4146bd8ee7

在着色器中使用漫反射贴图的方法和纹理教程中是完全一样的。但这次我们会将纹理储存为Material结构体中的一个sampler2D。我们将之前定义的vec3漫反射颜色向量替换为漫反射贴图.

struct Material{vec3 ambient;sampler2D diffuse;vec3 specular;float shininess;};

fragment shader:
 

#type fragment
#version 330 corestruct Material{vec3 ambient;sampler2D diffuse;vec3 specular;float shininess;};out vec4 FragColor;float ambientStrength = 0.1f;
float specularStrength = 1.0f;
//uniform float u_shininessStrength;//反光度因子,可以是2,4,8,16,..256,一个物体的反光度越高,反射光的能力越强,散射得越少,高光点就会越小in vec2 v_TexCoord;
in vec3 v_Normal;
in vec3 v_FragPos; uniform Material u_Material;
uniform sampler2D u_Texture1;
uniform sampler2D u_Texture2;
uniform float u_MixValue;uniform vec3 u_LightColor;
uniform vec3 u_LightPos;
uniform vec3 u_CameraViewPos;//ambient
vec3 ambient = u_LightColor * u_Material.ambient* texture(u_Material.diffuse,v_TexCoord).rgb;//u_LightColor * u_Material.ambient//diffuse
vec3 lightDir = normalize(u_LightPos-v_FragPos);
vec3 norm = normalize(v_Normal);
float diff = max(dot(lightDir,norm),0.0f);
vec3 diffuse = u_LightColor * diff * texture(u_Material.diffuse,v_TexCoord).rgb;// u_Material.diffuse);u_LightColor//specular
vec3 reflectDir = normalize(reflect(-lightDir,norm));
vec3 viewDir = normalize(u_CameraViewPos-v_FragPos);
float spec = pow(max(dot(reflectDir,viewDir),0.0),u_Material.shininess);
vec3 specular = u_LightColor * spec * u_Material.specular;void main(){FragColor = vec4((diffuse + ambient + specular),1.0);// * mix(texture(u_Texture1, v_TexCoord), texture(u_Texture2, vec2(1.0 - v_TexCoord.x, v_TexCoord.y)), u_MixValue);
}

在Application.cpp中添加一个 DiffuseMap的纹理:

m_DiffuseMap.reset(new Texture("assets/texture/container2.png"));

并设置Uniform

由于之前已经有两个纹理了,所以DiffuseMap绑定为2号纹理:

m_Shader->SetUniform1i("u_Material.diffuse", 2);

renderer loop:

//render loopwhile (!glfwWindowShouldClose(m_Window->GetNativeWindow())) {float time = (float)glfwGetTime();Timestep ts = time - m_LastFrameTime;m_LastFrameTime = time;InputCheck(ts);if (glfwGetKey(m_Window->GetNativeWindow(), GLFW_KEY_ESCAPE) == GLFW_PRESS)glfwSetWindowShouldClose(m_Window->GetNativeWindow(), true);// render// ------//glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClearColor(0.1f, 0.1f, 0.1f, 0.1f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// bind textures on corresponding texture unitsglActiveTexture(GL_TEXTURE0);m_Texture1->Bind();glActiveTexture(GL_TEXTURE1);m_Texture2->Bind();glActiveTexture(GL_TEXTURE2);m_DiffuseMap->Bind();Renderer::BeginScene(*m_Camera);glm::mat4 model = glm::mat4(1.0f);model = glm::translate(model, m_LightSource->GetPosition());model = glm::scale(model, glm::vec3(0.5f));Renderer::Submit(m_LightSource->GetVertexArray(), m_LightSource->GetShader(), model);glDrawArrays(GL_TRIANGLES, 0, 36);for (unsigned int i = 0; i <10; i++){glm::mat4 model = glm::mat4(1.0f);model = glm::translate(model, cubePositions[i]);model = glm::rotate(model, (float)(glfwGetTime()), glm::vec3(1.0f, (float)i * 20, 0.0f));//(float)(glfwGetTime())m_Shader->SetUniformMat4f("u_TranInverseModel", glm::transpose(glm::inverse(model)));m_Shader->SetUniformVec3f("u_CameraViewPos", m_Camera->GetPosition());//glm::vec3 lightColor;// = m_LightSource->GetLightColor();//lightColor.x = sin(glfwGetTime() * 2.0f);//lightColor.y = sin(glfwGetTime() * 0.7f);//lightColor.z = sin(glfwGetTime() * 1.3f);m_Shader->SetUniformVec3f("u_LightColor", m_LightSource->GetLightColor());m_Shader->SetUniformVec3f("u_Material.ambient", glm::vec3(0.25,0.20725,0.20725));m_Shader->SetUniform1i("u_Material.diffuse", 2);//m_Shader->SetUniformVec3f("u_Material.diffuse", glm::vec3(1 ,0.829 ,0.829));m_Shader->SetUniformVec3f("u_Material.specular", glm::vec3(0.5, 0.5,0.5));m_Shader->SetUniform1f("u_Material.shininess",64.0f);Renderer::Submit(m_VertexArray, m_Shader, model);glDrawArrays(GL_TRIANGLES, 0, 36);}glfwSwapBuffers(m_Window->GetNativeWindow());glfwPollEvents();}

镜面光贴图:

你可能会注意到,镜面高光看起来有些奇怪,因为我们的物体大部分都是木头,我们知道木头不应该有这么强的镜面高光的。我们可以将物体的镜面光材质设置为vec3(0.0)来解决这个问题,但这也意味着箱子钢制的边框将不再能够显示镜面高光了,我们知道钢铁应该是有一些镜面高光的。所以,我们想要让物体的某些部分以不同的强度显示镜面高光。

镜面光贴图上的每个像素都可以由一个颜色向量来表示,比如说黑色代表颜色向量vec3(0.0),灰色代表颜色向量vec3(0.5)。在片段着色器中,我们接下来会取样对应的颜色值将它乘以光源的镜面强度。一个像素越「白」,乘积就会越大,物体的镜面光分量就会越亮

由于箱子大部分都由木头所组成,而且木头材质应该没有镜面高光,所以漫反射纹理的整个木头部分全部都转换成了黑色。箱子钢制边框的镜面光强度是有细微变化的,钢铁本身会比较容易受到镜面高光的影响,而裂缝则不会。

把u_Material 的 specular设置为贴图--》Sampler2D

struct Material{vec3 ambient;sampler2D diffuse;sampler2D specular;float shininess;};

Application 添加 SpecularMap

m_Shader->SetUniform1i("u_Material.specular", 3);m_SpecularMap.reset(new Texture("assets/texture/container2_specular.png"));

 

放射光贴图

对物体的发光部分贴图

完整代码:https://github.com/DXT00/LearnOpenGL_study/tree/e0127d6525036402a0d32319ddbe2144d4226a3a

//ambient
vec3 ambient = u_LightColor * u_Material.ambient* texture(u_Material.diffuse,v_TexCoord).rgb;//u_LightColor * u_Material.ambient//diffuse
vec3 lightDir = normalize(u_LightPos-v_FragPos);
vec3 norm = normalize(v_Normal);
float diff = max(dot(lightDir,norm),0.0f);
vec3 diffuse = u_LightColor * diff * texture(u_Material.diffuse,v_TexCoord).rgb;// u_Material.diffuse);u_LightColor//specular
vec3 reflectDir = normalize(reflect(-lightDir,norm));
vec3 viewDir = normalize(u_CameraViewPos-v_FragPos);
float spec = pow(max(dot(reflectDir,viewDir),0.0),u_Material.shininess);
vec3 specular = u_LightColor * spec * texture(u_Material.specular,v_TexCoord).rgb;//emission
vec3 emission = texture(u_Material.emission,v_TexCoord).rgb;
void main(){FragColor = vec4((diffuse + ambient + specular + emission),1.0);// * mix(texture(u_Texture1, v_TexCoord), texture(u_Texture2, vec2(1.0 - v_TexCoord.x, v_TexCoord.y)), u_MixValue);
}

m_EmissionMap.reset(new Texture("assets/texture/matrix.jpg"));m_Shader->SetUniform1i("u_Material.emission", 4);


推荐阅读
  • 本文详细解析了使用C++实现的键盘输入记录程序的源代码,该程序在Windows应用程序开发中具有很高的实用价值。键盘记录功能不仅在远程控制软件中广泛应用,还为开发者提供了强大的调试和监控工具。通过具体实例,本文深入探讨了C++键盘记录程序的设计与实现,适合需要相关技术的开发者参考。 ... [详细]
  • PTArchiver工作原理详解与应用分析
    PTArchiver工作原理及其应用分析本文详细解析了PTArchiver的工作机制,探讨了其在数据归档和管理中的应用。PTArchiver通过高效的压缩算法和灵活的存储策略,实现了对大规模数据的高效管理和长期保存。文章还介绍了其在企业级数据备份、历史数据迁移等场景中的实际应用案例,为用户提供了实用的操作建议和技术支持。 ... [详细]
  • 解决Only fullscreen opaque activities can request orientation错误的方法
    本文介绍了在使用PictureSelectorLight第三方框架时遇到的Only fullscreen opaque activities can request orientation错误,并提供了一种有效的解决方案。 ... [详细]
  • 单片微机原理P3:80C51外部拓展系统
      外部拓展其实是个相对来说很好玩的章节,可以真正开始用单片机写程序了,比较重要的是外部存储器拓展,81C55拓展,矩阵键盘,动态显示,DAC和ADC。0.IO接口电路概念与存 ... [详细]
  • window下的python安装插件,Go语言社区,Golang程序员人脉社 ... [详细]
  • com.hazelcast.config.MapConfig.isStatisticsEnabled()方法的使用及代码示例 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 在Delphi7下要制作系统托盘,只能制作一个比较简单的系统托盘,因为ShellAPI文件定义的TNotifyIconData结构体是比较早的版本。定义如下:1234 ... [详细]
  • php更新数据库字段的函数是,php更新数据库字段的函数是 ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • 在尝试对 QQmlPropertyMap 类进行测试驱动开发时,发现其派生类中无法正常调用槽函数或 Q_INVOKABLE 方法。这可能是由于 QQmlPropertyMap 的内部实现机制导致的,需要进一步研究以找到解决方案。 ... [详细]
  • 本文详细介绍了在MySQL中如何高效利用EXPLAIN命令进行查询优化。通过实例解析和步骤说明,文章旨在帮助读者深入理解EXPLAIN命令的工作原理及其在性能调优中的应用,内容通俗易懂且结构清晰,适合各水平的数据库管理员和技术人员参考学习。 ... [详细]
  • 为了确保iOS应用能够安全地访问网站数据,本文介绍了如何在Nginx服务器上轻松配置CertBot以实现SSL证书的自动化管理。通过这一过程,可以确保应用始终使用HTTPS协议,从而提升数据传输的安全性和可靠性。文章详细阐述了配置步骤和常见问题的解决方法,帮助读者快速上手并成功部署SSL证书。 ... [详细]
  • 本文详细解析了 Android 系统启动过程中的核心文件 `init.c`,探讨了其在系统初始化阶段的关键作用。通过对 `init.c` 的源代码进行深入分析,揭示了其如何管理进程、解析配置文件以及执行系统启动脚本。此外,文章还介绍了 `init` 进程的生命周期及其与内核的交互方式,为开发者提供了深入了解 Android 启动机制的宝贵资料。 ... [详细]
  • 深入解析Android 4.4中的Fence机制及其应用
    在Android 4.4中,Fence机制是处理缓冲区交换和同步问题的关键技术。该机制广泛应用于生产者-消费者模式中,确保了不同组件之间高效、安全的数据传输。通过深入解析Fence机制的工作原理和应用场景,本文探讨了其在系统性能优化和资源管理中的重要作用。 ... [详细]
author-avatar
兴添刚
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有