純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