1. 程式人生 > >純GLSL分步實現電影般畫面的湖光山色<Step1>: 豔陽藍天(WebGL實現)

純GLSL分步實現電影般畫面的湖光山色<Step1>: 豔陽藍天(WebGL實現)

在實時渲染領域,呈現一個絢麗的畫面除了藝術美術的功力之外,還需要大部分的技術支援: 數理幾何原理和渲染技術。

GLSL(OpenGL的Shader語言,用於對GPU渲染過程實現程式設計控制)就是這些技藝和呈現之間的橋樑。

一個稍微複雜的畫面,用純GLSL實現,除了要熟悉這個語法以及對應的GPU功能之外還需要熟悉數理原理和一些技巧,所以包含的內容比較多。

湖光山色是一個富有詩意的畫面,在ShaderToy上看到大神的一個作品: https://www.shadertoy.com/view/MsB3WR, 畫面很美

現在,就分若干步驟,一步一步分解開來,由簡入繁,單獨拆解幾個重要的技術點,以實現對大神技藝的臨摹和分享

因為是重寫,加了自己的想法,程式碼和畫面效果都和原來有出入。

Step1,豔陽和藍天。效果如下:

Demo: http://www.artvily.com/sdf?sample=column&clip=lakeMountain/skyAndSun

GLSL原始碼:

// Write by Vily.
precision highp float;
// u_param.xy: (stageWidth,stageHeight), u_param.z>1.0: mouse_down,u_param.z<1.0: mouse_up
uniform vec4 u_param;
// u_mouse.x: mouse x offset from mouseDown position x,
// u_mouse.y: mouse y offset from mouseDown position y,
// u_mouse.z: mouse x accumulation from mouseDown position x,
// u_mouse.w: mouse y accumulation from mouseDown position y
uniform vec4 u_mouse;

mat2 rotY(const in float a) {
	return mat2(cos(a),sin(a),-sin(a),cos(a));	
}
// light direction
vec3 lightDirection = normalize(vec3( 0.3,0.7, 0.6));
// create the sky and a sun
vec3 createSkyAndSun( const in vec3 ray ) {
	float sunDensity = clamp( dot(lightDirection, ray), 0.0, 1.0 );
	// sky color
	vec3 color = vec3(0.2,0.4,0.6) - ray.y*0.3*vec3(0.1,0.5,1.0) + 0.13;
	// sun and sun's halo
	color += vec3(0.8,.7,0.2)*pow( sunDensity, 16.0 ) * 0.4 + vec3(1.0,.7,0.2)*pow( sunDensity, 32.0 ) * 0.6;
	color *= 0.95;
	return color;
}
// create a matrix33 of camera space to world space
mat3 viewMatrix3(vec3 eye, vec3 center, vec3 up) {
    vec3 f = normalize(center - eye);
    vec3 s = normalize(cross(f, up));
    vec3 u = cross(s, f);
    return mat3(s, u, -f);
}
void main()
{
    vec2 q = gl_FragCoord.xy / u_param.xy;
    q = -1.0 + 2.0*q;
    q.x *= u_param.x/ u_param.y;
	//
    float inTime = u_param.z * 2.0;
	vec3 lookAtCenter = vec3(0.0, 0.0, 0.0);
	vec3 eye = vec3(0.0, 3.5,3.0);
	//
	//if(u_param.z > 1.0) inTime += 0.1 * u_mouse.x;
	inTime += 0.1 * u_mouse.z;
	//
	vec3 ray = normalize(vec3(q.x,q.y,2.5));
	eye.xz *= rotY( mod(inTime * 0.03, 6.2831852) );
    ray = viewMatrix3(eye, lookAtCenter, vec3(0.0,1.0,0.0)) * ray;
	//
	vec3 col = createSkyAndSun( ray );
	//
    gl_FragColor = vec4( col * vec3(1.0,1.0,1.4), 1.0 );
}

在以上原始碼上,已有相應的註釋。

這個GLSL,我所需Geometry的只是由兩個三角形構成的矩形,這個矩形鋪滿整個視口。不需要紋理。需要的輸入引數由uniform指定。以上程式碼中 uniform vec4 u_param,存放了四個值,x,y對應的是視口對應的額螢幕裝置寬和高,z是一個由0開始每一幀累加0.1的float值, 暫時w沒用到,值為0.0

以上Demo中所用的引擎是我自己的渲染系統, 比較完整,支援webgl1和webgl2, 如果有需要可以直接在瀏覽器的資源中下載得到。而且這部分程式碼是按c++原來的方式寫的,所以歸類很清晰。

下一篇:https://blog.csdn.net/vily_lei/article/details/83180765