一次失败尝试:-(码绘写实眼睛

2023-11-23 18:40

本文主要是介绍一次失败尝试:-(码绘写实眼睛,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一次失败尝试:-(码绘写实眼睛

这是互动媒体第一次作业,要求手绘一幅静态画,然后再用代码将静态画实现。将两幅用不同形式画出来的画进行对比,得出一定结论。
这里我手绘作品所用工具:数位板,码绘使用p5.js

绘画第一步:观察

手绘准备

每一个美术生,上课的第一件事不是让你练排线,而是让你去观察临摹本的线条为什么要这么排,这个物体的结构为什么要这么画,这幅画面的透视,这些画的明暗交界线在哪……就拿一幅结构素描举例——
图源网络,非原创(图源网络,非原创)
试想一下,假如我们要画的就是这样一幅画,我们应该从什么地方入手?
如果是我的话,我会先把这些物体的大概范围,位置确定好,比如:罐子中线以上,右中大苹果,后面藏着西红柿,左前高脚杯,最下大梨子……
接下来是透视,明显俯视角度,所以越在下面的物体,透视越大。在结构素描中具体表现为切面从下到上变形程度递增。
再接下来就是明暗交界线划分以及排线(这两部分跟本文没啥太多联系就不细说了)

以上是手绘的观察,那么代码跟它比起来,需要准备些什么呢?

码绘准备

首先你得有一张画布。
其次你需要确定你画的画中心点在哪里(这一点可以和手绘的位置确定对应起来)
然后是根据客观的物理存在抽象出一定的数学逻辑。比如说之前提到的透视,物理逻辑是——小俯视,越往上透视越大。那么在数学逻辑里,你可以抽象成一条线段和一个位移变量y,y越小(在p5中画布中y值从上到下递增)线段越短……当然你也可以抽象成圆的半径,旋转角度等等。总之,你需要根据现实的物理世界创建一个代码的逻辑世界。
最后才是动手写代码……

绘画进行中:基本元素

手绘

说到传统画画,其实就是点线面的组合。
还是回到上面的结构素描,你可以发现,这一幅画几乎就是用线条构成的!什么罐子结构线是弧,瞎扯,其实都是线段连接而成的!手绘到这里就没话说了,排线吧,顺着纹理来,排到最后画也就出来了。

码绘

码绘选择的基本元素其实挺多,点线基本几何体都可以成为你的基本元素,你需要做的就是根据规则把这些基本元素正确排放……

课程作业实践

当时p5还不是很熟练,只是大概清楚了一些基本的点线基本图形,所以根据实际情况,我选择了只有黑白灰变化的素描……话不多说,先放一张自己板绘的一张眼睛——
当时画完这只眼睛,我就想着码绘大概就稳了,毕竟它的组成元素大部分都是曲线,甚至眼球都可以用圆形加以概括,然后我代码画出来的眼睛是下面这样的:-(
在这里插入图片描述丑的惨不忍睹……
是我高估了自己对贝塞尔曲线的掌握程度,每次画出来的曲线都要调整很久才能勉强达到自己对这幅画的需求。
下面附上没有技术含量的完整代码……

function setup() {createCanvas(600,400);
}function draw() { background(150);stroke(10);fill(120,90,20);strokeWeight(8);ellipse(300, 250, 80, 80);fill(50,20,20);ellipse(300, 250, 50, 50);strokeWeight(1);fill(200,200,200);ellipse(280, 240, 20, 15);createeye();createmeis(8,-20);}function createmeis(x,y)
{createmei1(-20+x,12+y);createmei1(-12+x,9+y);createmei1(-3+x,6+y);createmei1(-3+x,5+y);createmei1(10+x,0+y);createmei1(20+x,-5+y);createmei1(30+x,-5+y);createmei1(40+x,-5+y);createmei1(50+x,-6+y);createmei1(60+x,-10+y);createmei1(65+x,-10+y);createmei1(70+x,-12+y);createmei1(80+x,-15+y);createmei2(85+x,-15+y);createmei2(95+x,-15+y);createmei2(90+x,-15+y);createmei2(105+x,-15+y);createmei2(110+x,-17+y);createmei2(120+x,-20+y);createmei3(140+x,-17+y);createmei3(150+x,-1+y);createmei3(130+x,-7+y);createmei3(140+x,-5+y);createmei4(162+x,-10+y);createmei4(175+x,-8+y);createmei4(180+x,-3+y);createmei4(190+x,0+y);
}function createmei1(x,y)
{beginShape();strokeWeight(4);curveVertex(180+x,190+y);curveVertex(180+x,200+y);curveVertex(190+x,180+y);curveVertex(200+x,165+y);curveVertex(220+x,150+y);curveVertex(220+x,150-y);endShape();}
function createmei2(x,y)
{beginShape();strokeWeight(4);curveVertex(180+x,210+y);curveVertex(180+x,200+y);curveVertex(190+x,180+y);curveVertex(210+x,160+y);curveVertex(230+x,150+y);curveVertex(230+x,150+y);endShape();
}
function createmei3(x,y)
{beginShape();strokeWeight(4);curveVertex(180+x,210+y);curveVertex(180+x,180+y);curveVertex(200+x,165+y);curveVertex(220+x,160+y);curveVertex(250+x,160+y);curveVertex(270+x,160+y);endShape();
}
function createmei4(x,y)
{beginShape();strokeWeight(3);curveVertex(160+x,200+y);curveVertex(170+x,180+y);curveVertex(200+x,175+y);curveVertex(220+x,175+y);curveVertex(250+x,185+y);curveVertex(270+x,205+y);endShape();
}function createeye()
{noFill();strokeWeight(4);//下眼皮beginShape();curveVertex(320,250);curveVertex(210,271);curveVertex(320,300);curveVertex(300,300);endShape();beginShape();curveVertex(3,250);curveVertex(210,268);curveVertex(320,300);curveVertex(500,300);endShape();beginShape();curveVertex(300,290);curveVertex(300,290);curveVertex(310,295);curveVertex(350,285);curveVertex(390,250);curveVertex(400,170);endShape();beginShape();curveVertex(300,290);curveVertex(300,290);curveVertex(310,295);curveVertex(350,295);curveVertex(400,260);curveVertex(400,190);endShape();beginShape();strokeWeight(2);curveVertex(210,290);curveVertex(210,280);curveVertex(290,320);curveVertex(350,320);curveVertex(380,300);endShape();//上眼皮beginShape();strokeWeight(10);curveVertex(320,230);curveVertex(200,275);curveVertex(310,205);curveVertex(500,300);endShape();beginShape();curveVertex(320,235);curveVertex(200,275);curveVertex(310,210);curveVertex(500,305);endShape();beginShape();curveVertex(320,233);curveVertex(200,273);curveVertex(310,207);curveVertex(500,303);endShape();beginShape();strokeWeight(5);curveVertex(200,260);curveVertex(200,260);curveVertex(240,220);curveVertex(290,190);curveVertex(340,195);curveVertex(380,210);curveVertex(400,220);curveVertex(410,220);endShape();beginShape();strokeWeight(9);curveVertex(300,200);curveVertex(315,206);curveVertex(400,250);curveVertex(440,340);endShape();beginShape();strokeWeight(9);curveVertex(0,170);curveVertex(315,206);curveVertex(415,260);curveVertex(490,340);endShape();}

代码没有啥技术含量,值得一提的是画眉毛的时候用了一个自己写的函数:

function createmei1(x,y)
{beginShape();strokeWeight(4);curveVertex(180+x,190+y);curveVertex(180+x,200+y);curveVertex(190+x,180+y);curveVertex(200+x,165+y);curveVertex(220+x,150+y);curveVertex(220+x,150-y);endShape();
}

现在看看当时自己写代码的方式真的很愚钝,可以说是为了画而去凑代码,凑坐标。其实可以根据实际情况确定一个中心点,再由这个中心点进行扩展,这样会比较方便灵活。

这篇关于一次失败尝试:-(码绘写实眼睛的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/419948

相关文章

pip install jupyterlab失败的原因问题及探索

《pipinstalljupyterlab失败的原因问题及探索》在学习Yolo模型时,尝试安装JupyterLab但遇到错误,错误提示缺少Rust和Cargo编译环境,因为pywinpty包需要它... 目录背景问题解决方案总结背景最近在学习Yolo模型,然后其中要下载jupyter(有点LSVmu像一个

Python判断for循环最后一次的6种方法

《Python判断for循环最后一次的6种方法》在Python中,通常我们不会直接判断for循环是否正在执行最后一次迭代,因为Python的for循环是基于可迭代对象的,它不知道也不关心迭代的内部状态... 目录1.使用enuhttp://www.chinasem.cnmerate()和len()来判断for

Xshell远程连接失败以及解决方案

《Xshell远程连接失败以及解决方案》本文介绍了在Windows11家庭版和CentOS系统中解决Xshell无法连接远程服务器问题的步骤,在Windows11家庭版中,需要通过设置添加SSH功能并... 目录一.问题描述二.原因分析及解决办法2.1添加ssh功能2.2 在Windows中开启ssh服务2

Redis连接失败:客户端IP不在白名单中的问题分析与解决方案

《Redis连接失败:客户端IP不在白名单中的问题分析与解决方案》在现代分布式系统中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、消息队列、会话存储等场景,然而,在实际使用过程中,我们可能... 目录一、问题背景二、错误分析1. 错误信息解读2. 根本原因三、解决方案1. 将客户端IP添加到Re

电脑多久清理一次灰尘合? 合理清理电脑上灰尘的科普文

《电脑多久清理一次灰尘合?合理清理电脑上灰尘的科普文》聊起电脑清理灰尘这个话题,我可有不少话要说,你知道吗,电脑就像个勤劳的工人,每天不停地为我们服务,但时间一长,它也会“出汗”——也就是积累灰尘,... 灰尘的堆积几乎是所有电脑用户面临的问题。无论你的房间有多干净,或者你的电脑是否安装了灰尘过滤器,灰尘都

ORACLE 11g 创建数据库时 Enterprise Manager配置失败的解决办法 无法打开OEM的解决办法

在win7 64位系统下安装oracle11g,在使用Database configuration Assistant创建数据库时,在创建到85%的时候报错,错误如下: 解决办法: 在listener.ora中增加对BlueAeri-PC或ip地址的侦听,具体步骤如下: 1.启动Net Manager,在“监听程序”--Listener下添加一个地址,主机名写计

STM32 ADC+DMA导致写FLASH失败

最近用STM32G070系列的ADC+DMA采样时,遇到了一些小坑记录一下; 一、ADC+DMA采样时进入死循环; 解决方法:ADC-dma死循环问题_stm32 adc dma死机-CSDN博客 将ADC的DMA中断调整为最高,且增大ADCHAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_Buffer_Size); 的ADC_Bu

(function() {})();只执行一次

测试例子: var xx = (function() {     (function() { alert(9) })(); alert(10)     return "yyyy";  })(); 调用: alert(xx); 在调用的时候,你会发现只弹出"yyyy"信息,并不见弹出"10"的信息!这也就是说,这个匿名函数只在立即调用的时候执行一次,这时它已经赋予了给xx变量,也就是只是

flume系列之:记录一次flume agent进程被异常oom kill -9的原因定位

flume系列之:记录一次flume agent进程被异常oom kill -9的原因定位 一、背景二、定位问题三、解决方法 一、背景 flume系列之:定位flume没有关闭某个时间点生成的tmp文件的原因,并制定解决方案在博主上面这篇文章的基础上,在机器内存、cpu资源、flume agent资源都足够的情况下,flume agent又出现了tmp文件无法关闭的情况 二、

jmeter之仅一次控制器

仅一次控制器作用: 不管线程组设置多少次循环,它下面的组件都只会执行一次 Tips:很多情况下需要登录才能访问其他接口,比如:商品列表、添加商品到购物车、购物车列表等,在多场景下,登录只需要1次,我们期望的是重复执行登陆后面的接口来做压测,这就和事务相关,例如 事务1: 登录—>添加购物车 事务2: 登录—>购物车列表 事务3: 登录—>商品列表—>添加购物车 … 一、仅一次控制器案例 在