zoukankan      html  css  js  c++  java
  • GLSL 中的光照计算

    理论知识转载地址:http://blog.csdn.net/ym19860303/article/details/25545933

    1.Lambert模型(漫反射)

    环境光:

    Iambdiff = Kd*Ia

    其中Ia 表示环境光强度,Kd(0<K<1)为材质对环境光的反射系数,Iambdiff是漫反射体与环境光交互反射的光强。

    方向光:

    Ildiff = Kd * Il * Cos(θ)

    其中Il是点光源强度,θ是入射光方向与顶点法线的夹角,称入射角(0<=A<=90°),Ildiff是漫反射体与方向光交互反射的光强,若 N为顶点单位法向量,L表示从顶点指向光源的单位向量(注意顶点指向光源),则Cos(θ)等价于dot(N,L),故又有:

    Ildiff = Kd * Il * dot(N,L)

    最后综合环境光和方向光源,Lambert光照模型可以写成:

    Idiff = Iambdiff + Ildiff = Kd * Ia + Kd * Il * dot(N,L)

    2.Phong模型(镜面反射)

    Phong模型认为镜面反射的光强与反射光线和视线的夹角相关:

    Ispec = Ks * Il * ( dot(V,R) )^Ns

    其中Ks 为镜面反射系数,Ns是高光指数,V表示从顶点到视点的观察方向,R代表反射光方向。由于反射光的方向R可以通过入射光方向L(从顶点指向光源)和物体的法向量求出,
    R + L = 2 * dot(N, L) * N  即 R = 2 * dot(N,L) * N - L

    所以最终的计算式为:

    Ispec = Ks * Il * ( dot(V, (2 * dot(N,L) * N – L ) )^Ns

    3.Blinn-Phong光照模型(修正镜面光)

    Blinn-Phong是一个基于Phong模型修正的模型,其公式为:

    Ispec = Ks * Il * ( dot(N,H) )^Ns

    其中N是入射点的单位法向量,H是光入射方向L和视点方向V的中间向量,通常也称之为半角向量(半角向量被广泛用于各类光照模型,原因不但在于半角向量蕴含的信息价值,也在于半角向量是很简单的计算:H = (L + V) / |L + V|  )。

    4.Rendering Equation(全局光照模型)

    Rendering Equation 是Kajia在1986年提出的,

    Lo(X, Wo) = Le(X, Wo) + ∫fr(X, Wi, Wo) Li(X, Wi) dot(N, Wi) dWi

    其中X表示入射点,Lo(X, Wo)即从物体表面X点,沿方向Wo反射的光强,Le(X, Wo)表示从物体表面X以方向Wo 发射出去的光强,该值仅对自发光体有效,fr(X, Wi, Wo)为,入射光线方向为Wi, 照射到点X上,然后从Wo方向发射出去的BRDF值,Li(X, Wi)为入射方向为Wi照射到点X上的入射光强,N表示点X处的法向量,然后对入射方向进行积分(因为光线入射的方向是四面八方的,积分的意义是对每个方向进行一遍计算后相加),计算的结果就是全局光照的辐射率。

    对于单个点光源照射到不会自发光的物体上,公式可以简化成:

    Lo(X, Wo) = fr(X, Wi, Wo) Li(X, Wi) dot(N, Wi)

    这个公式非常有用,通常会将该公式分解为漫反射表达式和镜面表达式之和。对于漫反射表面,BRDF可以忽略不计,因为它总是返回某个恒定值,所以可以写成如下形式:

    Lo(X, Wo) = Idiff + frs(X, Wi, Wo) Li(X, Wi) dot(N, Wi)

    其中Idiff表示漫反射分量,使用公式的计算方法,frs(X, Wi, Wo)表示镜面反射的BRDF函数,前面的Phong高光模型,其实是rendering equation在单一光源下针对理想镜面反射的特定推导,对于Phong高光而言:

    frs(X, Wi, Wo) = Ks (dot(N, H)^Ns  / dot(N, Wi)

    基于GLSL的实现(所有光照和材质参数在实际应用时,应该从常量改为uniform,由外部进行控制):

    // 在顶点着色器中处理光照计算(环境光+漫射光+镜面反射)
    const char* ccPositionTextureColorForLight1_v = "
    uniform vec2 translate;

    attribute vec4 a_position;
    attribute vec4 a_color;
    attribute vec2 a_texCoord;
    attribute vec3 a_normal;

    #ifdef GL_ES
    varying mediump vec4 v_color;
    varying mediump vec2 v_texCoord;
    #else
    varying vec4 v_color;
    varying vec2 v_texCoord;
    #endif

    const vec3 lightAmbient = vec3(1.0, 1.0, 1.0);
    const vec3 lightDiffuse = vec3(1.0, 1.0, 1.0);
    const vec3 lightSpecular = vec3(1.0, 1.0, 1.0);
    const vec3 materialAmbient = vec3(1.0, 1.0, 1.0);
    const vec3 materialDiffuse = vec3(1.0, 1.0, 1.0);
    const vec3 materialSpecular = vec3(1.0, 1.0, 1.0);
    const int shininess = 8; // 0-128

    const vec3 eyePosition = vec3(512.0, 128.0, 442.0);
    const vec3 lightDirection = vec3(1.0, 1.0, 1.0);

    void main() {
    vec4 position = CC_MVMatrix * a_position;
    position.x += translate.x;
    position.y += translate.y;
    gl_Position = CC_PMatrix * position;

    vec3 normal = (CC_MVMatrix * vec4(a_normal, 1.0)).xyz;
    vec3 n_normal = normalize(normal);
    vec3 n_lightDirection = normalize(lightDirection);
    float cosNL = max(dot(n_normal, n_lightDirection), 0.0);
    vec4 diffuse = vec4(lightDiffuse * materialDiffuse, 1.0) * cosNL;

    vec4 ambient = vec4(lightAmbient * materialAmbient, 1.0);

    vec3 n_eyePosition = normalize(eyePosition - position.xyz);
    vec3 reflection = 2 * max(dot(n_normal, n_lightDirection), 0.0) * n_normal - n_lightDirection;
    vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_eyePosition, reflection), 0.0), shininess), 1.0);

    v_color = a_color * (diffuse + ambient + specular);
    v_texCoord = a_texCoord;
    }
    ";
    const char* ccPositionTextureColorForLight1_f = "
    #ifdef GL_ES
    precision lowp float;
    #endif

    varying vec4 v_color;
    varying vec2 v_texCoord;

    void main() {
    vec4 color = v_color * texture2D(CC_Texture0, v_texCoord);
    color.a = 1.0;

    gl_FragColor = color;
    }
    ";

    效果:

    // 在片段着色器中处理光照计算(环境光+漫反射+镜面反射)
    const char* ccPositionTextureColorForLight2_v = "
    uniform vec2 translate;

    attribute vec4 a_position;
    attribute vec4 a_color;
    attribute vec2 a_texCoord;
    attribute vec3 a_normal;

    #ifdef GL_ES
    varying mediump vec4 v_position;
    varying mediump vec4 v_color;
    varying mediump vec2 v_texCoord;
    varying mediump vec3 v_normal;
    #else
    varying vec4 v_position;
    varying vec4 v_color;
    varying vec2 v_texCoord;
    varying vec3 v_normal;
    #endif

    void main() {
    vec4 position = CC_MVMatrix * a_position;
    position.x += translate.x;
    position.y += translate.y;
    gl_Position = CC_PMatrix * position;

    v_position = position;
    v_color = a_color;
    v_texCoord = a_texCoord;
    v_normal = (CC_MVMatrix * vec4(a_normal, 1.0)).xyz;
    }
    ";
    const char* ccPositionTextureColorForLight2_f = "
    const vec3 lightAmbient = vec3(1.0, 1.0, 1.0);
    const vec3 lightDiffuse = vec3(1.0, 1.0, 1.0);
    const vec3 lightSpecular = vec3(1.0, 1.0, 1.0);
    const vec3 materialAmbient = vec3(1.0, 1.0, 1.0);
    const vec3 materialDiffuse = vec3(1.0, 1.0, 1.0);
    const vec3 materialSpecular = vec3(1.0, 1.0, 1.0);
    const int shininess = 8; // 0-128

    const vec3 eyePosition = vec3(512.0, 128.0, 442.0);
    const vec3 lightDirection = vec3(1.0, 1.0, 1.0);

    #ifdef GL_ES
    precision lowp float;
    #endif

    varying vec4 v_position;
    varying vec4 v_color;
    varying vec2 v_texCoord;
    varying vec3 v_normal;

    void main() {
    vec4 color = v_color * texture2D(CC_Texture0, v_texCoord);
    color.a = 1.0;

    vec3 normal = v_normal;
    vec3 n_normal = normalize(normal);
    vec3 n_lightDirection = normalize(lightDirection);
    float cosNL = max(dot(n_normal, n_lightDirection), 0.0);
    vec4 diffuse = vec4(lightDiffuse * materialDiffuse, 1.0) * cosNL;

    vec4 ambient = vec4(lightAmbient * materialAmbient, 1.0);

    vec3 n_eyeDirection = normalize(eyePosition - v_position.xyz);
    vec3 reflection = 2 * max(dot(n_normal, n_lightDirection), 0.0) * n_normal - n_lightDirection;
    vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_eyeDirection, reflection), 0.0), shininess), 1.0);
    //vec3 reflection = normalize(n_eyeDirection + n_lightDirection);
    //vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_normal, reflection), 0.0), shininess), 1.0);

    gl_FragColor = color * (ambient + diffuse + specular);
    }
    ";

    效果:

    // 在片段着色器中处理光照计算(环境光+漫反射+镜面反射+衰减系数)
    const char* ccPositionTextureColorForLight3_v = "
    uniform vec2 translate;

    attribute vec4 a_position;
    attribute vec4 a_color;
    attribute vec2 a_texCoord;
    attribute vec3 a_normal;

    #ifdef GL_ES
    varying mediump vec4 v_position;
    varying mediump vec4 v_color;
    varying mediump vec2 v_texCoord;
    varying mediump vec3 v_normal;
    varying float v_distance;
    #else
    varying vec4 v_position;
    varying vec4 v_color;
    varying vec2 v_texCoord;
    varying vec3 v_normal;
    varying float v_distance;
    #endif

    void main() {
    vec4 position = CC_MVMatrix * a_position;
    position.x += translate.x;
    position.y += translate.y;
    gl_Position = CC_PMatrix * position;

    v_position = position;
    v_color = a_color;
    v_texCoord = a_texCoord;
    v_normal = (CC_MVMatrix * vec4(a_normal, 1.0)).xyz;
    }
    ";
    const char* ccPositionTextureColorForLight3_f = "
    const vec3 lightAmbient = vec3(1.0, 1.0, 1.0);
    const vec3 lightDiffuse = vec3(1.0, 1.0, 1.0);
    const vec3 lightSpecular = vec3(1.0, 1.0, 1.0);
    const float lightAttenuationConst = 1.0;
    const float lightAttenuationLinear = 0.0002;
    const float lightAttenuationQuadratic = 0.000001;
    const vec3 materialAmbient = vec3(1.0, 1.0, 1.0);
    const vec3 materialDiffuse = vec3(1.0, 1.0, 1.0);
    const vec3 materialSpecular = vec3(1.0, 1.0, 1.0);
    const int shininess = 8; // 0-128

    const vec3 lightPosition = vec3(1024.0, 512.0, 100.0);
    const vec3 eyePosition = vec3(512.0, 256.0, 442.0);

    #ifdef GL_ES
    precision lowp float;
    #endif

    varying vec4 v_position;
    varying vec4 v_color;
    varying vec2 v_texCoord;
    varying vec3 v_normal;
    varying float v_distance;

    void main() {
    vec4 color = v_color * texture2D(CC_Texture0, v_texCoord);
    color.a = 1.0;

    vec3 lightDirection = lightPosition - v_position.xyz;
    float distance = length(lightDirection);
    float atten = 1.0 / (lightAttenuationConst + lightAttenuationLinear * distance + lightAttenuationQuadratic * distance * distance);

    vec3 normal = v_normal;
    vec3 n_normal = normalize(normal);
    vec3 n_lightDirection = normalize(lightDirection);
    float cosNL = max(dot(n_normal, n_lightDirection), 0.0);
    vec4 diffuse = vec4(lightDiffuse * materialDiffuse, 1.0) * cosNL;

    vec4 ambient = vec4(lightAmbient * materialAmbient, 1.0);

    vec3 n_eyeDirection = normalize(eyePosition - v_position.xyz);
    vec3 reflection = 2 * max(dot(n_normal, n_lightDirection), 0.0) * n_normal - n_lightDirection;
    vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_eyeDirection, reflection), 0.0), shininess), 1.0);
    //vec3 reflection = normalize(n_eyeDirection + n_lightDirection);
    //vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_normal, reflection), 0.0), shininess), 1.0);

    float colorA = color.a;
    gl_FragColor = vec4(color.rgb * (ambient + diffuse + specular).xyz * atten, colorA);
    }
    ";

    效果:

    // 在片段着色器中处理光照计算(环境光+漫反射+镜面反射+聚光灯+衰减系数)
    const char* ccPositionTextureColorForLight4_v = "
    uniform vec2 translate;
    const vec3 spotlightPosition = vec3(512.0, 256.0, 120.0);
    const vec3 lightPosition = vec3(512.0, 256.0, 442.0);
    const vec3 eyePosition = vec3(512.0, 256.0, 442.0);

    attribute vec4 a_position;
    attribute vec4 a_color;
    attribute vec2 a_texCoord;
    attribute vec3 a_normal;

    #ifdef GL_ES
    varying mediump vec4 v_position;
    varying mediump vec4 v_color;
    varying mediump vec2 v_texCoord;
    varying mediump vec3 v_normal;
    varying mediump float v_distance;
    varying mediump vec3 v_lightDirection;
    varying mediump vec3 v_spotlightDirection;
    #else
    varying vec4 v_position;
    varying vec4 v_color;
    varying vec2 v_texCoord;
    varying vec3 v_normal;
    varying float v_distance;
    varying vec3 v_lightDirection;
    varying vec3 v_spotlightDirection;
    #endif

    void main() {
    vec4 position = CC_MVMatrix * a_position;
    position.x += translate.x;
    position.y += translate.y;
    gl_Position = CC_PMatrix * position;

    v_position = position;
    v_color = a_color;
    v_texCoord = a_texCoord;
    v_normal = (CC_MVMatrix * vec4(a_normal, 1.0)).xyz;

    vec3 lightDirection = lightPosition - position.xyz;
    vec3 spotlightDirection = spotlightPosition - position.xyz;
    v_distance = length(lightDirection);
    v_lightDirection = normalize(lightDirection);
    v_spotlightDirection = normalize(spotlightDirection);
    }
    ";
    const char* ccPositionTextureColorForLight4_f = "
    const vec3 lightAmbient = vec3(1.0, 1.0, 1.0);
    const vec3 lightDiffuse = vec3(1.0, 1.0, 1.0);
    const vec3 lightSpecular = vec3(1.0, 1.0, 1.0);
    const float lightAttenuationConst = 1.0;
    const float lightAttenuationLinear = 0.001;
    const float lightAttenuationQuadratic = 0.000001;
    const vec3 materialAmbient = vec3(1.0, 1.0, 1.0);
    const vec3 materialDiffuse = vec3(1.0, 1.0, 1.0);
    const vec3 materialSpecular = vec3(1.0, 1.0, 1.0);
    const int shininess = 8; // 0-128
    const int lightSpotExponent = 1;
    const float lightSpotCosCutoff = cos(45.0 / 180.0 * 3.1415926);

    const vec3 lightPosition = vec3(512.0, 256.0, 442.0);
    const vec3 eyePosition = vec3(512.0, 256.0, 442.0);

    #ifdef GL_ES
    precision lowp float;
    #endif

    varying vec4 v_position;
    varying vec4 v_color;
    varying vec2 v_texCoord;
    varying vec3 v_normal;
    varying float v_distance;
    varying vec3 v_lightDirection;
    varying vec3 v_spotlightDirection;

    void main() {
    vec4 color = v_color * texture2D(CC_Texture0, v_texCoord);
    color.a = 1.0;

    // vec3 lightDirection = lightPosition - v_position.xyz;
    vec3 n_spotDirection = normalize(lightPosition - vec3(512.0, 256.0, 0.0));
    vec3 n_spotlightDirection = normalize(v_spotlightDirection);
    // float distance = length(lightDirection);
    float atten = 1.0 / (lightAttenuationConst + lightAttenuationLinear * v_distance + lightAttenuationQuadratic * v_distance * v_distance);

    vec3 normal = v_normal;
    vec3 n_normal = normalize(normal);
    vec3 n_lightDirection = normalize(v_lightDirection);
    float cosNL = max(dot(n_normal, n_lightDirection), 0.0);
    vec4 diffuse = vec4(lightDiffuse * materialDiffuse, 1.0) * cosNL;

    vec4 ambient = vec4(lightAmbient * materialAmbient, 1.0);

    vec3 n_eyeDirection = normalize(eyePosition - v_position.xyz);
    vec3 reflection = 2 * max(dot(n_normal, n_lightDirection), 0.0) * n_normal - n_lightDirection;
    vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_eyeDirection, reflection), 0.0), shininess), 1.0);
    //vec3 reflection = normalize(n_eyeDirection + n_lightDirection);
    //vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_normal, reflection), 0.0), shininess), 1.0);

    float cosSpot = dot(-1 * n_spotDirection, -1 * n_spotlightDirection);
    if (cosSpot > lightSpotCosCutoff)
    {
    float spotEffect = pow(cosSpot, lightSpotExponent);
    atten += spotEffect;
    }
    float colorA = color.a;
    gl_FragColor = vec4(color.rgb * (ambient + diffuse + specular).xyz * atten, colorA);
    }
    ";

    效果:

  • 相关阅读:
    iOS 组件化方案
    iOS 核心动画概览
    iOS @字面量
    iOS id 和 instancetype 的区别
    C++ 中的 const
    iOS 开发资料
    iOS 架构-App组件化开发
    iOS 知名大牛的一些博客
    iOS 键盘 隐藏系统的 toolBar
    iOS UIView 单独设置一个角为圆角,两个 三个角也行
  • 原文地址:https://www.cnblogs.com/iRidescent-ZONE/p/5483400.html
Copyright © 2011-2022 走看看