存档

2018年1月 的存档

OpenGL(十五)雾效 的 shader 实现

2018年1月29日 没有评论

雾效 可以表现出一个线性的颜色变化,常用于烘托场景气氛。这种效果的实现原理并不复杂,本文着重讨论如何通过shader编写完成雾效的实现。

核心原理

雾效 的核心在于:计算视点与物体之间的距离,然后根据一个衰减公式进行颜色混合。常规的算法有线性衰减,指数衰减,指数幂衰减。

线性雾效

使用线性差值衰减,即可达到这种 雾效 。示意图如下:

OpenGL(十五)雾效 的 shader 实现

对应shader如下:

//vs
varying vec3 V_Normal;
varying vec3 V_WorldPos;
varying vec4 V_EyeSpacePos;
void main()
{
    V_Normal=mat3(NM)*normal;
    vec4 worldPos=M*vec4(pos,1.0);
    V_WorldPos=worldPos.xyz;
    //将物体换算到视口坐标系
    V_EyeSpacePos=V*worldPos;
    gl_Position=P*V*worldPos;
}
//fs
uniform float U_FogStart;
uniform float U_FogEnd;
uniform vec4 U_FogColor;
varying vec3 V_Normal;
varying vec3 V_WorldPos;
varying vec4 V_EyeSpacePos;
float LinearFog(float distance)
{
    float fogAlpha=(distance-U_FogStart)/(U_FogEnd-U_FogStart);
    fogAlpha=clamp(fogAlpha,0.0,1.0);
    return fogAlpha;
}
void main()
{
    //color calculate
    ...
    //
    float fogAlpha = LinearFog(abs(V_EyeSpacePos.z/V_EyeSpacePos.w));
    gl_FragColor=mix(color,U_FogColor,fogAlpha);
}

指数雾效

指数雾效与上面的shader大体相同,唯一要更改的是衰减算法。添加一个density参数来控制曲线的弧度。

//fs
uniform vec4 U_Density;
float ExpFog(float distance)
{
    float fogAlpha=exp(-distance * U_Density);
    fogAlpha=1.0-clamp(fogAlpha,0.0,1.0);
    return fogAlpha;
}

指数幂雾效

通过Gradiant可以控制雾效的衰减速度。

//fs
uniform vec4 U_Density;
uniform vec4 U_Gradiant;
float ExpFog(float distance)
{
    float fogAlpha=exp(-pow(distance * U_Density,UGradiant));
    fogAlpha=1.0-clamp(fogAlpha,0.0,1.0);
    return fogAlpha;
}

总结

本文通过三种shader实现,介绍了如何制作 雾效 来烘托氛围效果。

分类: 未分类 标签:

OpenGL(十五)雾效 的 shader 实现

2018年1月29日 没有评论

雾效 可以表现出一个线性的颜色变化,常用于烘托场景气氛。这种效果的实现原理并不复杂,本文着重讨论如何通过shader编写完成雾效的实现。

核心原理

雾效 的核心在于:计算视点与物体之间的距离,然后根据一个衰减公式进行颜色混合。常规的算法有线性衰减,指数衰减,指数幂衰减。

线性雾效

使用线性差值衰减,即可达到这种 雾效 。示意图如下:

OpenGL(十五)雾效 的 shader 实现

对应shader如下:

//vs
varying vec3 V_Normal;
varying vec3 V_WorldPos;
varying vec4 V_EyeSpacePos;
void main()
{
    V_Normal=mat3(NM)*normal;
    vec4 worldPos=M*vec4(pos,1.0);
    V_WorldPos=worldPos.xyz;
    //将物体换算到视口坐标系
    V_EyeSpacePos=V*worldPos;
    gl_Position=P*V*worldPos;
}
//fs
uniform float U_FogStart;
uniform float U_FogEnd;
uniform vec4 U_FogColor;
varying vec3 V_Normal;
varying vec3 V_WorldPos;
varying vec4 V_EyeSpacePos;
float LinearFog(float distance)
{
    float fogAlpha=(distance-U_FogStart)/(U_FogEnd-U_FogStart);
    fogAlpha=clamp(fogAlpha,0.0,1.0);
    return fogAlpha;
}
void main()
{
    //color calculate
    ...
    //
    float fogAlpha = LinearFog(abs(V_EyeSpacePos.z/V_EyeSpacePos.w));
    gl_FragColor=mix(color,U_FogColor,fogAlpha);
}

指数雾效

指数雾效与上面的shader大体相同,唯一要更改的是衰减算法。添加一个density参数来控制曲线的弧度。

//fs
uniform vec4 U_Density;
float ExpFog(float distance)
{
    float fogAlpha=exp(-distance * U_Density);
    fogAlpha=1.0-clamp(fogAlpha,0.0,1.0);
    return fogAlpha;
}

指数幂雾效

通过Gradiant可以控制雾效的衰减速度。

//fs
uniform vec4 U_Density;
uniform vec4 U_Gradiant;
float ExpFog(float distance)
{
    float fogAlpha=exp(-pow(distance * U_Density,UGradiant));
    fogAlpha=1.0-clamp(fogAlpha,0.0,1.0);
    return fogAlpha;
}

总结

本文通过三种shader实现,介绍了如何制作 雾效 来烘托氛围效果。

分类: 未分类 标签:

OpenGL(十四)环境反射 环境折射 的shader实现

2018年1月22日 没有评论

在上一节我们讲解了如何制作天空盒,本篇文章介绍它的一个衍生功能——在物体上叠加 环境反射 。

核心原理

核心很简单,在天空盒中,视线照射到天空盒上的区域即需要绘制的部分。在环境反射中,需要绘制的区域变成了视线在物体表面的反射光线,反射光线照射到天空盒的位置即要绘制的部分。

环境反射

按照上面的说法,将法线方向传入shader中,具体编写如下:

//vs
attribute vec3 pos;
attribute vec2 texcoord;
attribute vec3 normal;
uniform mat4 M;
uniform mat4 P;
uniform mat4 V;
uniform mat4 NM;
varying vec4 V_WorldPos;
varying vec3 V_Normal;
void main()
{
    V_WorldPos=M*vec4(pos,1.0);
    V_Normal=mat3(NM)*normal;
    gl_Position=P*V*M*vec4(pos,1.0);
}
//fs
varying vec4 V_WorldPos;
varying vec3 V_Normal;
uniform samplerCube U_MainTexture;
void main()
{
    vec3 eyeVec=normalize(V_WorldPos.xyz-vec3(0.0));
    vec3 n=normalize(V_Normal);
    vec3 r=reflect(eyeVec,n);
    vec4 color=textureCube(U_MainTexture,r);
    gl_FragColor=color;
}

环境折射

环境折射实现原理与环境反射相同,只不过在计算射出光线时使用折射函数:

//fs
varying vec4 V_WorldPos;
varying vec3 V_Normal;
uniform samplerCube U_MainTexture;
void main()
{
    vec3 eyeVec=normalize(V_WorldPos.xyz-vec3(0.0));
    vec3 n=normalize(V_Normal);
    vec3 r=refract(eyeVec,n,1.0/2.4);
    vec4 color=textureCube(U_MainTexture,r);
    gl_FragColor=color;
}

总结

借助天空盒,可以很方便的实现环境反射和环境折射的效果。其中折射率有对照表,可以通过搜索引擎查到。

OpenGL(十四)环境反射 环境折射 的shader实现

转载请注明出处:http://blog.csdn.net/fansongy/article/details/79128108

分类: 未分类 标签:

OpenGL(十四)环境反射 环境折射 的shader实现

2018年1月22日 没有评论

在上一节我们讲解了如何制作天空盒,本篇文章介绍它的一个衍生功能——在物体上叠加 环境反射 。

核心原理

核心很简单,在天空盒中,视线照射到天空盒上的区域即需要绘制的部分。在环境反射中,需要绘制的区域变成了视线在物体表面的反射光线,反射光线照射到天空盒的位置即要绘制的部分。

环境反射

按照上面的说法,将法线方向传入shader中,具体编写如下:

//vs
attribute vec3 pos;
attribute vec2 texcoord;
attribute vec3 normal;
uniform mat4 M;
uniform mat4 P;
uniform mat4 V;
uniform mat4 NM;
varying vec4 V_WorldPos;
varying vec3 V_Normal;
void main()
{
    V_WorldPos=M*vec4(pos,1.0);
    V_Normal=mat3(NM)*normal;
    gl_Position=P*V*M*vec4(pos,1.0);
}
//fs
varying vec4 V_WorldPos;
varying vec3 V_Normal;
uniform samplerCube U_MainTexture;
void main()
{
    vec3 eyeVec=normalize(V_WorldPos.xyz-vec3(0.0));
    vec3 n=normalize(V_Normal);
    vec3 r=reflect(eyeVec,n);
    vec4 color=textureCube(U_MainTexture,r);
    gl_FragColor=color;
}

环境折射

环境折射实现原理与环境反射相同,只不过在计算射出光线时使用折射函数:

//fs
varying vec4 V_WorldPos;
varying vec3 V_Normal;
uniform samplerCube U_MainTexture;
void main()
{
    vec3 eyeVec=normalize(V_WorldPos.xyz-vec3(0.0));
    vec3 n=normalize(V_Normal);
    vec3 r=refract(eyeVec,n,1.0/2.4);
    vec4 color=textureCube(U_MainTexture,r);
    gl_FragColor=color;
}

总结

借助天空盒,可以很方便的实现环境反射和环境折射的效果。其中折射率有对照表,可以通过搜索引擎查到。

OpenGL(十四)环境反射 环境折射 的shader实现

转载请注明出处:http://blog.csdn.net/fansongy/article/details/79128108

分类: 未分类 标签: