c语言3d入门教程,WebGL入门教程四:借助 ? image3D绘制三维图形入门(一个简单的例子)...

本文介绍了如何通过npm安装并使用image3D辅助库进行WebGL绘图,包括着色器编写、3D对象创建、数据准备及绘制过程。重点讲解了顶点和片段着色器,以及如何通过attribute和varying修饰符传递数据。通过实例演示了如何设置点的位置、大小和颜色。
摘要由CSDN通过智能技术生成

作者:心叶

时间:2019-09-12 14:51

通过前面三篇文档的说明,大家应该基本了解了webgl的绘制方法,为了下一步更深入的学习,我们先来学习一下一个辅助库image3D,这个库主要是提供一些辅助方法。

引入image3D

通过npm方式管理,首先你需要通过命令行安装image3D,就像这样:

npm install --save image3d

安装好了以后,在需要的地方引入即可:

import image3D from 'image3d';

const image3D = require("image3d");

首先,我们不得不说明一下绘图的基本流程:编辑着色器→创建3D对象→准备好数据→绘制

我们接下来准备绘制一个点,点的颜色、大小和位置不停改变。

着色器

绘图的时候,本质上我们都是需要通过着色器来和GPU进行数据交互,因此,需要传递的数据都需要在这里提前定义好,看看本例子的着色器:

attribute vec4 a_position;

attribute float a_size;

attribute vec4 a_color;

varying vec4 v_color;

void main(){

gl_Position=a_position;

gl_PointSize=a_size;

v_color=a_color;

}

varying vec4 v_color;

void main(){

gl_FragColor=v_color;

}

着色器分二类:顶点着色器和片段着色器,前者用于传递点的位置和大小,后者用于传递点的颜色。

本质上来讲,着色器其实就是二个字符串,用script标签包裹是为了在html文本中方便编辑,在后面的过程就可以看出来了。

着色器的代码有点像C语言,我们目前需要了解这三点:

gl开头的有三个,分别对应点的位置、大小和颜色(从上到下),这是着色器内置的变量,分别隶属于二个着色器,我们所谓的传值,从这个层次看,就是最终给这三个变量赋值。

然后再看看attribute修饰的三个变量,被这个修饰符修饰的变量等于暴露了一个入口,image3D提供了传值的方法,所谓的传值,也就是通过这个入口实现的(第二个修饰符,vec4和float是变量的数据类型,类似别的语言)。

前一条说的入口由attribute修饰实现,是针对每个点提供的,片段着色器是针对全部的点,因此attribute不可以直接出现在第二类着色器中,我们需要使用varying修饰符来标记一个桥梁,实现二个着色器之间的数据传递。

3D对象

着色器准备好了以后,我们就可以使用这二个着色器创建3D对象了,同样的,看看本例中的代码:

var image3d = new image3D(

document.getElementsByTagName('canvas')[0], {

// 传递着色器

"vertex-shader":

document.getElementById("vs").innerText,

"fragment-shader":

document.getElementById("fs").innerText

});

从这里是不是可以看出来,着色器只不过是二段字符串。

传递数据

实际的例子是不停的改变,我们为了方便说明,这里假设某个瞬间的操作:

image3d

// 设置点的位置

.setAttributeFloat("a_position", 0.5, 0.5, 0.0)

// 设置点的大小

.setAttributeFloat("a_size", 50.0)

// 设置点的颜色

.setAttributeFloat("a_color", 1.0, 0.0, 0.0);

比如点的位置,“a_position”是和着色器中attribute修饰的变量对应的。大部分根据感觉应该就可以看出来,下面稍微提二点:

image3D选择的是右手坐标系,记作uvz(对应数学中的坐标系就是xyz),每个轴的有效可视范围是-1.0~1.0,因此这里的坐标(0.5, 0.5, 0.0)页面上看上去就是位于第一象限中心(右上角),请注意和浏览器的坐标区分。

点的颜色需要传递三个值,范围是0.0~1.0,分别对应RGB(当然还可以有一个alpha透明度,这里没有传递)。

绘制

一切准备完毕,获取画笔绘制即可:

image3d.Painter().drawPoint(0, 1);

这里缩减版的例子最终会绘制一个大小是50px,位于第一象限中心的红色正方形。完整的例子请点击此处查看运行效果。

后记

你可以试着修改第二个例子中点的坐标试试。这篇文章主要是要入门借助image3D绘图的流程,是不是很容易。例子中涉及的方法和一些细节我们后面再说明。有任何疑惑可以留言提问。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
三维图c语言编写,可以缩放图形。 /* Note:Your choice is C IDE */ #include "stdio.h" #include "graphics.h" #include "math.h" void hua(int T[8][3]) { moveto(T[0][0]/T[0][2],T[0][1]/T[0][2]); lineto(T[1][0]/T[1][2],T[1][1]/T[1][2]); lineto(T[2][0]/T[2][2],T[2][1]/T[2][2]); lineto(T[3][0]/T[3][2],T[3][1]/T[3][2]); lineto(T[0][0]/T[0][2],T[0][1]/T[0][2]); moveto(T[4][0]/T[4][2],T[4][1]/T[4][2]); lineto(T[5][0]/T[5][2],T[5][1]/T[5][2]); lineto(T[6][0]/T[6][2],T[6][1]/T[6][2]); lineto(T[7][0]/T[7][2],T[7][1]/T[7][2]); lineto(T[4][0]/T[4][2],T[4][1]/T[4][2]); moveto(T[0][0]/T[0][2],T[0][1]/T[0][2]); lineto(T[4][0]/T[4][2],T[4][1]/T[4][2]); moveto(T[1][0]/T[1][2],T[1][1]/T[1][2]); lineto(T[5][0]/T[5][2],T[5][1]/T[5][2]); moveto(T[2][0]/T[2][2],T[2][1]/T[2][2]); lineto(T[6][0]/T[6][2],T[6][1]/T[6][2]); moveto(T[3][0]/T[3][2],T[3][1]/T[3][2]); lineto(T[7][0]/T[7][2],T[7][1]/T[7][2]); } /*/////////////////////////////////////////////////////////////////////////*/ void x(int T[8][3],float af) { int i; float theta =0.00017* af; for(i=0;i<8;i++) { T[i][0]=T[i][0]; T[i][1]=T[i][0]*0+T[i][1]*cos(theta)+T[i][2]*(-sin(theta)); T[i][2]=T[i][0]*0+T[i][1]*sin(theta)+T[i][2]*cos(theta); } hua(T); } /*//////////////////////////////////////////////////////////////////////*/ void y(int T[8][3],float af) { int i; float theta =0.00017* af; for(i=0;i<8;i++) { T[i][0]=T[i][0]*cos(theta)+T[i][2]*sin(theta); T[i][1]=T[i][1]; T[i][2]=T[i][0]*(-sin(theta))+T[i][2]*cos(theta); } hua(T); } /*/////////////////////////////////////////////////////////////////////////*/ void z(int T[8][3],float af) { int i; float theta =0.00017* af; for(i=0;i<8;i++) { T[i][0]=T[i][0]*cos(theta)+T[i][1]*(-sin(theta)); T[i][1]=T[i][1]*sin(theta)+T[i][1]*cos(theta); T[i][2]=T[i][2]; } hua(T); } /*//////////////////////////////////////////////////////////////*/ void projection(int T[8][3],float af,float af1) { int i; float theta =0.017* af; float theta1 =0.017* af1; for(i=0;i<8;i++) { T[i][0]=T[i][0]*cos(theta)+T[i][1]*(-sin(theta)); T[i][1]=0; T[i][2]=T[i][0]*(-sin(theta)*sin(theta1))+T[i][1]*(-cos(theta)*sin(theta1))+T[i][2]*cos(theta1); } hua(T); } /*////////////////////////////////////////////////////////////////////*/ void perspective(int T[8][4],float af,float af1,float q) { int i; float theta =0.017* af; float theta1 =0.017* af1; for(i=0;i<8;i++) { T[i][0]=T[i][0]*cos(theta)+T[i][1]*(-sin(theta)); T[i][1]=0; T[i][2]=T[i][0]*(-sin(theta)*sin(theta1))+T[i][1]*(-cos(theta)*sin(theta1))+T[i][2]*cos(theta1); T[i][3]=T[i][0]*q*sin(theta)*cos(theta1)+T[i][1]*q*cos(theta)*cos(theta1)+T[i][2]*q*sin(theta1)+T[i][3]; } hua(T); } /*//////////////////////////////////////////////////////////////////////*/ void Zperspective(int T[8][3]) { int i; for(i=0;i<8;i++) { T[i][0]=T[i][0]*0.707+T[i][1]*(-0.707); T[i][1]=0; T[i][2]=T[i][0]*(-0.408)+T[i][1]*(-0.408)+T[i][2]*(0.816); } hua(T); } /*==============================================================================================================*/ main() { int gdriver=DETECT,gmode; int T[8][3]={530,390,1,500,420,1,560,420,1,590,390,1,530,450,1,500,480,1,560,480,1,590,450,1}; int TT[8][3]={80,50,1,50,80,1,110,80,1,140,50,1,80,110,50,140,110,140,140,110,80,110,1}; float af,af1,q; initgraph(&gdriver,&gmode,""); cleardevice(); setbkcolor(9);setcolor(4); hua(T); printf("input af:"); scanf("%f",&af); x(T,af); /*****************************/ printf("input af:"); scanf("%f",&af); x(T,af); /*****************************/ printf("input af:"); scanf("%f",&af); x(T,af); /*****************************/ printf("input af:"); scanf("%f",&af); y(T,af); /*****************************/ printf("input af:"); scanf("%f",&af); z(T,af); /*****************************/ /* printf("input af,af1:"); scanf("%f%f",&af,&af1); projection(T,af,af1); printf("input af,af1,q:"); scanf("%f%f%f",&af,&af1,&q); perspective(T,af,af1,q); Zperspective(T); */ getch(); closegraph(); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值