我正在尝试通过webgl绘制一个简单的四边形。以下是一些数据:
顶点数据:(每个顶点2个浮点数)
0:0
1:0
2:1
3:0
4:1
5:1
6:0
7:1
tex coords :(并不重要)
0:-1
1:1
2:1
3:1
4:1
5:-1
6:-1
7:-1
指数:
0:3
1:0
2:1
3:3
4:1
5:2
着色器:
<script id="shader-fs" type="x-shader/x-fragment">
varying highp vec2 vTextureCoord;
uniform highp vec3 uColor;
uniform sampler2D uSampler;
uniform int uSamplerCount;
void main(void) {
highp vec4 texColor =vec4(uColor, 1.0);
if(uSamplerCount > 0)
texColor = texture2D(uSampler, vTextureCoord);
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); //just white for now
}
</script>
<!-- Vertex shader program -->
<script id="shader-vs" type="x-shader/x-vertex">
attribute highp vec2 aVertexPosition;
attribute highp vec2 aTextureCoord;
uniform highp vec2 uPosition;
uniform highp float uZLayer;
varying highp vec2 vTextureCoord;
void main(void) {
gl_Position = vec4(uPosition + aVertexPosition, uZLayer, 1.0);
vTextureCoord = aTextureCoord;
}
</script>
对我来说这似乎没问题。现在我在这里绑定缓冲区:
$p.UpdateBuffers = function ConvexSprite_UpdateBuffers() {
this.gl.bindBuffer(34962 /* WebGLRenderingContext.ARRAY_BUFFER */, this.bVertexPositions);
this.gl.bufferData(34962 /* WebGLRenderingContext.ARRAY_BUFFER */, this.rotatedPoints, 35044 /* WebGLRenderingContext.STATIC_DRAW */);
// string s = rotatedPoints.join(",");
// System.Console.WriteLine("Vertices: " + s);
this.gl.bindBuffer(34962 /* WebGLRenderingContext.ARRAY_BUFFER */, this.bTextureCoords);
this.gl.bufferData(34962 /* WebGLRenderingContext.ARRAY_BUFFER */, this.texCoords, 35044 /* WebGLRenderingContext.STATIC_DRAW */);
//System.Console.WriteLine("Texcoords: " + texCoords.join(","));
this.gl.bindBuffer(34963 /* WebGLRenderingContext.ELEMENT_ARRAY_BUFFER */, this.bIndices);
this.gl.bufferData(34963 /* WebGLRenderingContext.ELEMENT_ARRAY_BUFFER */, this.triangles, 35044 /* WebGLRenderingContext.STATIC_DRAW */);
};
这就是我的绘画方式:
private void DrawScene()
{
gl.viewport(0, 0, (int)canvas.width, (int)canvas.height);
gl.clear(GL.COLOR_BUFFER_BIT | GL.DEPTH_BUFFER_BIT);
testSprite.Draw(aVertexPosition, aTextureCoord, uColor, uPosition, uZLayer, uSampler, uSamplerCount);
}
绘制功能:
public void Draw(uint aVertexPosition, uint aTextureCoord,
WebGLUniformLocation uColor, WebGLUniformLocation uPosition, WebGLUniformLocation uZLayer, WebGLUniformLocation uSampler, WebGLUniformLocation uSamplerCount)
{
//position
gl.uniform2f(uPosition, this.position.x, this.position.y);
gl.uniform1f(uZLayer, this.position.z);
gl.uniform3f(uColor, 1f, 0.5f, 0.5f);
gl.uniform1i(uSamplerCount, 0);
//vertex data
gl.bindBuffer(GL.ARRAY_BUFFER, bVertexPositions);
gl.vertexAttribPointer(aVertexPosition, 2, GL.FLOAT, false, 0, 0);
gl.bindBuffer(GL.ARRAY_BUFFER, bTextureCoords);
gl.vertexAttribPointer(aTextureCoord, 2, GL.FLOAT, false, 0, 0);
gl.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, bIndices);
//texture
// gl.activeTexture(GL.TEXTURE0);
// gl.bindTexture(GL.TEXTURE_2D, texture);
// gl.uniform1i(uSampler, 0);
//draw
gl.drawElements(GL.TRIANGLES, triangles.length, GL.UNSIGNED_SHORT, 0);
}
不幸的是,我得到的只是黑屏。三角形是ccw,并且在0-1位置范围内。这不应该吸引到屏幕上吗?我忘记了什么?
答案 0 :(得分:1)
this.position.x
和this.position.y
的值是多少?假设您拥有最佳的0,1 quad,那么您将能够使用此着色器,并且这些顶点坐标在画布的1/4处绘制四边形。您需要输出的值必须在剪辑空间中(-1&lt; - &gt; +1)。
从像素转换为剪辑空间
clipX = pixelX / gl.canvas.width * 2 - 1
clipY = pixelY / gl.canvas.height * 2 - 1
表示像素空间中的宽度和高度
clipWidth = pixelWidth / gl.canvas.width * 2
clipHeight = pixelHeight / gl.canvas.height * 2
在调试未绘制的WebGL程序时,我做的第一件事就是将片段着色器更改为最简单的东西
gl_FragColor = vec4(1,0,0,1); return;
如果我看到我想到的红色,我知道问题出在了碎片中。如果我不知道问题出在其他地方。
接下来,我可以使用WebGL Inspector来查看我在制服中传递的值。例如,如果this.position.x
或this.position.y
大于1或小于-2,则不会出现任何内容,因为您的四边形为0到1,因此0 + 1
= 1这意味着您的四边形将是在画布的右侧或顶部。 1 + -2 = -1
在这种情况下,四边形将离开画布的左侧或底侧。
其他一些事情。您将其设置为白色gl_FragColor = vec4(1,1,1,1);
,但默认网页颜色为白色,默认的清晰颜色为0,0,0,0
(透明黑色),这意味着除非(a)制作没有alpha的画布(b)将显示的颜色设置为不显示的地方或(c)将页面或画布的CSS设置为您不会看到任何颜色的其他颜色。
这里有一些在像素位置绘制四边形的代码
"use strict";
window.onload = function() {
// Get A WebGL context
var canvas = document.getElementById("c");
var gl = canvas.getContext("webgl");
if (!gl) {
return;
}
// setup GLSL program
var program = webglUtils.createProgramFromScripts(gl, ["2d-vertex-shader", "2d-fragment-shader"]);
gl.useProgram(program);
// look up where the vertex data needs to go.
var positionLocation = gl.getAttribLocation(program, "a_position");
// look up uniform locations
var u_matrixLoc = gl.getUniformLocation(program, "u_matrix");
var u_colorLoc = gl.getUniformLocation(program, "u_color");
// provide texture coordinates for the rectangle.
var positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
0.0, 1.0,
1.0, 0.0,
1.0, 1.0]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
function rand(min, max) {
return min + Math.random() * (max - min) | 0;
}
for (var ii = 0; ii < 300; ++ii) {
var dstX = rand(0, gl.canvas.width - 20);
var dstY = rand(0, gl.canvas.height - 20);
var dstWidth = rand(10, 30);
var dstHeight = rand(10, 30);
// convert dst pixel coords to clipspace coords
var clipX = dstX / gl.canvas.width * 2 - 1;
var clipY = dstY / gl.canvas.height * -2 + 1;
var clipWidth = dstWidth / gl.canvas.width * 2;
var clipHeight = dstHeight / gl.canvas.height * -2;
// build a matrix that will stretch our
// unit quad to our desired size and location
gl.uniformMatrix3fv(u_matrixLoc, false, [
clipWidth, 0, 0,
0, clipHeight, 0,
clipX, clipY, 1,
]);
gl.uniform4f(u_colorLoc, Math.random(), Math.random(), Math.random(), 1);
// Draw the rectangle.
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
}
&#13;
canvas {
border: 1px solid black;
}
&#13;
<script src="//webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
<canvas id="c"></canvas>
<!-- vertex shader -->
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
uniform mat3 u_matrix;
void main() {
gl_Position = vec4(u_matrix * vec3(a_position, 1), 1);
}
</script>
<!-- fragment shader -->
<script id="2d-fragment-shader" type="x-shader/x-fragment">
precision mediump float;
// our texture
uniform vec4 u_color;
void main() {
gl_FragColor = u_color;
}
</script>
&#13;
如果你没有得到矩阵数学here's an article that explains it。
另一个建议,而不是uSamplerCount
的条件,你可能只考虑
gl_FragColor = uColor * texture2D(uSampler, vTextureCoord);
然后制作1像素的白色纹理
whiteTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, whiteTex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, gl.RGBA, gl.UNSIGNED_BYTE,
new Float32Array([255,255,255,255]));
现在每当你想用纯色绘制时,
gl.bindTexture(gl.TEXTURE_2D, whiteTex);
gl.uniform4f(uColorLocation, r, g, b, a);
每当你想用纹理绘制时
gl.bindTexture(gl.TEXTURE_2D, someTexture);
gl.uniform4f(uColorLocation, 1, 1, 1, 1);