第七课:纹理滤波、光源和键盘控制



  • 纹理滤波

    在纹理映射的过程中,如果图元的大小不等于纹理的大小,OpenGL便会对纹理进行缩放以适应图元的尺寸。我们可以通过设置纹理滤镜来决定OpenGL对某个纹理采用的放大、缩小的算法

    滤镜 描述
    GL_NEAREST 取最邻近像素
    GL_LINEAR 线性内部插值
    GL_NEAREST_MIPMAP_NEAREST 最近多贴图等级的最邻近像素
    GL_NEAREST_MIPMAP_LINEAR 在最近多贴图等级的内部线性插值
    GL_LINEAR_MIPMAP_NEAREST 在最近多贴图等级的外部线性插值
    GL_LINEAR_MIPMAP_LINEAR 在最近多贴图等级的外部和内部线性插值

    光源

    环境光

    因为我们使用的OpenGL 3.x API,使用可编程管线,不使用glLightfv

    修改着色器代码

    • 颜色=环境光强度(0.5)* 环境光颜色 * 物体本身颜色
    static const char *vertexShaderSource =
        "attribute highp vec4 posAttr;\n"
        "attribute lowp vec3 colAttr;\n"
        "varying lowp vec3 col;\n"
        "uniform highp mat4 projection;\n"
        "uniform highp mat4 view;\n"
        "uniform highp mat4 model;\n"
        "attribute vec2 a_texcoord;\n"
        "varying highp vec2 v_texcoord;\n"
        "void main() {\n"
        "   gl_Position = projection * view * model * posAttr;\n"
        "   v_texcoord = a_texcoord;\n"
        "   col = colAttr;\n"
        "}\n";
    
    static const char *fragmentShaderSource =
        "varying lowp vec3 col;\n"
        "uniform sampler2D texture;\n"
        "uniform lowp vec3 ambientColAttr;\n"
        "varying highp vec2 v_texcoord;\n"
        "void main() {\n"
        "   float ambientStrength = 0.5f;\n"
        "   gl_FragColor = vec4(ambientStrength * ambientColAttr * col, 1.0f);\n"
        "}\n";
    

    获取 环境光属性

    //环境光属性
    m_ambientColAttr = m_program->uniformLocation("ambientColAttr");
    

    绘制时候设置环境光

    QVector3D ambient(1.0f, 1.0f, 1.0f);
    m_program->setUniformValue(m_ambientColAttr, ambient);
    

    效果

    之所以有这样的效果,是因为左上角白色受环境光影响,反射了环境光颜色

    • 白色环境光
      0_1526954839519_f40f63b4-9d0a-46c9-a505-a98451d42c33-image.png
    • 红色环境光
      0_1526954873463_d6a83b40-63bb-4986-8a4f-d5df3a1475a4-image.png
    • 绿色环境光
      0_1526954902270_14818a8e-daf4-4f8c-8563-2c711e200dbf-image.png
    • 蓝色环境光
      0_1526954923358_7a242e55-54fe-4108-9d41-d39813facab2-image.png

    点光源-漫反射

    修改着色器代码

    我们追加了点光源颜色,光源位置,物体的法线(实际具有增幅/衰减光亮的效果)

    static const char *vertexShaderSource =
        "attribute highp vec3 posAttr;\n"
        "attribute lowp vec3 colAttr;\n"
        "varying lowp vec3 col;\n"
        "uniform lowp vec3 aNormal;\n"
        "uniform highp mat4 projection;\n"
        "uniform highp mat4 view;\n"
        "uniform highp mat4 model;\n"
        "attribute vec2 a_texcoord;\n"
    
        "varying highp vec2 v_texcoord;\n"
        "varying vec3 Normal;\n"
        "varying vec3 FragPos;\n"
    
        "void main() {\n"
        "   gl_Position = projection * view * model * vec4(posAttr, 1.0);\n"
        "   FragPos = vec3(model * vec4(posAttr, 1.0));\n"
        "   v_texcoord = a_texcoord;\n"
        "   Normal = mat3(transpose(inverse(model))) * aNormal;\n"
        "   col = colAttr;\n"
        "}\n";
    
    static const char *fragmentShaderSource =
        "varying lowp vec3 col;\n"
        "uniform sampler2D texture;\n"
        "uniform lowp vec3 ambientColAttr;\n"
        "uniform lowp vec3 lightColAttr;\n"
        "uniform lowp vec3 lightPosAttr;\n"
    
        "varying highp vec2 v_texcoord;\n"
        "varying vec3 Normal;\n"
        "varying vec3 FragPos;\n"
    
        "void main() {\n"
        "   vec3 norm = normalize(Normal);\n"
        "   vec3 lightDir = normalize(lightPosAttr - FragPos);\n"
        "   float ambientStrength = 0.1;\n"
        "   float diffuse = max(dot(norm, lightDir), 0.0);\n"
        "   gl_FragColor = vec4((ambientStrength + diffuse) * lightColAttr * col, 1.0);\n"
        "}\n";
    

    获取 点光源属性

    //点光源属性
        m_lightColAttr = m_program->uniformLocation("lightColAttr");
        m_lightPosAttr = m_program->uniformLocation("lightPosAttr");
        m_aNormal = m_program->uniformLocation("aNormal");
    

    绘制时候设置点光

    //环境光
        QVector3D ambient(1.0f, 1.0f, 1.0f);
        m_program->setUniformValue(m_ambientColAttr, ambient);
    
        //点光源-漫反射
        QVector3D pointLightCol(1.0f, 1.0f, 1.0f);
        m_program->setUniformValue(m_lightColAttr, pointLightCol);
    
        QVector3D pointLightPos(2.0f, 0.0f, 2.0f);
        m_program->setUniformValue(m_lightPosAttr, pointLightPos);
    
        //法线=强度
        QVector3D objNormal(0.0f, 1.0f, 1.0f);
        m_program->setUniformValue(m_aNormal, objNormal);
    

    效果

    0_1526965557596_20180522_125850.gif

    高光-镜面反射

    光源照射到物体然后反射到人的眼睛里时,物体上最亮的那个点就是高光,
    所以我们需要知道眼睛(摄像机)的位置,然后根据光的方向,法线求出反射

    修改着色器代码

    static const char *vertexShaderSource =
        "attribute highp vec3 posAttr;\n"
        "attribute lowp vec3 colAttr;\n"
        "varying lowp vec3 col;\n"
        "uniform lowp vec3 aNormal;\n"
        "uniform highp mat4 projection;\n"
        "uniform highp mat4 view;\n"
        "uniform highp mat4 model;\n"
        "attribute vec2 a_texcoord;\n"
    
        "varying highp vec2 v_texcoord;\n"
        "varying vec3 Normal;\n"
        "varying vec3 FragPos;\n"
    
        "void main() {\n"
        "   gl_Position = projection * view * model * vec4(posAttr, 1.0);\n"
        "   FragPos = vec3(model * vec4(posAttr, 1.0));\n"
        "   v_texcoord = a_texcoord;\n"
        "   Normal = mat3(transpose(inverse(model))) * aNormal;\n"
        "   col = colAttr;\n"
        "}\n";
    
    static const char *fragmentShaderSource =
        "varying lowp vec3 col;\n"
        "uniform sampler2D texture;\n"
        "uniform lowp vec3 ambientColAttr;\n"
        "uniform lowp vec3 lightColAttr;\n"
        "uniform lowp vec3 lightPosAttr;\n"
        "uniform lowp vec3 viewPosAttr;\n"
    
        "varying highp vec2 v_texcoord;\n"
        "varying vec3 Normal;\n"
        "varying vec3 FragPos;\n"
    
        "void main() {\n"
        //漫反射
        "   vec3 norm = normalize(Normal);\n"
        "   vec3 lightDir = normalize(lightPosAttr - FragPos);\n"
        "   float ambientStrength = 0.1;\n"
        "   float diffuse = max(dot(norm, lightDir), 0.0);\n"
    
        //高光
        "   vec3 viewDir = normalize(viewPosAttr - FragPos);\n"
        "   vec3 reflecDir = reflect(-lightDir, norm);\n"
        "   float specularStrength = 0.5;\n"
        "   float specular = pow(max(dot(viewDir, reflecDir), 0.0), 64) * specularStrength;\n"
        "   gl_FragColor = vec4((ambientStrength + diffuse + specular) * lightColAttr * col, 1.0);\n"
        "}\n";
    

    获取 视点属性

    //视点属性
        m_viewPosAttr = m_program->uniformLocation("viewPosAttr");
    

    绘制时候设置视点

    //视点为摄像机位置
        m_program->setUniformValue(m_viewPosAttr, camera);
    

    效果

    仔细看,有高光
    0_1526968253241_20180522_134903.gif

    源代码

    https://gitee.com/chen227/opengl_OpenGLFunctions7



  • @青山白云 纹理滤波的选择,可以让纹理放大或者缩小的时候避免失真。还有一个叫做Anisotropic的扩展,中文名是各向异性采样,是更高级也是更好看的一个。


 

最近的回复

  • 大家好!最近应该很好吧。世界杯来了,有没有喝一杯呢?
    我很高兴地告诉大家,我们在上周末的时候完成了Live2D的改造,将我们的看板娘换了哦。原先是蕾姆。
    0_1529471654453_dfe4b40e-ad64-4b7a-9d58-5c48609ea3e2-image.png
    同时我对样式也做了一些微调,比如说这里:
    0_1529471386270_828e7fbb-fe0c-4f6b-bb52-03938ac7e19f-image.png
    看起来稍微好了一些。

    随后论坛进行升级了哦,升级到了最新1.9.2版本了,各种功能应该得到优化了吧。
    最后欢迎大家继续来玩~

    阅读更多
  • Qt for Python终于发布了!
    以前的我,可能接触了一点Python,但是都没有坚持下来,现在Python水平还很弱呢。不过我基本语法还是了解一点的。所以我打算借着Qt for Python的东风,来尝试一下Python的开发。

    1、去Python 官网安装Python。地址是:

    https://www.python.org/downloads/mac-osx
    0_1529422911935_1.png
    我下载的版本是3.6.5

    2、双击pkg安装包进行安装,按照提示安装即可,不必做什么设置。
    0_1529422932496_2.png
    3、安装pip。pip是一个类似npm的快速安装器,非常适合python安装。由于Mac的安全策略,这个时候要输入的命令以sudo开始:

    sudo python get-pip.py

    4、需要安装Qt官网提供的python安装包。Qt的Python安装包并没有放入Pypi的地址,因为Qt库本身就偏大。
    但是依然能够通过pip安装。只是安装的命令稍微长:

    sudo pip install --index-url=https://download.qt.io/official_releases/QtForPython/ pyside2

    然后输出的结果是:
    daxiongtekiMacBook-Air:~ jiangcaiyang$ sudo pip install --index-url=https://download.qt.io/official_releases/QtForPython/ pyside2
    Password:
    The directory '/Users/jiangcaiyang/Library/Caches/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
    The directory '/Users/jiangcaiyang/Library/Caches/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
    Looking in indexes: https://download.qt.io/official_releases/QtForPython/
    Collecting pyside2
    Downloading https://download.qt.io/official_releases/QtForPython/pyside2/PySide2-5.11.0-5.11.0-cp27-cp27m-macosx_10_11_intel.whl (125.7MB)
    100% |████████████████████████████████| 125.7MB 1.0MB/s
    matplotlib 1.3.1 requires nose, which is not installed.
    matplotlib 1.3.1 requires tornado, which is not installed.
    Installing collected packages: pyside2
    Successfully installed pyside2-5.11.0
    安装成功。

    5、安装成功了,开始写一个测试的程序吧!
    最简单的,当然是Hello Qt for Python啦。很简单,使用Qt Creator,很方便地可以创建这样的Python脚本,使用方法也和C++版本的Qt应用相同:

    #!/usr/bin/env python # -*- coding: utf-8 -*- from PySide2.QtWidgets import QApplication, QLabel app = QApplication( [ ] ) label = QLabel( "您好 Qt for Python!" ) label.show( ) app.exec_( )

    0_1529422962008_4.jpg
    其中第一行表示用/usr/bin/python 来解析,大家可以在命令提示符输入“which python”来看结果:
    第二行则是在Python 3.x下不用写了,设定的是utf-8编码格式。大家最好也是使用这样的格式,因为这样遇到编码的坑最少。
    因为Python没有main()函数的说法,所以直接从上往下运行就可以了。Python是弱语言,所以不用声明类型,这里还有一点不一样,就是
    app.exec_( ),和C++版本不同的是,添加上了一个下划线。可能和Python内置的函数冲突了?我还需要再调查一下。

    接下来我就仿照例子写了一个更加复杂的Python程序,大致是这样的:

    #!/usr/bin/env python # -*- coding: utf-8 -*- import sys import random from PySide2.QtCore import Qt from PySide2.QtWidgets import (QApplication, QWidget, QPushButton, QLabel, QVBoxLayout ) class MyWidget( QWidget ): def __init__( self ): QWidget.__init__( self ) self.hello = [ "Hallo welt!", "Ciao mondo", "Hei maailma", "Hola mundo", "Hei verden!" ] self.button = QPushButton( "Click me!" ) self.text = QLabel( "Hello World" ) self.text.setAlignment( Qt.AlignCenter ) self.layout = QVBoxLayout( ) self.layout.addWidget( self.text ) self.layout.addWidget( self.button ) self.setLayout( self.layout ) self.button.clicked.connect( self.magic ) def magic( self ): self.text.setText( random.choice( self.hello ) ) if __name__ == "__main__": app = QApplication( sys.argv ) widget = MyWidget( ) widget.resize( 640, 480 ) widget.show( ) sys.exit( app.exec_( ) )

    程序运行起来还行吧!
    0_1529422988117_5.png

    阅读更多
  • @jiangcaiyang 如果需要自动化测试,也用的上

    阅读更多
  • @青山白云 这个可能有点用,但是可能更多局限于爬虫领域吧。

    阅读更多

关注我们

微博
QQ群











召唤伊斯特瓦尔