• HLSL之漫反射光


         整整忙了一个月了,总算清闲下来了,从上次写完环境光后又过了这么长时间,继续学习......加油!!今天整理下漫反射光并记录下来,那就直接进入主题吧,开始漫反射光的学习。

         漫反射光是在环境光的基础上添加一个定向光让物体看起来更真实,定向光照射到物体表面,会根据物体表面不同的凹凸程度呈现出强度差异的反射光,让物体看起来更有立体感;当光线方向固定后,决定反射光强度的就是物体表面的法线方向。如果光线方向平行于物体表面(即和物体表面的法线垂直时)这时候的反射光是最弱的,如果光线方向垂直于物体表面(即和物体表面的法线平行时)这时候的反射光是最强的。

        漫反射光的公式:I = Aintensity*Acolor + Dintensity*Dcolor *N.L 

        公式说明:前面的Aintensity*Acolor仍然是环境光的公式,后面一部分表示添加的反射光,其中Dintensity表示光照强度,Dcolor 表示颜色,N表示物体表面的法线,L表示光线方向,N.L则是N和L两向量的点乘,等价于:N.L=|N|*|L|*cos(a)(a为两法线夹角).注意:L的方向是自顶点指向光源的。

        下面看看相对于环境光代码相关变动的地方,除了Draw中的变化,其他代码均无变化,所以这里主要看看Draw里面的代码

                effect.CurrentTechnique = effect.Techniques["DiffuseLight"]; //读取fx
    
                foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                {
                    pass.Apply();
                    foreach (ModelMesh mesh in model.Meshes)
                    {
                        foreach (ModelMeshPart part in mesh.MeshParts)
                        {
                            effect.Parameters["World"].SetValue(modelTransform[mesh.ParentBone.Index] * Matrix.CreateScale(30.0f) * Matrix.CreateRotationY((float)angle) * Matrix.CreateRotationX((float)angle));
                            effect.Parameters["View"].SetValue(viewMatrix);
                            effect.Parameters["Projection"].SetValue(projectionMatrix);
                            effect.Parameters["AmbientColor"].SetValue(new Vector4(0.0f, 0.5f, 0f, 1.0f));
                            effect.Parameters["DiffuseColor"].SetValue(new Vector4(1.0f, 0.4f, 0.24f, 0.1f));
                            effect.Parameters["AmbientIntensity"].SetValue(0.5f);
                            effect.Parameters["LightDirection"].SetValue(Vector4.Normalize(new Vector4(1, 0, 0.0f, 1.0f)));
    
                            graphics.GraphicsDevice.SetVertexBuffer(part.VertexBuffer);
                            graphics.GraphicsDevice.Indices = part.IndexBuffer;
    
                            graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, part.VertexOffset, 0, part.NumVertices, part.StartIndex, part.PrimitiveCount);
                        }
                    }
                }

               代码中可以看出环境光AmbientColor:Vector4(0,0.5,0,1)这样做的目地是为了可以在下面的截图中看到意图,同时光线方向是平行于X轴指向X轴正半轴的。下面看看运行效果

                               

      其中橘黄色是反射光的颜色也即是DiffuseColor:Vector4(1.0f, 0.4f, 0.24f, 0.1f),而绿色是环境光的颜色AmbientColor:Vector4(0,0.5,0,1)光线方向是沿着X轴。可以看到未被照射到的地方色差明显。此时我们修改下LightDirection将其改成Vector4(0, 0, 1.0f, 1.0f) 沿着Z轴正方向(对比两张效果图即可明白光线方向的不同对最终效果的影响)

                        

           接下来我们看看fx里面的代码:

    float4x4 World;
    float4x4 View;
    float4x4 Projection;
    float4 AmbientColor;
    float4 DiffuseColor;
    float AmbientIntensity;
    float4 LightDirection;
    
    // TODO: add effect parameters here.
    
    struct VertexShaderInput
    {
        float4 Position : POSITION0;
    };
    
    struct VertexShaderOutput
    {
        float4 Position : POSITION0;
        float3 N:TEXCOORD0;
    };
    
    VertexShaderOutput VertexShaderDiffuse(float4 Position:POSITION0,float3 N:NORMAL)
    {
        VertexShaderOutput output;
    
        float4 worldPosition = mul(Position, World);
        float4 viewPosition = mul(worldPosition, View);
        output.Position = mul(viewPosition, Projection);
    
        output.N=normalize(mul(N,World));
    
        return output;
    }
    
    float4 PixelShaderDiffuse(VertexShaderOutput input) : COLOR0
    {
        return AmbientColor*AmbientIntensity+1.0f*DiffuseColor*saturate(dot(LightDirection,input.N));
    }
    
    technique DiffuseLight
    {
        pass Pass0
        {
            // TODO: set renderstates here.
            VertexShader = compile vs_2_0 VertexShaderDiffuse();
            PixelShader = compile ps_2_0 PixelShaderDiffuse();
        }
    }

         除了公式不同以外,在这里我们看到一个TEXCOORD0,TEXCOORDN是可以存放任何数据的寄存器,在相应位置没有存放纹理坐标的时候可以用来存储任何数据,并在以后读取出来。

        漫反射光的知识也就这么多了,期待下节镜面反射光照的学习.......

  • 相关阅读:
    StringTable
    TCP网络协议
    也说JVM内存区域
    JVM类加载
    java中的引用:强、软、弱、虚
    AQS
    vscode支持unicode编码
    设计模式简记-快速改善代码质量的编程规范
    擅事利器
    设计模式简记-通过重构增强代码可测试性实战
  • 原文地址:https://www.cnblogs.com/wangyong/p/3145709.html
Copyright © 2020-2023  润新知