赞
踩
使用 shader 绘制 五角星线段,mix 合并图层
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>五角星线段</title> <script src="../external/three.js"></script> <script src="../controls/OrbitControls.js"></script> <style> body { overflow: hidden; padding: 0; margin: 0; } </style> </head> <body> <div id="container"></div> <script id="vertexShader" type="x-shader/x-vertex"> varying vec2 pos; void main() { pos = (vec2(position) + 1.0) * 0.5; mat4 mvp = projectionMatrix * modelViewMatrix; gl_Position = mvp * vec4( position, 1.0 ); } </script> <script id="fragmentShader" type="x-shader/x-fragment"> uniform vec2 u_resolution; uniform float u_time; varying vec2 pos; vec4 _OutlineColor = vec4(1.0,1.0,1.0,1.0); vec4 _FrontColor = vec4(1.0,0.0,0.0,1.0); float pi=3.14159; float _Antialias=0.01; //画点 vec4 circle(vec2 pos, vec2 center, float radius, vec4 color) { //求点是否在圆的半径内 float d = length(pos - center) - radius; //fwidth(x) ==abs(ddx(x)) + abs(ddy(x)),对点求偏导,这种处理能让数据变平滑 float w = fwidth(0.5*d) * 2.0; //图层0 画圆外边框 vec4 layer0 = vec4(_OutlineColor.rgb, 1.0-smoothstep(-w, w, d - _Antialias)); //图层1 画内圆 vec4 layer1 = vec4(color.rgb, 1.0-smoothstep(0.0, w, d)); //混合两个图层并返回 return mix(layer0, layer1, layer1.a); // return layer0; } //画线 vec4 line(vec2 pos, vec2 point1, vec2 point2, float width) { //分别求出点二到点一以及当前点到点一的向量 vec2 dir0 = point2 - point1; vec2 dir1 = pos - point1; //dot()方法返回两个向量的点积 如果向量垂直返回0,平行返回1 相反返回-1 //clamp()方法限制返回0到1 截出线段,不然会返回直线 //这公式返回点到线上的距离 float h = clamp(dot(dir1, dir0)/dot(dir0, dir0), 0.0, 1.0); //判断点是否在线的两边范围内 float d = (length(dir1 - dir0 * h) - width * 0.5); //平滑处理 float w = fwidth(0.5*d) * 2.0; //画线的外边 vec4 layer0 = vec4(_OutlineColor.rgb, 1.-smoothstep(-w, w, d - _Antialias)); //画线 vec4 layer1 = vec4(_FrontColor.rgb, 1.-smoothstep(-w, w, d)); //混合两个图层 return mix(layer0, layer1, layer1.a); } //根据index来保存图层的颜色值 void setlayer(inout vec4 layer[5],int index,vec4 val){ if(index==0) layer[0]=val; if(index==1) layer[1]=val; if(index==2) layer[2]=val; if(index==3) layer[3]=val; if(index==4) layer[4]=val; } void main() { vec2 uv = pos * 3.0 - 1.5; //动态背景颜色 vec3 col = 0.5 + 0.5*cos(u_time+uv.xyx+vec3(0.0, 2.0, 4.0)); vec4 fragColor=vec4(col,1.0); //点的图层 vec4 layers[5]; float d=u_time*10.0; //保存五个点 从1开始 vec2 degree[6]; //for循环创建五个点 for(int i=0;i<=4;i++){ //保存点 //坐标上圆边上的点的坐标(cos(r),sin(r)) r为弧度 degree[i+1]=vec2(cos(d*pi/180.0),sin((d*pi)/180.0)); //绘制点 setlayer(layers, i, circle(uv, degree[i+1], 0.06, _FrontColor) ); //圆上的五角星,每个点相隔72度 d+=72.0; } //for循环画五条线 for(int i=1;i<6;i++){ vec2 point1=vec2(0.0,0.0); //判断连线的位置 即当前点的隔一个点 if(i<=2) { point1=degree[i+3]; } else { point1=degree[i-2]; } //画线 vec4 temp=line(uv,degree[i],point1,0.02); //混合线的图层 fragColor=mix(fragColor, temp, temp.a); } //混合点的图层 for (int i = 4; i >= 0; i--) { fragColor = mix(fragColor, layers[i], layers[i].a); } gl_FragColor = fragColor; } </script> <script> //https://blog.csdn.net/ssssssilver/article/details/81166233 var container; var camera, scene, renderer; var uniforms; init(); animate(); function init() { container = document.getElementById( 'container' ); camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); camera.position.set(0, 0, 2); scene = new THREE.Scene(); scene.add(new THREE.AxesHelper(20)); var geometry = new THREE.PlaneBufferGeometry( 2, 2 ); uniforms = { u_time: { type: "f", value: 1.0 }, u_resolution: { type: "v2", value: new THREE.Vector2(window.innerWidth, window.innerHeight) } }; var material = new THREE.ShaderMaterial( { uniforms: uniforms, side: THREE.DoubleSide, vertexShader: document.getElementById( 'vertexShader' ).textContent, fragmentShader: document.getElementById( 'fragmentShader' ).textContent } ); material.extensions.derivatives = true; var material2 = new THREE.MeshBasicMaterial({color: '#00bbbb', wireframe: true, side: THREE.DoubleSide}) var mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); renderer = new THREE.WebGLRenderer(); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setClearColor( '#f4f4f4', 1 ); container.appendChild( renderer.domElement ); let orbit = new THREE.OrbitControls( camera, renderer.domElement ); onWindowResize(); window.addEventListener( 'resize', onWindowResize, false ); } function onWindowResize( event ) { renderer.setSize( window.innerWidth, window.innerHeight ); // uniforms.u_resolution.value.x = renderer.domElement.width; // uniforms.u_resolution.value.y = renderer.domElement.height; } function animate() { requestAnimationFrame( animate ); render(); } function render() { uniforms.u_time.value += 0.02; renderer.render( scene, camera ); } </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>雨伞</title> <script src="../lib/three.js"></script> <script src="../lib/OrbitControls.js"></script> <style> body { overflow: hidden; padding: 0; margin: 0; } </style> </head> <body> <div id="container"></div> <script id="vertexShader" type="x-shader/x-vertex"> varying vec2 pos; void main() { pos = (vec2(position) + 1.0) * 0.5; mat4 mvp = projectionMatrix * modelViewMatrix; gl_Position = mvp * vec4( position, 1.0 ); } </script> <script id="fragmentShader" type="x-shader/x-fragment"> uniform vec2 u_resolution; uniform float u_time; varying vec2 pos; float sdfCircle(vec2 center, float radius, vec2 coord ) { vec2 offset = coord - center; return sqrt((offset.x * offset.x) + (offset.y * offset.y)) - radius; } float sdfEllipse(vec2 center, float a, float b, vec2 coord) { float a2 = a * a; float b2 = b * b; return (b2 * (coord.x - center.x) * (coord.x - center.x) + a2 * (coord.y - center.y) * (coord.y - center.y) - a2 * b2)/(a2 * b2); } float sdfLine(vec2 p0, vec2 p1, float width, vec2 coord) { vec2 dir0 = p1 - p0; vec2 dir1 = coord - p0; float h = clamp(dot(dir0, dir1)/dot(dir0, dir0), 0.0, 1.0); return (length(dir1 - dir0 * h) - width * 0.5); } float sdfUnion( const float a, const float b ) { return min(a, b); } float sdfDifference( const float a, const float b) { return max(a, -b); } float sdfIntersection( const float a, const float b ) { return max(a, b); } vec4 render(float d, vec3 color, float stroke) { //stroke = fwidth(d) * 2.0; float anti = fwidth(d) * 1.0; vec4 strokeLayer = vec4(vec3(0.05), 1.0-smoothstep(-anti, anti, d - stroke)); vec4 colorLayer = vec4(color, 1.0-smoothstep(-anti, anti, d)); if (stroke < 0.000001) { return colorLayer; } return vec4(mix(strokeLayer.rgb, colorLayer.rgb, colorLayer.a), strokeLayer.a); } void main() { float pixSize = 1.0 / 512.0; vec2 uv = pos; float stroke = pixSize * 1.5; vec2 center = vec2(0.5, 0.5 ); float a = sdfEllipse(vec2(0.5, center.y*2.0-0.34), 0.25, 0.25, uv); float b = sdfEllipse(vec2(0.5, center.y*2.0+0.03), 0.8, 0.35, uv); b = sdfIntersection(a, b); vec4 layer1 = render(b, vec3(0.32, 0.56, 0.53), fwidth(b) * 2.0); // Draw strips vec4 layer2 = layer1; float t, r0, r1, r2, e, f; vec2 sinuv = vec2(uv.x, (sin(uv.x*40.0)*0.02 + 1.0)*uv.y); for (float i = 0.0; i < 10.0; i++) { t = mod(3.14 + 0.3 * i, 3.0) * 0.2; r0 = (t - 0.15) / 0.2 * 0.9 + 0.1; r1 = (t - 0.15) / 0.2 * 0.1 + 0.9; r2 = (t - 0.15) / 0.2 * 0.15 + 0.85; e = sdfEllipse(vec2(0.5, center.y*2.0+0.37-t*r2), 0.7*r0, 0.35*r1, sinuv); f = sdfEllipse(vec2(0.5, center.y*2.0+0.41-t), 0.7*r0, 0.35*r1, sinuv); f = sdfDifference(e, f); f = sdfIntersection(f, b); vec4 layer = render(f, vec3(1.0, 0.81, 0.27), 0.0); layer2 = mix(layer2, layer, layer.a); } // Draw the handle float bottom = 0.08; float handleWidth = 0.01; float handleRadius = 0.04; float d = sdfCircle(vec2(0.5-handleRadius+0.5*handleWidth, bottom), handleRadius, uv); float c = sdfCircle(vec2(0.5-handleRadius+0.5*handleWidth, bottom), handleRadius-handleWidth, uv); d = sdfDifference(d, c); c = uv.y - bottom; d = sdfIntersection(d, c); c = sdfLine(vec2(0.5, center.y*2.0-0.05), vec2(0.5, bottom), handleWidth, uv); d = sdfUnion(d, c); c = sdfCircle(vec2(0.5, center.y*2.0-0.05), 0.01, uv); d = sdfUnion(c, d); c = sdfCircle(vec2(0.5-handleRadius*2.0+handleWidth, bottom), handleWidth*0.5, uv); d = sdfUnion(c, d); vec4 layer0 = render(d, vec3(0.404, 0.298, 0.278), stroke); vec2 p = 2.0*uv - 1.0; vec3 bcol = vec3(1.0,0.8,0.7-0.07*p.y)*(1.0-0.25*length(p)); vec4 fragColor = vec4(bcol, 1.0); fragColor.rgb = mix(fragColor.rgb, layer0.rgb, layer0.a); fragColor.rgb = mix(fragColor.rgb, layer1.rgb, layer1.a); fragColor.rgb = mix(fragColor.rgb, layer2.rgb, layer2.a); fragColor.rgb = pow(fragColor.rgb, vec3(1.0/2.2)); gl_FragColor = fragColor; } </script> <script> //https://blog.csdn.net/ssssssilver/article/details/81166233 var container; var camera, scene, renderer; var uniforms; init(); animate(); function init() { container = document.getElementById( 'container' ); camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); camera.position.set(0, 0, 2); scene = new THREE.Scene(); scene.add(new THREE.AxesHelper(20)); var geometry = new THREE.PlaneBufferGeometry( 2, 2 ); uniforms = { u_time: { type: "f", value: 1.0 }, u_resolution: { type: "v2", value: new THREE.Vector2(window.innerWidth, window.innerHeight) } }; var material = new THREE.ShaderMaterial( { uniforms: uniforms, side: THREE.DoubleSide, vertexShader: document.getElementById( 'vertexShader' ).textContent, fragmentShader: document.getElementById( 'fragmentShader' ).textContent } ); material.extensions.derivatives = true; var material2 = new THREE.MeshBasicMaterial({color: '#00bbbb', wireframe: true, side: THREE.DoubleSide}) var mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); renderer = new THREE.WebGLRenderer(); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setClearColor( '#f4f4f4', 1 ); container.appendChild( renderer.domElement ); let orbit = new THREE.OrbitControls( camera, renderer.domElement ); onWindowResize(); window.addEventListener( 'resize', onWindowResize, false ); } function onWindowResize( event ) { renderer.setSize( window.innerWidth, window.innerHeight ); // uniforms.u_resolution.value.x = renderer.domElement.width; // uniforms.u_resolution.value.y = renderer.domElement.height; } function animate() { requestAnimationFrame( animate ); render(); } function render() { uniforms.u_time.value += 0.02; renderer.render( scene, camera ); } </script> </body> </html>
https://sites.google.com/site/webglbook/
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。