zoukankan      html  css  js  c++  java
  • CS184.1X 计算机图形学导论 第7讲 学习笔记

    L7V1:OPENGL 着色:学习动机

    1.光照的重要性

    1)能够真正显示出形状感知的外观;

    2)准确的着色和光照对对传达物体的形状非常重要;

    3)着色的方式也十分重要:平面着色(GL_FLAT)、平滑着色(GL_SMOOTH)。

    2.颜色

    1)RGB模式:分为Red、Green、Blue三个通道

    2)RGBA模式:OpenGL中常用此模式,A代表着透明度,每个通道占8bit,总共4字节。

    L7V2:OPENGL 着色:Gouraud and Phong Shading

    1.Gouraud Shading--标准的平滑着色

    1)方法:采用线性插值的方法进行平滑着色;

    2)变量说明:I1、I2、I3分别为三个顶点的颜色值,Ip为所要求的颜色值,Ia、Ib为横向扫描线上的交点;

    3)公式推导:

    a.首先沿Y轴方向插值,得到Ia、Ib

    b.在扫描线上沿X轴方向插值,得到Ip

    4)极端情况:当以上公式分母等于0时,该公式无法进行插值;

          解决方法:将模型细化,分割成足够多的三角形。

    2.Phong Shading (≠ Phong Illumination)

    1)思想:不是对颜色进行插值,而是对法向量进行插值;

    2)整个光照计算是逐个像素进行的;

    L7V3:OPENGL 着色:光照和着色

    1.光源

    1)属性:Position、Color;

    2)衰减模型:

    其中:atten代表光强,d代表距离,kc、kl、kq为常数;

    3)常数设置(一般情况下,假设光源不存在能量衰竭):

    a)点光源:(kc, kl, kq)=(0, 0, 1);

    b)线光源:(kc, kl, kq)=(0, 1, 0);

    c)面光源(方向光源):(kc, kl, kq)=(1, 0, 0),此处忽略光强衰减;

    2.材质

    1)计算法向量 -->进而计算漫反射、镜面反射的反射方向;需要计算出每一个顶点的法向量;

         一些由GLUT提供的图形,GLUT已经计算好了法向量;

    2)着色模式:

    A)环境光(Ambient):即使没有光照射到表面,仍然有光在屋内来回反射,并且产生了漫反射或环境光的感觉;需要设置一个环境光强度,一般来说很小,使不存在黑色的像素;

    B)漫反射(Diffuse):对应粗糙不光滑的表面,如墙壁、地板;光均匀地向各个方向反射;

    C)镜面反射(Specular):对应于光滑的物体;

    D)发射光(Emissive):对应于太阳光等光源,对应于直接看向光源发出的光,而不是反射方向的,在OpenGL中,想看到光源还必须创建光源的几何体;

    3.Phong Illumination

    1)简单依赖于视点的高光,不基于物理;

     2)思想:a)在镜面反射上,选择视线和反射光线之间进行点积,更进一步,给cos项加上指数来控制表面的光泽度,高光到底有多亮;b)取光源、视线之间的角度的一半,求视线和法向的点积,这样会更接近;

    3)Phong Formula

    specular = Ks * lightcolor * (dot(V, R))shininess

    【说明】

    Ks:物体对于反射光线的衰减系数

    N:表面法向量

    H:光入射方向L和视点方向V的中间向量

    Shininess:高光系数

    Phong模型计算中的一个关键步骤就是反射向量R的计算:

    上图中的位于表面“下面”的向量 ‘I’ 是原始 ‘I’ 向量的拷贝,并且二者是一样的,现在我们的目标计算出向量'R'。根据向量相加原则,向量'R'等于'I'+'V','I'是已知的,所以我们需要做的就是找出向量'V'。注意法向量 ‘N’ 的负方向就是 ‘-N’,我们可以在 ‘I’ 和 ‘-N’ 之间使用一个点乘运算就能得到 ‘I’ 在 ‘-N’ 上面的投影的模。这个模正好是 ‘V’ 的模的一半,由于 ‘V’ 与 ‘N’ 有相同的方向,我们可以将这个模乘上 ‘N’ (其模为 1 )再乘上 2 即可得到 ‘V’。总结一下就是下面的公式:

    R = I + V

    V = 2 * N * ( -N * I )

    得出:R = I + 2 * N * ( -N * I ) = I - 2 * N * ( N * I )

    4)Blinn-Phong Formula

    Phong模型中计算反射光线的向量是一件相对比较耗时的任务,因此Blinn-Phong对这一点进行了改进。

    specular = Ks * lightcolor * (dot(V, H))shininess

    【说明】

    Ks:物体对于反射光线的衰减系数

     

    N:表面法向量

     

    H:光入射方向L和视点方向V的中间向量

     

    Shininess:高光系数

    可见,通过该式计算镜面反射光是符合基本规律的,当视点方向和反射光线方向一致时,计算得到的H与N平行,dot(N,H)取得最大;当视点方向V偏离反射方向时,H也偏离N。同时H的计算比起反射向量R的计算简单的多,R向量的计算需要若干次的向量乘法与加法,而H的计算仅仅需要一次加法。

     

    L7V4:OPENGL 着色:片元着色器

    1.片元着色器的设置

    1 # version 120 
    2 
    3 varying vec4 color ;
    4 varying vec3 mynormal ; 
    5 varying vec4 myvertex ; 
    6 
    7 uniform sampler2D tex ; 
    8 uniform int istex ; 
    9 uniform int islight ; // are we lighting. 

    【说明】

    3-5行:由顶点着色器简单传入颜色、法向、顶点;7-8行:sampler2D tex用于纹理,istex表示是否是纹理,islight表示是否是光源,uniform表示在片元着色器中一直不变;

    2.着色器变量

     1 // Assume light 0 is directional, light 1 is a point light.  
     2 // The actual light values are passed from the main OpenGL program. 
     3 
     4 uniform vec3 light0dirn ; 
     5 uniform vec4 light0color ; 
     6 uniform vec4 light1posn ; 
     7 uniform vec4 light1color ; 
     8 
     9 // Now, set the material parameters.  These could be varying and/or 
    10 // bound to a buffer.  But for now, I'll just make them uniform.  
    11 
    12 uniform vec4 ambient ; 
    13 uniform vec4 diffuse ; 
    14 uniform vec4 specular ; 
    15 uniform float shininess ; 

    【说明】

    6行:vec4 light1posn:这是齐次坐标下一个位置处的光源;

    12-15行:设置材质参数:环境光系数、漫反射系数、镜面反射系数、光泽度;

    3.计算光照

     1 vec4 ComputeLight (const in vec3 direction, const in vec4 lightcolor, 
     2         const in vec3 normal, const in vec3 halfvec, const in vec4 mydiffuse,
     3         const in vec4 myspecular, const in float myshininess) {
     4 
     5     float nDotL = dot(normal, direction)  ;         
     6     vec4 lambert = mydiffuse * lightcolor * max (nDotL, 0.0) ;  
     7 
     8     float nDotH = dot(normal, halfvec) ; 
     9     vec4 phong = myspecular * lightcolor * pow (max(nDotH, 0.0), myshininess) ; 
    10 
    11     vec4 retval = lambert + phong ; 
    12     return retval ;            
    13 }    

    【说明】此处算法参考Phong光照模型

    4.主要变换代码

     1         // They eye is always at (0,0,0) looking down -z axis 
     2         // Also compute current fragment position and direction to eye 
     3 
     4         const vec3 eyepos = vec3(0,0,0) ; 
     5         vec4 _mypos = gl_ModelViewMatrix * myvertex ; 
     6         vec3 mypos = _mypos.xyz / _mypos.w ; // Dehomogenize current location 
     7         vec3 eyedirn = normalize(eyepos - mypos) ; 
     8 
     9         // Compute normal, needed for shading. 
    10         // Simpler is vec3 normal = normalize(gl_NormalMatrix * mynormal) ; 
    11         vec3 _normal = (gl_ModelViewMatrixInverseTranspose*vec4(mynormal,0.0)).xyz ; 
    12         vec3 normal = normalize(_normal) ; 
    13 
    14         // Light 0, directional
    15         vec3 direction0 = normalize (light0dirn) ; 
    16         vec3 half0 = normalize (direction0 + eyedirn) ; 
    17         vec4 col0 = ComputeLight(direction0, light0color, normal, half0, diffuse, specular, shininess) ;
    18 
    19         // Light 1, point 
    20         vec3 position = light1posn.xyz / light1posn.w ; 
    21         vec3 direction1 = normalize (position - mypos) ; // no attenuation 
    22         vec3 half1 = normalize (direction1 + eyedirn) ;  
    23         vec4 col1 = ComputeLight(direction1, light1color, normal, half1, diffuse, specular, shininess) ;
    24 
    25         gl_FragColor = ambient + col0 + col1 ; 

    【说明】11行:思维矩阵转置后,我们只取xyz分量部分,去掉齐次坐标部分;

     

  • 相关阅读:
    [模板] 文艺平衡树
    [模板]平衡树splay
    [ZJOI2015]诸神眷顾的幻想乡
    [HAOI2016]找相同字符
    SP8093 JZPGYZ
    SP1812 LCS2
    SP1811 LCS
    AHOI2013 差异
    TJOI2015 弦论
    工艺(SAM)
  • 原文地址:https://www.cnblogs.com/mzyan/p/9641982.html
Copyright © 2011-2022 走看看