WebGL绘制矩形&图像到一个着色器
WebGL draw rect & image to one shader
只是想做一些基本的webgl,我有两个"游戏对象"。一个简单的精灵和一个矩形。基本上,我想做的是绘制精灵图像,然后绘制一个指定颜色的矩形。
两个对象都有一个pos
矢量,宽度和高度。sprite有一个图像对象,rect有一个rgb值为0到1的颜色对象。
对不起所有的代码,但这是我的绘图方法:
draw: function () {
this.resize();
var delta = this.getDeltaTime();
gl.viewport(0, 0, gl.canvas.clientWidth, gl.canvas.clientHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
var shaderProgram = this.shader.shaderProgram;
var matrixLocation = gl.getUniformLocation(shaderProgram, "uMatrix");
for (var i = 0; i < this.objects.length; i++) {
var planePositionBuffer = gl.createBuffer();
mat3.identity(this.mvMatrix);
gl.bindBuffer(gl.ARRAY_BUFFER, planePositionBuffer);
var object = this.objects[i];
var x1 = object.pos.x;
var y1 = object.pos.y;
var x2 = object.pos.x + object.width;
var y2 = object.pos.y + object.height;
var vertices = [
x1, y1,
x2, y1,
x1, y2,
x1, y2,
x2, y1,
x2, y2
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0);
var textureBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer);
var textureCoords;
if (object.image) {
var dw = (object.width / object.image.image.width);
var dh = 1.0 - (object.height / object.image.image.height);
textureCoords = [
0.0, 1.0,
dw, 1.0,
0.0, dh,
0.0, dh,
dw, 1.0,
dw, dh
];
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this.objects[i].image);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
}
mat3.multiply(this.mvMatrix, this.mvMatrix, [
2 / gl.canvas.clientWidth, 0, 0,
0, -2 / gl.canvas.clientHeight, 0,
-1, 1, 1
]);
gl.uniformMatrix3fv(matrixLocation, false, this.mvMatrix);
gl.uniform1i(shaderProgram.samplerUniform, 0);
var colorLocation = gl.getUniformLocation(shaderProgram, "uColor");
if (object.color) {
var color = object.color;
gl.uniform4f(colorLocation, color.r, color.g, color.b, 1);
}
else {
gl.uniform4f(colorLocation, 1.0, 1.0, 1.0, 1);
}
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 6);
}
requestAnimationFrame(this.draw.bind(this));
}
基本上,我正在做的是把位置坐标放在一起,以便在哪里绘制图像/矩形。
然后我检查对象是否有图像。如果是,则根据其精灵宽度与图像尺寸计算纹理坐标。并绑定纹理。
然后在下面,如果对象没有颜色,我将统一颜色设置为白色。如果对象确实有一种颜色,则会根据该颜色设置统一。
现在,在我的列表中,图像sprite是第一个,rect是第二个,bindTexture首先针对图像调用。这会一直持续到抽签。OpenGL是一个状态机,因此图像首先绘制,保持绑定,然后再次绘制直角坐标。它只是使用了我保存在矩形中的绿色。
所以我在这里的主要问题是:有合适的方法来解决这个问题吗或者有没有一种方法只在某些情况下针对顶点绘制颜色,而在另一种情况下针对纹理绘制颜色?
这是我的着色器:
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
varying vec2 vTextureCoord;
uniform sampler2D uSampler;
uniform vec4 uColor;
void main(void) {
gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)) * uColor;
}
</script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec2 aVertexPosition;
attribute vec2 aTextureCoord;
uniform mat3 uMatrix;
varying vec2 vTextureCoord;
void main() {
gl_Position = vec4((uMatrix * vec3(aVertexPosition, 1)).xy, 0, 1);
vTextureCoord = aTextureCoord;
}
</script>
很简单。使用统一矩阵使代码中的屏幕坐标超过剪辑坐标。
使用单个着色器绘制纹理或颜色的典型方法是将未使用的着色器设置为白色并相乘或黑色并相加。我更喜欢白色和乘法,这是你已经有的了。
所以,当你只想用纹理绘制时
var whiteColor = [1, 1, 1, 1];
gl.bindTexture(gl.TEXTURE_2D, textureWithImageInIt);
gl.uniform4fv(uColorLocation, whiteColor);
当你只想用一个颜色绑定1x1像素的白色纹理绘制
在初始时间
var white1PixelTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, white1PixelTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
new Uint8Array([255,255,255,255]));
提款时
gl.bindTexture(gl.TEXTURE_2D, white1PixelTexture);
gl.uniform4fv(uColorLocation, someColor);
这是因为white = 1
和1 * something = something
是texture * 1 = texture
、1 * color = color
;
它还可以使纹理着色以获得简单的效果。将颜色设置为redish [1, 0.4, 0.4, 1]
,您将获得红色版本的纹理。随着时间的推移调整alpha [1, 0, 0, lerpColorOverTime]
,您可以淡出纹理。
是的,有一种正确的方法,只需在完成后解除纹理绑定即可:
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, null);
- D3在一个调用中绘制不同的SVG形状,没有可见性
- 有没有一个javascript图形绘制库可以进行气球树布局
- 只有一个图像被绘制到画布上
- 从 Ol3 中的绘制交互中删除最后一个点
- 使用 jQuery animate 时绘制一个又一个对象的线条
- 如何在一个适用于HTML5的TeeChart中绘制堆叠和普通系列
- 单击鼠标在画布上绘制一个实心圆
- FLOT只绘制一个值,或者没有绘制整个图形
- 如何在画布上绘制一个简单的五角大楼
- 用一个加载项绘制图像阵列
- 绘制一个没有边框的空心圆
- 从带有循环的数组中一个接一个地在画布上绘制形状
- 一个很好的方法来抵消所有绘制到画布上的0.5像素
- 将一个画布绘制到另一个不起作用的画布上
- 在画布上绘制另一个图像
- 如何在D3 Javascript中绘制一个简单的力导向图
- 在鼠标移动时绘制一个矩形,并使用 kineticjs 在鼠标向上选择该矩形内的所有形状
- 在 Openlayer3 中只允许一个绘制功能
- 在主动画循环中执行另一个绘制循环,持续5秒
- 是否有一种方法来确定一个给定的点(宽,长)是否在一个绘制的多边形内