zoukankan      html  css  js  c++  java
  • 颜色,基础光照,材质(二)

    本篇blog讲一下关于材质的知识。


    在前面中,我们通过设定几个光照分量以及物体本身的颜色,实现了物体的视觉输出(就是人眼看到的啦)。

    设置材质:我们可以通过进一步地整合数据,来对物体的颜色进行更加严格的控制,既环境光照,漫反射光照,镜面光照三个分量,再加上反光度(为了方便理解,我们把这几个分量看成是物体本身的属性,也就是材质,同各个光照分量对应)。共四个分量,我们可以通过结构体来整合数据:

    struct Material {
        vec3 ambient;
        vec3 diffuse;
        vec3 specular;
        float shininess;
    };
    uniform Material material;

    在主程序,我们可以传入数据:

    //in the main.cpp
    void main()
    {
        ...
        somethingShader.setVec3("material.ambient", 1.0f, 0.5f, 0.31f);
        somethingShader.setVec3("material.diffuse", 1,0f, 0.5f, 0.31f);
        somethingShader.setVec3("material.specular", 0.5f, 0.5f, 0.5f);
        somethingShader.setFloat("material.shininess", 32.0f);
        ...  
    }

    这里将物体的ambient和diffuse分量都设置为物体本来的颜色,而将specular设置为0.5是因为高光程度过高。接着,我们可以在片段着色器里面这么做:

    //fragment shader
    void main()
    {
        vec3 ambient = light * material.ambient;
        ......
        ......
        vec3 result = ambient + diffuse + specular;
        FragColor = vec4(result, 1.0f);
    }

    这里和上一篇blog其实没有本质区别,上一篇blog我们是这么写的:

    //fragment shader
    void main()
    {
        float ambientStrength = 0.1f;
        float ambient = light * ambientStrength;
        
        glm::vec3 result = ambient * coral;
        FragColor = vec4(result, 1.0f);
    }

    注:只看ambient部分,coral是物体的颜色,而material.ambient也是物体的颜色,两者都是将光源乘以物体本身颜色,要说有区别的话,就是原来的ambient实际上是光强度罢了(下面我们会将这个光强度也补齐)。

    既然没有本质区别,那么我们为什么要这样做呢?答案是处于结构化的思维,并且我们可以直接在main.cpp函数中更改数据(而不用在fragment shader中去更改),同时我们可以更简单地让多个物体有多种不同的材质。


    光的属性:在前面的blog中,我们还加入了强度这个东西,而引入它是因为光照强度的问题,不经过处理的话,物体的ambient, diffuse, specular会全力反射光,造成很亮眼的结果。因此这里,我们尝试创建单独的光照属性来影响每个单独的光照向量(请记住,本质上这和前面的strength没有任何区别,只是出于结构化的思维,以及可以直接在main.cpp函数中更改它。

    这里我们创建一个和材质差不多的结构体:

    struct Light {
        vec3 position;
    
        vec3 ambient;
        vec3 diffuse;
        vec3 specular;
    };
    uniform Light light;

    传入数据:

    lightingShader.setVec3("light.ambient",  0.2f, 0.2f, 0.2f);
    lightingShader.setVec3("light.diffuse",  0.5f, 0.5f, 0.5f); // 将光照调暗了一些以搭配场景
    lightingShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f); 

    然后更新着色器对应的代码:

    vec3 ambient  = light.ambient * material.ambient;
    vec3 diffuse  = light.diffuse * (diff * material.diffuse);
    vec3 specular = light.specular * (spec * material.specular);
    result = ambient + diffuse + specular;

    这样子就完成了。

    请记住,这种写法和前面的blog没有本质上的区别,只是出于结构化的思维,以及我们可以在main.cpp函数中自由地操纵数据。

    原来人类的悲欢并不相通, 我只觉得他们吵闹。
  • 相关阅读:
    Mybatis中Log4j日志的使用
    Mybatis结果集ResultMap映射
    Mybatis中的基本对象的生命周期和作用域
    IAR瑞萨单片机开发加入printf调试函数
    【转】C语言mem.h中的函数介绍
    【转】c语言位域操作—_结构体内冒号:的使用
    串口数据传输当中的共用体和结构体转换
    【转】printf格式串中的%f的输出格式和内容
    【转】缓冲区设计--环形队列(C++)
    【转】环形队列理论(C语言)
  • 原文地址:https://www.cnblogs.com/zhlabcd/p/11654139.html
Copyright © 2011-2022 走看看