canvas坐标系统 webgl坐标系统 uv纹理坐标系统 原点

本文介绍了Web开发中Canvas、WebGL和UV坐标系的区别,包括Canvas的左上角原点,x轴向右y轴向下;WebGL的中心原点,x轴向右y轴向上,数据范围[-1,1];以及UV坐标系统的左下角原点,同样x轴向右y轴向上,数据范围同样为[-1,1]。

一、canvas、屏幕坐标:原点在左上角,x轴正方向向右,y轴正方向向下,一个点对应一个像素

二、webgl、屏幕归一化坐标(NDC)原点在正中间,x轴正方向向右,y轴正方向向上。

注意:NDC数据显示范围在[-1,1]之间,超过此范围不显示数据

三、uv原点在左下角,x轴正方向向右,y轴正方向向上,数据范围在[-1,1]之间

uv坐标不直接表示纹理的像素位置,而是一个比例关系,例如u=0.5,v=0.5 表示纹理的正中心

四:纹理空间:单位是像素,而不是比例,原点在左下角

<think>我们有一个顶点着色器代码,它使用WebGL来渲染图形。这个着色器有几个关键部分:1.精度声明:`precisionmediumpfloat;`设置浮点数精度为中等精度。2.属性变量:`attributevec2xy;`表示每个顶点特有的属性,这里是顶点的二维坐标。3.统一变量:`uniformvec2scale;`和`uniformvec2translate;`是所有顶点共用的,用于缩放和平移顶点坐标。4.可变变量:`varyinghighpvec2uv;`用于将数据传递给片元着色器,这里传递的是纹理坐标。5.main函数:是着色器的入口点。在main函数中:-首先对顶点坐标进行变换:`scaledPosition=xy*scale+translate;`这里对原始顶点坐标进行缩放和平移。-然后设置顶点位置:`gl_Position=vec4(scaledPosition,0.0,1.0);`因为是在二维中,z设为0.0,w设为1.0。-接着计算纹理坐标:`uv=vec2((1.0+xy.x)/2.0,(1.0-xy.y)/2.0);`将xy坐标从[-1,1]映射到[0,1]的纹理坐标空间。注意:纹理坐标原点通常在左上角,但WebGL纹理坐标原点在左下角。这里通过`(1.0-xy.y)/2.0`将y坐标翻转,使得原点在左上角。但是,这里有一个潜在问题:我们传入的顶点坐标xy的范围可能是[-1,1](在归一化设备坐标中),然后通过这个变换将xy映射到[0,1]作为纹理坐标。然而,在WebGL中,通常我们使用顶点缓冲区来传递顶点属性。下面我们给出一个完整的示例,展示如何编译着色器、设置顶点数据、设置uniform以及绘制。由于问题中只给出了顶点着色器,我们还需要一个片元着色器来完成渲染。假设我们要渲染一个纹理,片元着色器可能是这样的:```glslprecisionmediumpfloat;varyinghighpvec2uv;uniformsampler2Dtexture;voidmain(void){gl_FragColor=texture2D(texture,uv);}```接下来,我们将展示如何使用WebGLAPI来设置和渲染。注意:由于WebGL的API较为冗长,我们将分步骤解释。步骤:1.获取WebGL上下文。2.编译着色器程序(包括顶点着色器和片元着色器)。3.设置顶点数据。4.设置uniform变量。5.绘制。我们将编写一个函数来初始化着色器程序,然后设置顶点数据。这里我们绘制一个覆盖整个画布的矩形(两个三角形)。由于顶点着色器中的`xy`属性范围是[-1,1],我们可以直接使用两个三角形组成一个矩形(四个顶点)。顶点数据:-四个顶点:(-1,-1),(1,-1),(-1,1),(1,1)-索引数据:0,1,2,2,1,3或者用两个三角形带。但是,我们也可以使用一个包含四个顶点的数组,然后使用`gl.TRIANGLE_STRIP`模式绘制,这样只需要4个顶点。我们使用两个三角形(6个顶点)的方式,但这里为了简单,我们使用三角形带(4个顶点)。下面我们给出完整的代码示例。注意:这个示例假设我们有一个canvas元素,并且我们要在它上面绘制一个纹理纹理的加载我们这里不展示,我们使用一个单色纹理代替。由于代码较长,我们将逐步分解。</think>### 顶点着色器代码解析 这个顶点着色器用于在 WebGL 中处理顶点位置和纹理坐标的计算。下面是逐行解析: ```glsl precision mediump float; // 指定浮点数精度 ``` - 设置所有浮点类型变量的默认精度为中等精度 (`mediump`),适用于移动设备和大多数场景 ```glsl attribute vec2 xy; // 输入的顶点坐标 ``` - `attribute`:顶点属性,每个顶点独有的数据 - `vec2 xy`:二维向量,表示顶点的原始位置(通常范围在 -1.0 到 1.0 之间) ```glsl uniform vec2 scale; // 缩放因子 uniform vec2 translate; // 平移向量 ``` - `uniform`:全局变量,所有顶点共享的值 - `scale`:控制顶点坐标的缩放比例 - `translate`:控制顶点坐标的平移偏移 ```glsl varying highp vec2 uv; // 输出到片元着色器的纹理坐标 ``` - `varying`:顶点着色器输出,片元着色器输入的插值变量 - `highp`:指定高精度,确保纹理坐标计算准确 - `uv`:计算后的纹理坐标(范围 0.0 到 1.0) ```glsl void main(void) { // 应用缩放和平移变换 vec2 scaledPosition = xy * scale + translate; // 设置顶点位置 (z=0.0, w=1.0 表示2D平面) gl_Position = vec4(scaledPosition, 0.0, 1.0); // 将NDC坐标(-1到1)转换为纹理坐标(0到1) // 同时翻转Y轴匹配纹理坐标uv = vec2((1.0 + xy.x) / 2.0, (1.0 - xy.y) / 2.0); } ``` ### 关键计算解释: 1. **顶点位置变换**: ```glsl vec2 scaledPosition = xy * scale + translate; ``` - 线性变换:`原始坐标 × 缩放 + 平移` - 示例:若 `scale=(0.5,0.5)`, `translate=(0.2,-0.1)`,则顶点 (1,1) 变为 (1×0.5+0.2, 1×0.5-0.1)=(0.7,0.4) 2. **纹理坐标生成**: ```glsl uv = vec2((1.0 + xy.x) / 2.0, (1.0 - xy.y) / 2.0); ``` - X转换:`(1 + x)/2` 将 [-1,1] 映射到 [0,1] - Y转换:`(1 - y)/2` 将 [-1,1] 翻转后映射到 [0,1](解决WebGL纹理Y轴方向问题) ### 完整使用示例 以下是使用该着色器绘制纹理四边形的基本WebGL代码: ```html <canvas id="glCanvas"></canvas> <script> const canvas = document.getElementById('glCanvas'); const gl = canvas.getContext('webgl'); // 顶点着色器源码(即问题中的代码) const vsSource = ` precision mediump float; attribute vec2 xy; uniform vec2 scale; uniform vec2 translate; varying highp vec2 uv; void main(void) { vec2 scaledPosition = xy * scale + translate; gl_Position = vec4(scaledPosition, 0.0, 1.0); uv = vec2((1.0 + xy.x) / 2.0, (1.0 - xy.y) / 2.0); } `; // 片元着色器(示例) const fsSource = ` precision mediump float; varying highp vec2 uv; uniform sampler2D uSampler; void main() { gl_FragColor = texture2D(uSampler, uv); } `; // 创建着色器程序 const program = initShaderProgram(gl, vsSource, fsSource); // 定义四边形顶点(两个三角形) const vertices = new Float32Array([ -1, -1, // 左下 1, -1, // 右下 -1, 1, // 左上 1, 1 // 右上 ]); // 创建顶点缓冲区 const vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); // 获取属性位置 const xyLocation = gl.getAttribLocation(program, 'xy'); gl.enableVertexAttribArray(xyLocation); gl.vertexAttribPointer(xyLocation, 2, gl.FLOAT, false, 0, 0); // 获取uniform位置 const scaleLocation = gl.getUniformLocation(program, 'scale'); const translateLocation = gl.getUniformLocation(program, 'translate'); // 设置变换参数(示例值) gl.uniform2f(scaleLocation, 0.8, 0.8); // 缩放80% gl.uniform2f(translateLocation, 0.1, -0.1); // 向右上平移 // 渲染 gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); // 初始化着色器的辅助函数 function initShaderProgram(gl, vsSource, fsSource) { // ... 标准WebGL着色器初始化流程 ... } </script> ``` ### 实际应用场景 1. **2D图像处理**:缩放/平移图像 2. **纹理映射**:将纹理精确映射到几何体 3. **UI渲染**:控制界面元素的位置和大小 4. **动态效果**:通过改变uniform实现动画
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值