-
2019-04-23 16:07:54
在three.js中已经为我们封装好了这一效果,我们只需要引入特定的包就可以使用;
引入三个js包,它们相互关联,缺一不可,否则会报错,可在工程文件夹下example文件夹找到
<script type="text/javascript" src="js/objects/Water2.js" ></script>//水的主要模型包 <script type="text/javascript" src="js/objects/Reflector.js" ></script>//实现水的反射效果 <script type="text/javascript" src="js/objects/Refractor.js" ></script>//实现水的折射效果
构造函数:
new THREE.Water(geometry,options)
-geometry:object,图形(一般使用平面PlaneGeometry图形)
-options:objects,
可选参数(颜色color,水波大小scale,流动方向flowDirection,画布宽度textureWidth,画布高度 textureHeight,流线图贴图flowMap等)
{-
color:new THREE.Color(),
-
scale:number,
-
flowDirection:new THREE.Vector2(x,y),//二维方向向量
-
textureWidth:2的次方倍,
-
textureHeight:2的次方倍,
-
flowMap:map//流线贴图,
…
}
注意,flowDiretion和flowMap两个属性不能连用,会起冲突;
有些朋友问shapeGeometry可以不?我的回答是可以,但是更推荐使用threejs内置的geometry,使用自定义形状是有效果的,但是不太明显,因为shapeGeomtry本身顶点过于复杂,Water包·运算较慢,水流效果较缓,尤其是浅色的,几乎看不到效果
示例代码:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>测试water的属性</title> <script type="text/javascript" src="js/three.js" ></script> <script type="text/javascript" src="js/libs/stats.min.js" ></script> <script type="text/javascript" src="js/WebGL.js" ></script> <script type="text/javascript" src="js/libs/dat.gui.min.js" ></script> <script type="text/javascript" src="js/controls/OrbitControls.js" ></script> <script type="text/javascript" src="js/objects/Water2.js" ></script> <script type="text/javascript" src="js/objects/Reflector.js" ></script> <script type="text/javascript" src="js/objects/Refractor.js" ></script> <style> body{ padding:0; margin: 0; overflow: hidden; } </style> </head> <body> <script> if(WEBGL.isWebGLAvailable()===false){alert("该浏览器不支持WebGL!");document.body.appendChild(WEBGL.getWebGLErrorMessage());} var scene,renderer,camera,controls,stats; var cubeTexture=new THREE.CubeTextureLoader().setPath("img/skybox1/").load([ 'px.jpg','nx.jpg', 'py.jpg','ny.jpg', 'pz.jpg','nz.jpg' ]);//天空盒子 function init(){ scene=new THREE.Scene(); scene.background=cubeTexture; renderer=new THREE.WebGLRenderer({ antialias:true }); renderer.setSize(window.innerWidth,window.innerHeight); renderer.setPixelRatio(window.devicePixelRatio); document.body.appendChild(renderer.domElement); camera=new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,0.1,1000); camera.position.set(0,30,0); camera.lookAt(scene.position); controls=new THREE.OrbitControls(camera,renderer.domElement); controls.enableDamping=true; controls.minDistance=0.1; controls.maxDistance=1000; stats=new Stats(); document.body.appendChild(stats.dom); scene.add(new THREE.AmbientLight(0x404040)); var dLight=new THREE.DirectionalLight(0xffffff,0.8); dLight.position.set(-1,1,1); scene.add(dLight); } var axes;var torusKnot; var water1;var water2;var helper; function initModel(){ axes=new THREE.AxesHelper(10); scene.add(axes); axes.visible=false; var geometry=new THREE.PlaneBufferGeometry(20,20,1); //平面1 var plane=new THREE.Mesh(geometry,new THREE.MeshStandardMaterial({ side:THREE.DoubleSide, roughness:0.8, metalness:0.4 })); plane.position.set(-12,0,0); plane.rotation.x=-0.5*Math.PI; scene.add(plane); new THREE.TextureLoader().load("textures/hardwood2_diffuse.jpg",function(map){ map.wrapS=map.wrapT=THREE.RepeatWrapping; map.anisotropy=16; map.repeat.set(4,4); plane.material.map=map; plane.material.needsUpdate=true; }); torusKnot=new THREE.Mesh(new THREE.TorusKnotBufferGeometry(3,1,256,32),new THREE.MeshNormalMaterial()); torusKnot.scale.set(0.5,0.5,0.5); torusKnot.position.set(-12,4,0); scene.add(torusKnot); //水1 water1=new THREE.Water(geometry,{ color:'#ffffff', scale:2, flowDirection:new THREE.Vector2(1,1), textureWidth:1024, textureHeight:1024, }); water1.rotation.x=-0.5*Math.PI; water1.position.set(-12,1,0); scene.add(water1); //平面二 var texture=new THREE.TextureLoader().load('textures/FloorsCheckerboard_S_Diffuse.jpg',function(map){ map.wrapS=map.wrapT=THREE.RepeatWrapping; map.anisotropy=16; map.repeat.set(4,4); }); var ground=new THREE.Mesh(geometry,new THREE.MeshBasicMaterial({ color:0xcccccc, map:texture })); ground.position.set(12,0,0); ground.rotation.x=-Math.PI/2; scene.add(ground); //水2 var flowMap=new THREE.TextureLoader().load('textures/water/Water_1_M_Flow.jpg'); water2=new THREE.Water(geometry,{ scale:2, textureWidth:1024, textureHeiht:1024, flowMap:flowMap }); water2.rotation.x=-Math.PI/2; water2.position.set(12,1,0); scene.add(water2); //贴图原图显示 helper=new THREE.Mesh(geometry,new THREE.MeshBasicMaterial({ map:flowMap })); helper.position.set(12,1.05,0); helper.rotation.x=-Math.PI/2; scene.add(helper); helper.visible=false; } var setting; function initGui(){ setting={ axesVisible:false, color:"#ffffff", scale:2, flowX:1, flowY:1, helper:false, } var gui=new dat.GUI(); gui.add(setting,"axesVisible").onChange(function(e){ axes.visible=e; }); //水的属性设置 var waterProperty=gui.addFolder("water1"); waterProperty.addColor(setting,"color").onChange(function(e){ water1.material.uniforms['color'].value.set(e); }); waterProperty.add(setting,"scale",1,10).onChange(function(e){ water1.material.uniforms['config'].value.w=e; }); waterProperty.add(setting,"flowX",-1,1).onChange(function(e){ water1.material.uniforms['flowDirection'].value.x=e; water1.material.uniforms['flowDirection'].value.normalize();//归一化 }); waterProperty.add(setting,"flowY",-1,1).onChange(function(e){ water1.material.uniforms['flowDirection'].value.y=e; water1.material.uniforms['flowDirection'].value.normalize(); }); waterProperty.open(); var waterPro2=gui.addFolder("water2"); waterPro2.add(setting,"helper").name("show flowMap").onChange(function(e){ helper.visible=e; }); waterPro2.addColor(setting,"color").onChange(function(e){ water2.material.uniforms['color'].value.set(e); }); waterPro2.add(setting,"scale",1,10).onChange(function(e){ water2.material.uniforms['config'].value.w=e; }); waterPro2.open(); } function onWindowResize(){ camera.aspect=window.innerWidth/window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth,window.innerHeight); } var clock=new THREE.Clock(); function render(){ var delta=clock.getDelta(); torusKnot.rotation.x+=delta; torusKnot.rotation.y+=delta*0.5; renderer.render(scene,camera); } function animate(){ render(); controls.update(); stats.update(); window.onresize=onWindowResize(); requestAnimationFrame(animate); } function threeStart(){ init(); initModel(); initGui(); animate(); } threeStart(); </script> </body> </html>
更多相关内容 -
-
水彩画水的奥秘.pdf
2020-07-15 20:56:57水彩画水的奥秘 水彩画艺术的本体语言,除了一般绘画形式共有的点、线、面、 色、形体等各种可视的基本元素外,它还拥有透明、水韵、彩味、笔 意、诗境等独特的艺术内涵和形式魅力。这完全是因为水彩画的工具、 ... -
水墨中国风传统水画PPT模板.ppt
2021-09-29 21:33:23水墨中国风传统水画PPT模板.ppt -
康熙字典八画属水的汉字 康熙字典9画属水的字.docx
2022-01-12 15:08:42康熙字典八画属水的汉字 康熙字典9画属水的字.docx -
矿泉水瓶的三维画 素材
2013-12-03 10:30:59inventor2012上画的矿泉水瓶希望大家共同努力 -
红黄蓝水彩线条画风格艺术PPT模板.pptx
2019-09-25 16:33:27红黄蓝水彩线条画风格艺术PPT模板.pptx,PPT的封面是蓝色的线条水笔画,其余标题是一个大圆点,颜色有蓝色、红色。内容部分,PPT的背景也是以这种水彩线条的图案为主。PPT的主要颜色是红黄蓝。PPT的内容大致由七个... -
康熙字典11画属水的字-康熙字典15画属金的字.docx
2022-01-02 02:29:16康熙字典11画属水的字-康熙字典15画属金的字.docx -
康熙笔划15画五行属水字-康熙五行属水16画字.docx
2022-01-02 02:29:42康熙笔划15画五行属水字-康熙五行属水16画字.docx -
二年级美术上册《洒水成画》教学设计2 湘教版
2021-08-19 16:24:52二年级美术上册《洒水成画》教学设计2 湘教版 -
二年级美术上册《洒水成画》教学设计1 湘教版
2021-08-19 14:58:26二年级美术上册《洒水成画》教学设计1 湘教版 -
二年级美术上册《洒水成画》教学简案 湘教版
2021-08-19 14:46:45二年级美术上册《洒水成画》教学简案 湘教版 -
Python-程序生成的中国山水画
2019-08-10 04:07:42程序生成的中国山水画 -
动漫人物头发怎么画出水彩效果?水彩头发怎么画出层次感
2020-09-10 19:17:42今天小编就在网络上收集整理了关于动漫人物头发怎么画出水彩效果?水彩头发怎么画出层次感教程,教程非常简单,赶紧来看看叭: 重点是通过将不透明的颜色应用于头发的纹理来表达潮湿和性感的氛围。有几大步骤,但是...动漫人物头发怎么画出水彩效果?怎样才能画出水彩头发层次感?想画把头发画出水彩效果的教程有哪些?想必这些问题都是初学者比较伤脑筋的问题,那么初学者到底怎样才能把头发画出水彩效果呢?今天小编就在网络上收集整理了关于动漫人物头发怎么画出水彩效果?水彩头发怎么画出层次感教程,教程非常简单,赶紧来看看叭:
重点是通过将不透明的颜色应用于头发的纹理来表达潮湿和性感的氛围。有几大步骤,但是请与我们在一起直到最后。
1、使头发变色
我打算用浅蓝色的黑发来修饰头发,所以我使用了淡紫色(浅紫色浅蓝色),水蓝色(淡黄绿色)和淡紫色(浅紫色)作为发色的基础。
效果不大,因为颜色是从上到下依次层叠的,但是我觉得,当层叠几种基色时,整体印象会很自然。
2、使头发顺畅
我将使用Davis Gray绘制头发的流动。大概不用画太多。
3、呈现清晰的手绘纹理
在阴影的最暗部分周围绘制头发流并将其添加。这样,粗颗粒可以使屏幕具有鲜明而独特的笔迹气氛。
4、熟悉整体氛围
如果您的头发稍浅一点,则可以将黄色或壳粉红色混合。
5、赋予头发三维外观
可能很难看到,因为它不是很暗,但是我用薰衣草画了卷发和帽子的阴影。
6、画头发
到目前为止的头发流动情况,耐心地将其像光泽一样。我个人最喜欢这个过程。
7、再增加整体氛围
当我用锐化笔画头发时,整个头发都变黑了,与眼睛相比,在某种意义上来说很明显
8、赋予头发三维外观
再次用薰衣草涂抹以强调引擎盖和卷发的阴影。添加蓝色调也是有意义的
9、强调头发的流动
由于靛蓝和棕褐色的混合,请在阴影最暗的部分周围绘制。
此时,
·不要通过微妙地改变每次融化油漆的密度来保持单调
·如果在发梢的卷曲部分上画得太多,则屏幕会太吵,所以请停在头发的中间
10、增加整体氛围
但是这次,我没有以模糊的方式应用它,而是将其分散在整个头发上,而不是将其散布在整个头发上。
这是反复多次,直到整体的质地完成。
11、完成
最后用锐利画笔描绘头发就完成了!!
绘制的重点:
①通过多次分层肤色,赋予质地“苗条”和“温暖”的效果
②画头发就像种头发
③通过创建要绘制的区域和不应该绘制的区域来给人留下深刻的印象
以上内容就是小编为大家从网络上收集整理分享的优质教程嘞,主要就是教大家怎么把头发画出水彩效果以及层次感的教程!教程超级实用,相信这个教程一定会对大家有所帮助,赶紧收藏练习吧~
如果你对我们的自学计划感兴趣的话
欢迎来加入我们的免费公益绘画交流社区群:978622391
在那里,我们会有很多的绘画教程以及素材参考资源
还有定期的免费直播课程哦
每天老师在线指导你的绘画技法
助你开启绘画提升之门
大家在群里,可以畅所欲言
在轻松的交流中享受绘画的乐趣! -
三种画线算法(DDA,Bresenham,Midpoint).rar
2019-10-20 12:07:07DDA、Bresenham、中点画线算法的C++实现,使用graphics.h图形库(下载EasyX插件就可以用很方便:) 实现了【各种斜率和方向】!的绘制 -
从《瓶水斋诗集》看舒位的画学造诣与画坛交游
2020-04-30 04:41:27舒位是活跃于乾嘉诗坛的一位颇有盛名的...尽管舒位留存下来的画作极少,但其《瓶水斋诗集》中收录了大量论画、题画诗,通过分析这些诗歌所反映出的绘画理论,并结合其与当朝画坛名流的交游情况,可以大致了解他的画学成就。 -
水厂制作的wincc画面
2019-11-09 14:01:18供水制作的wincc画面,包括两个蓄水池,六个水井! -
行业文档-设计装置-三维立体画塑料复合材料书法水写文具.zip
2021-09-08 12:15:06行业文档-设计装置-三维立体画塑料复合材料书法水写文具 -
宗炳画论:山水画美学的先驱与典范
2020-06-20 04:50:20宗炳是中国早期山水画家之杰出代表,也是中国山水画美学之先驱,他最早将"受佛家思想浸泡的老庄道家思想"贯彻到山水画创作和山水画论中去,他的《画山水序》不仅是中国最早的山水画论,更是中国山水画美学的典范之作,对... -
QT 带有动画的 圆形进度条 水波进度条
2019-07-29 18:18:23通过设置画刷 QBrush 来设置未占用的的背景色: painter->setBrush(QBrush(m_bgColor)); 这样就完成了第一步,背景的绘制: void WaterProcess::drawBg(QPainter *painter) { int width = this->width(); int ...我们在使用其他软件的时候,经常能看到各种绚丽的进度条,其中带有水波波纹的进度条就是其中一个。对于PC端软件开发使用的QT,只是提供了process bar,样式十分单一。 所以这次我们就使用QT的paint 以及定时器来实现类似的水波进度条。
先看一下最终效果图:
这个是怎样实现的呢? 我们仍然是在一个QWidget上的paintEvent上重绘实现图形绘制 + QTimer 实现动画效果。
首先,我们是在一个QWidget 上进行绘制,绘制是在paintEvent 里面进行开始绘制。水波动画是使用QTimer 定时器进行定时触,重绘控件,造成水波波动的动画。
我们照例来分解一下整个实现过程: 圆形背景(边框+背景) + 水波进度 + 进度数值。
第一步,我们先绘制圆形的背景,这个背景包含边框,以及未被占有的背景。这个背景是一个圆形,我们使用 drawEllipse函数:
void QPainter::drawEllipse(const QRectF &rectangle)
其中我们通过设置 画笔QPen 的宽度来实现 边框:
QPen pen;
pen.setColor(borderColor);
pen.setWidthF(borderWidth);
pen.setJoinStyle(Qt::RoundJoin);
painter->setPen(pen);通过设置画刷 QBrush 来设置未占用的的背景色:
painter->setBrush(QBrush(m_bgColor));
这样就完成了第一步,背景的绘制:
void WaterProcess::drawBg(QPainter *painter) { int width = this->width(); int height = this->height(); int side = qMin(width, height) - m_borderWidth; int startX = (width - side) * 0.5; int startY = (height - side) * 0.5; painter->save(); painter->setBrush(QBrush(m_bgColor)); if (m_borderWidth == 0) { painter->setPen(Qt::NoPen); } else { QBrush brush(m_borderColor); painter->setPen(QPen(brush, m_borderWidth, Qt::SolidLine)); } painter->drawEllipse(startX, startY, side, side); painter->restore(); }
我们来看看效果:
第二步,是需要绘制水波,这也是至关重要的一步。我们使用设定的颜色使用QPainterPath来设定,其中最重要的有两个,第一个就是QPainterPath 的一个intersected(求相交、挖除)功能。
QPainterPath QPainterPath::intersected(const QPainterPath &p) const
这个功能是返回两个路径相交(重合)的部分。我们来分析一下为什么使用这个求相交的功能。
因为我们要实现水波,所以我们需要使用我们以前学过的正弦sin 或者余弦cos 函数,进行模拟水波。正弦曲线公式 y = A * qSin(ωx + φ) + k
- A : 表示振幅, 我们可以用作水波的高度。
- w : 表示周期,可以理解为水波密度,W越大,表示水波越密集。
- k : 标识Y轴偏移量,可以理解为进度,取值是进度百分比
我们可以设置两个透明度不同、起始位置有偏差的两条正弦曲线相互交错,形成波浪的起伏,更具有真实性。
我们的大路径 totalPainterPath,是整个圆形。上面用到的正弦公式模拟的水波。我们就要使用到了上面提到的intersected相交函数,来去除额外不需要显示的部分。void WaterProcess::drawProcess(QPainter *painter) { int width = this->width(); int height = this->height(); int side = qMin(width, height) - (2 * m_borderWidth); //直径 int startX = (width - side) * 0.5; int startY = (height - side) *0.5; int endX = startX + side; int endY = startY + side; double percent = (m_value * 1.0) / (m_maxValue - m_minValue); double w = 2 * M_PI / endX; double A = endY * m_waterHeight; double k = endY * (1.0 - percent); painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(m_usedColor); QPainterPath totalPath; //加入圆形路径 totalPath.addEllipse(startX, startY, side, side); //水波路径 QPainterPath water1; QPainterPath water2; water1.moveTo(startX, endY); water2.moveTo(startX, endY); m_offset += 0.6; if (m_offset > (endX / 2)) { m_offset = 0; } for(int i = startX; i < endX; i++) { //第一条波浪Y轴 double waterY1 = (double)(A * qSin(w * i + m_offset)) + k; //第二条波浪Y轴 double waterY2; waterY2 = (double)(A * qSin(w * i + m_offset + (endX / 2 * w))) + k; water1.lineTo(i, waterY1); water2.lineTo(i, waterY2); if (m_value == m_minValue) { waterY1 = endY; } if (m_value == m_maxValue) { waterY1 = startY; } } //封闭 water1.lineTo(endX, endY); water2.lineTo(endX, endY); QPainterPath path; QColor waterColor1 = m_usedColor; waterColor1.setAlpha(100); QColor waterColor2 = m_usedColor; waterColor2.setAlpha(200); //第一条波浪 path = totalPath.intersected(water1); painter->setBrush(waterColor1); painter->drawPath(path); //第二条波浪挖去后的路径 path = totalPath.intersected(water2); painter->setBrush(waterColor2); painter->drawPath(path); painter->restore(); }
这个时候我们看一下效果图:
这时候就已经完成了大部分功能,不过很重要的是没有显示进度百分比。第三步就是 完成文字百分比的显示了,我们使用drawText函数进行函数绘制。
void QPainter::drawText(const QPointF &position, const QString &text)
这个就比较简单了,只需要算出来百分比就可以了,其实上一步我们已经完成了对百分比的算法了
void WaterProcess::drawValue(QPainter *painter) { painter->save(); int width = this->width(); int height = this->height(); int side = qMin(width, height) - m_borderWidth; int startX = (width - side) * 0.5; int startY = (height - side) * 0.5; int fontSize = side / 3; QFont font; font.setFamily("微软雅黑"); font.setPixelSize(fontSize); font.setBold(true); painter->setFont(font); painter->setPen(Qt::white); painter->drawText(QRectF(startX, startY, side, side), Qt::AlignCenter, QString("%1%").arg(m_value)); painter->restore(); }
到这里我们就完成了所有动作的绘制,只需要在paintEvent函数里进行调用了
void WaterProcess::paintEvent(QPaintEvent *ev) { Q_UNUSED(ev) QPainter painter(this); painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); //背景 drawBg(&painter); //进度、水波 drawProcess(&painter); //进度数字 drawValue(&painter); }
在初始化的时候启动定时器就好了!
写在最后,例子已经上传到csdn了,没有积分的小伙伴,评论留下你的邮箱,看到后会立刻发出。
demo下载地址
没有积分支持的小伙伴,也可以访问、下载git代码,欢迎加星,会持续更新:https://github.com/xiezhongyuan/waterProcess
-
利用Python画随机水墨图
2018-08-28 16:26:00最近公司的事情忙的一逼,前段时间学的python再不看看等于又还回去了 上次再老婆大人的创意下,做了一个觉得比较好玩的图片出来.没错,就是用python来作图! 效果图 ...其实就是采用了python中的一个随机漫步的小方法...最近公司的事情忙的一逼,前段时间学的python再不看看等于又还回去了
上次再老婆大人的创意下,做了一个觉得比较好玩的图片出来.没错,就是用python来作图!
效果图
效果图
原理解释
其实就是采用了python中的一个随机漫步的小方法作图
话不多说,直接上代码吧,毕竟要下班咯,老婆叫我回家买鸡蛋呢.
代码
我有一个微信公众号,经常会分享一些python技术相关的干货;如果你喜欢我的分享,可以用微信搜索“python语言学习”
关注,欢迎大家加入千人交流答疑裙:699+749+852 -
python设计宇智波止水别天神
2020-07-07 16:24:24python设计的宇智波止水别天神 采用python pygame设计 可与鼠标交互旋转加速 -
王希卓妙用“水法”提高儿童水墨画创作能力的实践的设计研究作能力的实践的设计研究.doc
2021-10-10 01:50:11王希卓妙用“水法”提高儿童水墨画创作能力的实践的设计研究作能力的实践的设计研究.doc -
水化学分析软件
2014-11-22 17:21:47可以利用其做主要离子分析,确定水体的水化学类型。并进行水化学方面的分析。 -
用processing制作整齐排列的圆圈呈水波状动画效果
2020-04-07 09:43:37运行结果 代码部分 void setup(){ size(600,600); radius = 0.5*width/float(num_side+1); } int num_side = 10; float t = 0.0; float dt = 0.01; float x,y,osc,radius; float rateRatio=0.75;... t = t... -
js+css动画实现动态流水线条效果
2018-09-25 17:35:25需求让实现每个模块之间的线动态流水化,用canvas肯定很复杂,所有用了比较投机的方法,css动画加js控制 <!DOCTYPE html> <html> <head&...script type=&q -
苹果x漫画脸_【漫画大全】:漫画韩国全集
2020-10-21 21:50:59免费漫画大全|免费漫画公众号|免费漫画全集|漫画免费看|漫画免费大全|漫画恋爱大全|漫画免费看公众号|漫画韩国|...演山艺水拍话档4.人的生最过李渡前点5.人没鬼成结左界6.最中爱呃你为的她那啊十零年7.重里... -
OpenGL.ES在Android上的简单实践:23-水印录制(FBO离屏渲染,解决透明冲突,画中画)
2018-06-12 11:05:45(鼓掌散花) 3、创建FBO 既然我们已经认识了什么是FBO,接下来我们就认识认识关于FBO的OpenGL.API 和其他VAO,VBO,IBO一样,通过调用Gen****,创建FBO,代码如下: final int frameBuffers[] = new int[1];... -
android人脸检测并画框demo
2018-05-03 12:55:181. 人脸检测。 2. 自定义图片质量参数,包括最小识别人脸,光亮度,模糊度等。 3.自定义画人脸框,可以替换成任意图片。 -
「推荐」手机、平板绘画党福利!10个非常好用的绘画App赶紧试试
2021-06-09 04:35:52想必这些都是绘画初学者们经常在想的问题吧,就是不知道如何才能学好绘画,在手机或者平板上绘画出自己喜欢的东西那么今天老师就在网络上收集整理了一些关于如何学习绘画的教程给大家,10个非常好用的绘画App赶紧... -
学画漫画的APP有哪些?2018动漫绘画学习软件推荐
2020-12-30 16:43:56相信很多伙伴都和小编一样,喜欢动漫人物,看到别人画的漫画很漂亮,是不是也想动手试试?然而一直都画得不好?大家不要急,这里小编给大家推荐6款好用的学习画漫画的APP,大家可以慢慢学习,相信你也能画出栩栩如生...