LearnOpenGL 材質(zhì)

材質(zhì)

材質(zhì)在渲染程式中,它是表面各可視屬性的結(jié)合,這些可視屬性是指表面的色彩、紋理、光滑度、透明度、反射率、折射率、發(fā)光度等。正是有了這些屬性,才能讓我們識(shí)別三維中的模型是什么做成的,也正是有了模型材質(zhì)。

我們?cè)贠penGL中模擬多種類型的物體, 我們必須為每個(gè)物體分別定義材質(zhì)(Material)屬性.
類似面向?qū)ο缶幊? 比如當(dāng)前類應(yīng)該具有什么內(nèi)容.

在片元著色器中

用結(jié)構(gòu)體定義一個(gè)材質(zhì)的組成

//材質(zhì)
struct Material {
    vec3 ambient;//材質(zhì)向量定義了在環(huán)境光照下這個(gè)物體反射的是什么顏色,通常和物體顏色相同.
    vec3 diffuse;//材質(zhì)向量定義了在漫反射光照t下物體的顏色,漫反射顏色被設(shè)置為我們需要的物體顏色.
    vec3 specular;//材質(zhì)向量設(shè)置的是物體受到的鏡面光照的影響的顏色.
    float shininess;//鏡面反射散射因子(半徑).
};
uniform Material material;//材質(zhì)

用結(jié)構(gòu)體定義一個(gè)材質(zhì)的光照強(qiáng)度組成

//光照強(qiáng)度
struct Light {
    vec3 position;
    vec3 ambientStrength;//環(huán)境光照強(qiáng)度
    vec3 diffuseStrength;//漫反射光照強(qiáng)度
    vec3 specularStrength;//鏡面反射光照強(qiáng)度
};
uniform Light light;

賦值操作

//材質(zhì)
GLint matAmbientLoc = glGetUniformLocation(myProgram.program, "material.ambient");
GLint matDiffuseLoc = glGetUniformLocation(myProgram.program, "material.diffuse");
GLint matSpecularLoc = glGetUniformLocation(myProgram.program, "material.specular");
GLint matShineLoc = glGetUniformLocation(myProgram.program, "material.shininess");

glUniform3f(matAmbientLoc, 1.0f, 0.5f, 0.31f);
glUniform3f(matDiffuseLoc, 1.0f, 0.5f, 0.31f);
glUniform3f(matSpecularLoc, 0.5f, 0.5f, 0.5f);
glUniform1f(matShineLoc, 64.0f);
        

//光照強(qiáng)度
GLint lightAmbientStrengthLoc = glGetUniformLocation(myProgram.program, "light.ambientStrength");
GLint lightDiffuseStrengthLoc = glGetUniformLocation(myProgram.program, "light.diffuseStrength");
GLint lightSpecularStrengthLoc = glGetUniformLocation(myProgram.program, "light.specularStrength");

glUniform3f(lightAmbientStrengthLoc, 0.2f, 0.2f, 0.2f);
glUniform3f(lightDiffuseStrengthLoc, 0.5f, 0.5f, 0.5f);
glUniform3f(lightSpecularStrengthLoc, 1.0f, 1.0f, 1.0f);



Shader

#define STRINGIZE(x) #x
#define SHADER(shader) STRINGIZE(shader)

/// 著色器程序之間的數(shù)據(jù)傳遞
static char *myMaterialVertexShaderStr = SHADER(
    \#version 330 core\n
                                             
    layout (location = 0) in vec3 position; //頂點(diǎn)數(shù)據(jù)源輸入
    layout (location = 1) in vec3 normal; //法向量
                                              
    uniform mat4 myProjection;//投影矩陣
    uniform mat4 myView;//觀察矩陣
    uniform mat4 myModel;//模型矩陣
                                             
    out vec3 Normal;//法線向量
    out vec3 FragPos;//片段位置

    void main()
    {
        gl_Position = myProjection * myView * myModel * vec4(position, 1.0f);
        Normal = normal;
        FragPos = vec3(myModel * vec4(position, 1.0f) );
    }
);

//片元著色器程序
static char *myMaterialFragmentShaderSrc = SHADER(
    \#version 330 core\n
    //材質(zhì)
    struct Material {
        vec3 ambient;//材質(zhì)向量定義了在環(huán)境光照下這個(gè)物體反射的是什么顏色,通常和物體顏色相同.
        vec3 diffuse;//材質(zhì)向量定義了在漫反射光照t下物體的顏色,漫反射顏色被設(shè)置為我們需要的物體顏色.
        vec3 specular;//材質(zhì)向量設(shè)置的是物體受到的鏡面光照的影響的顏色.
        float shininess;//鏡面反射散射因子(半徑).
    };
    uniform Material material;//材質(zhì)

    //光照強(qiáng)度
    struct Light {
        vec3 position;
        vec3 ambientStrength;//環(huán)境光照強(qiáng)度
        vec3 diffuseStrength;//漫反射光照強(qiáng)度
        vec3 specularStrength;//鏡面反射光照強(qiáng)度
    };
    uniform Light light;

    in vec3 Normal;
    in vec3 FragPos;

    uniform vec3 lightColor;//光照顏色
    uniform vec3 lightPos;//光源位置
    uniform vec3 viewPos;//鏡面反射

    out vec4 color;
                                                               
    void main()
    {
        //環(huán)境光ambient
        //環(huán)境顏色 = 光源顏色 × 物體的環(huán)境材質(zhì)顏色 × 環(huán)境光照強(qiáng)度
        vec3 ambient = lightColor * material.ambient * light.ambientStrength;
    
        //漫反射diffuse
        //DiffuseFactor = max(0, dot(N, L))
        //漫反射顏色 = 光源顏色 × 物體的漫反射材質(zhì)顏色 × 漫反射因子(diffuseFactor) × 漫反射光照強(qiáng)度
        vec3 norm = normalize(Normal);
        vec3 lightDir = normalize(lightPos - FragPos);
        float diffuseFactor = max(dot(norm, lightDir),0.0);
        vec3 diffuse = lightColor * material.ambient * diffuseFactor * light.diffuseStrength;
        
        //鏡面反射specular
        //R=reflect(L, N)
        //SpecularFactor = pow(max(dot(R,V),0.0), shininess)
        //鏡面反射顏色 = 光源顏色 × 物體的鏡面材質(zhì)顏色 × 鏡面反射因子(SpecularFactor) × 鏡面反射光照強(qiáng)度
        vec3 viewDir = normalize(viewPos - FragPos);
        vec3 reflectDir = reflect(-lightDir , norm);
        float specularFactor = pow(max(dot(viewDir, reflectDir),0.0),material.shininess);
        vec3 specular = lightColor * material.ambient * specularFactor * light.specularStrength;

        //最終片段顏色:環(huán)境顏色+漫反射顏色+鏡面反射顏色
        vec3 result = ambient + diffuse + specular;
        color = vec4(result , 1.0f);
    }
);

頂點(diǎn)數(shù)據(jù)

#include "glad.h"
#include <GLFW/glfw3.h>


GLfloat myMaterialVertices[] = {
    //頂點(diǎn)數(shù)據(jù)              法線
   -0.5f, -0.5f, -0.5f,   0.0f,  0.0f, -1.0f,
    0.5f, -0.5f, -0.5f,   0.0f,  0.0f, -1.0f,
    0.5f,  0.5f, -0.5f,   0.0f,  0.0f, -1.0f,
    0.5f,  0.5f, -0.5f,   0.0f,  0.0f, -1.0f,
   -0.5f,  0.5f, -0.5f,   0.0f,  0.0f, -1.0f,
   -0.5f, -0.5f, -0.5f,   0.0f,  0.0f, -1.0f,

   -0.5f, -0.5f,  0.5f,   0.0f,  0.0f,  1.0f,
    0.5f, -0.5f,  0.5f,   0.0f,  0.0f,  1.0f,
    0.5f,  0.5f,  0.5f,   0.0f,  0.0f,  1.0f,
    0.5f,  0.5f,  0.5f,   0.0f,  0.0f,  1.0f,
   -0.5f,  0.5f,  0.5f,   0.0f,  0.0f,  1.0f,
   -0.5f, -0.5f,  0.5f,   0.0f,  0.0f,  1.0f,

   -0.5f,  0.5f,  0.5f,  -1.0f,  0.0f,  0.0f,
   -0.5f,  0.5f, -0.5f,  -1.0f,  0.0f,  0.0f,
   -0.5f, -0.5f, -0.5f,  -1.0f,  0.0f,  0.0f,
   -0.5f, -0.5f, -0.5f,  -1.0f,  0.0f,  0.0f,
   -0.5f, -0.5f,  0.5f,  -1.0f,  0.0f,  0.0f,
   -0.5f,  0.5f,  0.5f,  -1.0f,  0.0f,  0.0f,

    0.5f,  0.5f,  0.5f,   1.0f,  0.0f,  0.0f,
    0.5f,  0.5f, -0.5f,   1.0f,  0.0f,  0.0f,
    0.5f, -0.5f, -0.5f,   1.0f,  0.0f,  0.0f,
    0.5f, -0.5f, -0.5f,   1.0f,  0.0f,  0.0f,
    0.5f, -0.5f,  0.5f,   1.0f,  0.0f,  0.0f,
    0.5f,  0.5f,  0.5f,   1.0f,  0.0f,  0.0f,

   -0.5f, -0.5f, -0.5f,   0.0f, -1.0f,  0.0f,
    0.5f, -0.5f, -0.5f,   0.0f, -1.0f,  0.0f,
    0.5f, -0.5f,  0.5f,   0.0f, -1.0f,  0.0f,
    0.5f, -0.5f,  0.5f,   0.0f, -1.0f,  0.0f,
   -0.5f, -0.5f,  0.5f,   0.0f, -1.0f,  0.0f,
   -0.5f, -0.5f, -0.5f,   0.0f, -1.0f,  0.0f,

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

程序

#include <iostream>

#include "MyMaterial.hpp"
#include "MyProgram.hpp"
#include "MyMaterialShader.h"
#include "MyMaterialVertices.h"
#include "glm.hpp"
#include "matrix_transform.hpp"
#include "type_ptr.hpp"

#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_STATIC
#include "stb_image.h"


int runMyMaterialCube() {
    int result = glfwInit();
    if (result == GL_FALSE) {
        printf("glfwInit 初始化失敗");
        return -1;
    }
    
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
    GLFWwindow *window = glfwCreateWindow(600, 400, "My Opengl Window", NULL, NULL);
    if(!window) {
        printf("window 創(chuàng)建失敗");
    }
    glfwMakeContextCurrent(window);
    gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);

    //切換為紋理著色器程序
    MyProgram myProgram = MyProgram(myMaterialVertexShaderStr, myMaterialFragmentShaderSrc);

    ///
    GLuint VBO , VAO ;
    unsigned int squareIndicesCount = 0;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(myMaterialVertices), myMaterialVertices, GL_STATIC_DRAW);
    
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(0 * sizeof(GLfloat)));
    glEnableVertexAttribArray(0);

    //法線
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(1);

    //解綁VAO
    glBindVertexArray(0);
    squareIndicesCount = sizeof(myMaterialVertices)/(sizeof(myMaterialVertices[0]) * 5);

    glEnable(GL_DEPTH_TEST);


    
    //進(jìn)行繪制
    while(!glfwWindowShouldClose(window)){
        glfwPollEvents();
        
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glUseProgram(myProgram.program);
        
        
        //================================================
        glm::mat4 model = glm::mat4(1.0f);
        glm::mat4 view = glm::mat4(1.0f);
        glm::mat4 projection = glm::mat4(1.0f);
        
        GLint myModelLoc = glGetUniformLocation(myProgram.program,"myModel");
        GLint myViewLoc = glGetUniformLocation(myProgram.program,"myView");
        GLint myProjectionLoc = glGetUniformLocation(myProgram.program,"myProjection");
        
        projection = glm::perspective(glm::radians(60.0f), 1.0f, 0.01f, 100.f);//投影矩陣
        glUniformMatrix4fv(myProjectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
        
//        model = glm::rotate(model,(GLfloat)glfwGetTime() * 1.0f, glm::vec3(1.0f,0.0f,0.0f));//以x,y軸旋轉(zhuǎn)
        glUniformMatrix4fv(myModelLoc, 1, GL_FALSE, glm::value_ptr(model));

        // Material
        glm::vec3 MaterialEye   = glm::vec3(2.0f, 2.0f,  2.0f);
        glm::vec3 MaterialCenter = glm::vec3(0.0f, 0.0f, 0.0f);
        glm::vec3 MaterialUp    = glm::vec3(0.0f, 1.0f,  0.0f);
        
        glBindVertexArray(VAO);
        view = glm::lookAt(MaterialEye,       //攝像機(jī)位置
                           MaterialCenter,    //目標(biāo)
                           MaterialUp);       //上向量
        
        //================================================

        
        
        
        
        //================================================
        
        //材質(zhì)
        GLint matAmbientLoc = glGetUniformLocation(myProgram.program, "material.ambient");
        GLint matDiffuseLoc = glGetUniformLocation(myProgram.program, "material.diffuse");
        GLint matSpecularLoc = glGetUniformLocation(myProgram.program, "material.specular");
        GLint matShineLoc = glGetUniformLocation(myProgram.program, "material.shininess");

        glUniform3f(matAmbientLoc, 1.0f, 0.5f, 0.31f);
        glUniform3f(matDiffuseLoc, 1.0f, 0.5f, 0.31f);
        glUniform3f(matSpecularLoc, 0.5f, 0.5f, 0.5f);
        glUniform1f(matShineLoc, 64.0f);
        

        //光照強(qiáng)度
        GLint lightAmbientStrengthLoc = glGetUniformLocation(myProgram.program, "light.ambientStrength");
        GLint lightDiffuseStrengthLoc = glGetUniformLocation(myProgram.program, "light.diffuseStrength");
        GLint lightSpecularStrengthLoc = glGetUniformLocation(myProgram.program, "light.specularStrength");

        glUniform3f(lightAmbientStrengthLoc, 0.2f, 0.2f, 0.2f);
        glUniform3f(lightDiffuseStrengthLoc, 0.5f, 0.5f, 0.5f);
        glUniform3f(lightSpecularStrengthLoc, 1.0f, 1.0f, 1.0f);

        //光源位置
        GLint myLightPosLoc = glGetUniformLocation(myProgram.program,"lightPos");
        glUniform3f(myLightPosLoc,1.0f,0.0f,4.0f); //
        
        //鏡面反射
        GLint myViewPosLoc = glGetUniformLocation(myProgram.program,"viewPos");
        glUniform3f(myViewPosLoc,0.0,0.0f,3.0f); //
        
        //光照顏色
        GLint lightColorLoc = glGetUniformLocation(myProgram.program,"lightColor");
        glUniform3f(lightColorLoc,1.0f,1.0f,1.0f); //白光
        
        //動(dòng)態(tài)改變環(huán)境光和漫反射光顏色
        glm::vec3 lightColor = glm::vec3(1.0f,1.0f,1.0f);
        lightColor.x = sin(glfwGetTime() * 2.0f);
        lightColor.y = sin(glfwGetTime() * 0.7f);
        lightColor.z = sin(glfwGetTime() * 1.3f);
        
        glm::vec3 ambientColor = lightColor * glm::vec3(0.5f);
        glm::vec3 diffuseColor = lightColor * glm::vec3(0.5f);

        glUniform3f(matAmbientLoc,ambientColor.x,ambientColor.y,ambientColor.z);
        glUniform3f(matDiffuseLoc,diffuseColor.x,diffuseColor.y,diffuseColor.z);
        //================================================

                    
        glUniformMatrix4fv(myViewLoc, 1, GL_FALSE, glm::value_ptr(view));
        glDrawArrays(GL_TRIANGLES, 0, squareIndicesCount);
        glBindVertexArray(0);

        glfwSwapBuffers(window);
    }

    //程序銷毀
    glfwTerminate();
    
    return 1;
}

效果

材質(zhì)

趣味效果: 動(dòng)態(tài)改變環(huán)境光照和漫反射

//動(dòng)態(tài)改變環(huán)境光和漫反射光顏色
glm::vec3 lightColor = glm::vec3(1.0f,1.0f,1.0f);
lightColor.x = sin(glfwGetTime() * 2.0f);
lightColor.y = sin(glfwGetTime() * 0.7f);
lightColor.z = sin(glfwGetTime() * 1.3f);
        
glm::vec3 ambientColor = lightColor * glm::vec3(0.5f);
glm::vec3 diffuseColor = lightColor * glm::vec3(0.5f);

glUniform3f(matAmbientLoc,ambientColor.x,ambientColor.y,ambientColor.z);
glUniform3f(matDiffuseLoc,diffuseColor.x,diffuseColor.y,diffuseColor.z);
材質(zhì)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容