zoukankan      html  css  js  c++  java
  • D3D中的光照

    D3D中光源可大致分为3种,点光源,方向光,环境光

    1)

    可以大致对应我们生活中的 电灯泡,太阳光,环境光。通过抽象各种光的性质,我们可以使用结构体Light,以更方便地表示光。

    光可以定义如下

    Struct Light
    {
      D3DXVECTOR3 pos;//位置
      D3DXVECTOR3 dir;//方向
      D3DXCOLOR ambiet;//环境光颜色
      D3DXCOLOR diffuse;//漫反射颜色
      D3DXCOLOR specular;//镜面反射颜色
      float      power;//光强
    
    }

    从C++代码中定义各个分量,再通过Effect接口传入效果文件中。定义光源。下面是使用Light结构体定义一个具体的光(方向光的例子

    C++代码:

        mParallelLight.dir      = D3DXVECTOR3(0.57735f, -0.57735f, 0.57735f);
        mParallelLight.ambient  = D3DXCOLOR(0.4f, 0.4f, 0.4f, 1.0f);
        mParallelLight.diffuse  = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
        mParallelLight.specular = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);

    2)

    与之前的顶点赋色不同,当有光照参与时,需要为物体设置材质。通过计算光照与材质,最终得到物体的颜色。

    例如

    struct Material
    {
        Material()
        {
            ZeroMemory(this,sizeof(Material));
        }
    
        D3DXCOLOR ambient;
        D3DXCOLOR diffuse;
        D3DXCOLOR specular;
        float specpow;
    };

    由于D3D用三角形网格描述物体,而网格最终由顶点组成。所以材质的定义还是要落在顶点属性里。

    例如

    struct Vertex
    {
      D3DVECTOR3  pos;
      D3DVECTOR3 normal;
      D3DXCOLOR ambient; 
      D3DXCOLOR diffuse;
      D3DXCOLOR specular;
    }

    通过定义顶点布局,使效果文件知道如何使用Vertex的各个分量。

    3)

    光照与材质生成物体颜色的计算过程,我们在像素着色器中完成。

    下面是以平行光照射物体的处理为例。一段像素着色器的HLSL代码

    float4 PS(VS_OUT pIn) : SV_Target
    {
        pIn.normalW = normalize(pIn.normalW);
        SurfaceInfo v = {pIn.posW, pIn.normalW, pIn.diffuse, pIn.spec};
        
        float3 litColor;
        litColor = ParallelLight(v, gLight, gEyePosW);
              
        return float4(litColor, pIn.diffuse.a);
    }

    补充平行光与材质作用的具体光照方程(HLSL):

    float3 ParallelLight(SurfaceInfo v, Light L, float3 eyePos)
    {
        float3 litColor = float3(0.0f, 0.0f, 0.0f);
     
        // The light vector aims opposite the direction the light rays travel.
        float3 lightVec = -L.dir;
        
        // Add the ambient term.
        litColor += v.diffuse * L.ambient;    
        
        // Add diffuse and specular term, provided the surface is in 
        // the line of site of the light.
        
        float diffuseFactor = dot(lightVec, v.normal);
        [branch]
        if( diffuseFactor > 0.0f )
        {
            float specPower  = max(v.spec.a, 1.0f);
            float3 toEye     = normalize(eyePos - v.pos);
            float3 R         = reflect(-lightVec, v.normal);
            float specFactor = pow(max(dot(R, toEye), 0.0f), specPower);
                        
            // diffuse and specular terms
            litColor += diffuseFactor * v.diffuse * L.diffuse;
            litColor += specFactor * v.spec * L.spec;
        }
        
        return litColor;
    }

    在我们的程序中,存放在顶点缓冲区中的顶点数据首先经过顶点着色器,从顶点着色器出来后,进入像素着色器。完成光照计算。

  • 相关阅读:
    Java基础(九)--反射
    Java基础(八)--String(源码)、StringBuffer、StringBuilder
    Java基础(七)--Exception异常处理
    Java基础(五)--内部类
    Redis系列(十一)--阿里云开发规范
    Java基础(四)--接口和抽象类
    Java基础(三)--final关键字
    生成count个[0-n)不重复的随机数
    Java基础(二)--this关键字及初始化
    十大Intellij IDEA快捷键(附IDEA快捷键详细列表及使用技巧)
  • 原文地址:https://www.cnblogs.com/CAION/p/2921379.html
Copyright © 2011-2022 走看看