webgl中uniform、varying、attribute的差别

uniform 表示一次渲染过程中保存不变的,GPU的工作模式是多管道的,相当于一个像素点对应着一个管道,
    当然并不是说有这么多管道,只是表示他是一一对应并且一起处理;那么把整个屏幕处理时uniform       是持不变的

 

attribute 表示是实时在改变的,比如通常我们用了存放顶点,和颜色

varying 用来着色器之间的通讯,也就是顶点着色器和片段着色去之间的桥梁;比如你要传一个顶点颜色,你需要在两个着色

器里声明一个变量,然后你把颜色传入到顶点着色器中,并在main()函数里赋值,这才能把赋值给你声明的varying vec4 color

但是他们并不是一个变量;如下:

<script id="vs" type="x-shader/x-vertex"> attribute vec3 position; attribute vec4 color; uniform mat4 mvpMatrix; varying vec4 vColor; void main(void){ vColor = color; gl_Position = mvpMatrix * vec4(position,1.0); } </script> <script id="fs" type="x-shader/x-fragment"> precision mediump float; varying vec4 vColor; void main(void){ gl_FragColor = vColor; } </script> </head>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的用 WebGL 实现地球自转的 Demo: 首先,需要在 HTML 文件创建一个 canvas 元素: ```html <canvas id="myCanvas" width="800" height="600"></canvas> ``` 然后,在 JavaScript 文件获取 canvas 元素,并创建 WebGL 上下文: ```javascript const canvas = document.getElementById('myCanvas'); const gl = canvas.getContext('webgl'); ``` 接下来,需要编写着色器代码。这里我们需要两个着色器,一个用于顶点着色,一个用于片元着色。着色器代码如下: ```glsl // 顶点着色器代码 attribute vec3 aPosition; attribute vec2 aTexCoord; uniform mat4 uModelViewMatrix; uniform mat4 uProjectionMatrix; varying vec2 vTexCoord; void main() { gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aPosition, 1.0); vTexCoord = aTexCoord; } // 片元着色器代码 precision mediump float; uniform sampler2D uSampler; varying vec2 vTexCoord; void main() { gl_FragColor = texture2D(uSampler, vTexCoord); } ``` 接着,创建着色器程序,并将着色器代码编译链接: ```javascript // 顶点着色器代码 const vertexShaderSource = ` attribute vec3 aPosition; attribute vec2 aTexCoord; uniform mat4 uModelViewMatrix; uniform mat4 uProjectionMatrix; varying vec2 vTexCoord; void main() { gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aPosition, 1.0); vTexCoord = aTexCoord; } `; // 片元着色器代码 const fragmentShaderSource = ` precision mediump float; uniform sampler2D uSampler; varying vec2 vTexCoord; void main() { gl_FragColor = texture2D(uSampler, vTexCoord); } `; // 创建着色器程序 const shaderProgram = gl.createProgram(); // 编译链接顶点着色器 const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vertexShaderSource); gl.compileShader(vertexShader); gl.attachShader(shaderProgram, vertexShader); // 编译链接片元着色器 const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fragmentShaderSource); gl.compileShader(fragmentShader); gl.attachShader(shaderProgram, fragmentShader); // 链接着色器程序 gl.linkProgram(shaderProgram); ``` 然后,需要创建一个地球的顶点数据和纹理数据。这里我们使用了球体的顶点数据和 uv 坐标,以及地球的纹理图像。顶点数据和纹理数据如下: ```javascript // 球体顶点数据 const sphereVertices = []; const sphereUVs = []; const radius = 1; const segments = 32; const rings = 32; for (let r = 0; r < rings + 1; r++) { const theta = r * Math.PI / rings; const sinTheta = Math.sin(theta); const cosTheta = Math.cos(theta); for (let s = 0; s < segments + 1; s++) { const phi = s * 2 * Math.PI / segments; const sinPhi = Math.sin(phi); const cosPhi = Math.cos(phi); const x = cosPhi * sinTheta; const y = cosTheta; const z = sinPhi * sinTheta; sphereVertices.push(radius * x, radius * y, radius * z); sphereUVs.push(s / segments, r / rings); } } // 地球纹理图像 const textureImage = new Image(); textureImage.src = 'earth.jpg'; ``` 接下来,需要将顶点数据和纹理数据上传到 WebGL ,并为着色器程序的变量赋值: ```javascript // 将顶点数据和纹理数据上传到 WebGL const positionBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(sphereVertices), gl.STATIC_DRAW); const uvBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(sphereUVs), gl.STATIC_DRAW); // 为着色器程序的变量赋值 const aPosition = gl.getAttribLocation(shaderProgram, 'aPosition'); gl.enableVertexAttribArray(aPosition); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 0, 0); const aTexCoord = gl.getAttribLocation(shaderProgram, 'aTexCoord'); gl.enableVertexAttribArray(aTexCoord); gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer); gl.vertexAttribPointer(aTexCoord, 2, gl.FLOAT, false, 0, 0); const uModelViewMatrix = gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'); const uProjectionMatrix = gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'); const uSampler = gl.getUniformLocation(shaderProgram, 'uSampler'); // 加载纹理图像 const texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, textureImage); gl.generateMipmap(gl.TEXTURE_2D); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); ``` 最后,需要在循环更新地球的旋转角度,并渲染场景: ```javascript let angle = 0; function render() { // 更新角度 angle += 0.01; // 计算模型视图矩阵和投影矩阵 const modelViewMatrix = mat4.create(); mat4.translate(modelViewMatrix, modelViewMatrix, [0, 0, -5]); mat4.rotateY(modelViewMatrix, modelViewMatrix, angle); const projectionMatrix = mat4.create(); mat4.perspective(projectionMatrix, 45 * Math.PI / 180, canvas.width / canvas.height, 0.1, 100); // 清空画布并绘制地球 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.useProgram(shaderProgram); gl.uniformMatrix4fv(uModelViewMatrix, false, modelViewMatrix); gl.uniformMatrix4fv(uProjectionMatrix, false, projectionMatrix); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, texture); gl.uniform1i(uSampler, 0); gl.drawArrays(gl.TRIANGLE_STRIP, 0, sphereVertices.length / 3); requestAnimationFrame(render); } render(); ``` 这样,一个简单的地球自转的 WebGL Demo 就完成了。完整代码如下:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值