在WebGL中使用纹理时,有时我需要使它们比原来更大。当我这样做时,它会使纹理以不同的方式显示,尤其是在较浅的背景上。
我有以下图像(256 x 256):
在WebGL中渲染时,它略大于原始图像。以下是图像在两个不同背景上的显示方式:
如您所见,图像在深色背景上正确显示,但在浅色背景上时,图像呈现白色轮廓。
我的设置代码:
gl.clearColor(0x22 / 0xFF, 0x22 / 0xFF, 0x22 / 0xFF, 1); // set background color
gl.enable(gl.BLEND); // enable transparency
gl.disable(gl.DEPTH_TEST); // disable depth test (causes problems with alpha if enabled)
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); //set up blending
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); //clear the gl canvas
gl.viewport(0, 0, canvas.width, canvas.height); //set the viewport
这是每次加载纹理时调用的代码:
function handleTextureLoaded(image, texture) {
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
gl.generateMipmap(gl.TEXTURE_2D);
gl.bindTexture(gl.TEXTURE_2D, null);
loadCount++;
}
导致轮廓出现的原因,以及如何解决?
注意:当我将原始图像放在这两个相同的背景上时,即使调整图像大小,也不会出现此问题。
我尝试在WebGL上下文中禁用alpha(由@zfedoran讲述):
gl = canvas.getContext('webgl', {antialias: false, alpha: false })
|| canvas.getContext('experimental-webgl', {antialias: false, alpha: false });
图像周围会出现一个小的空白边框,如下所示(放大):
答案 0 :(得分:4)
在@zfedoran提到的画布上的alpha之上,你如何制作原始图像?
我认为问题如下
假设您有这样的抗锯齿边缘。这个像素是什么颜色的?
假设主要颜色(右下角的像素颜色)为1,0,0(纯红色)。理想情况下,箭头指向的像素为(1,0,0,0.5)。换句话说,纯红色的α为0.5。但是,根据图像的创建方式来生成抗锯齿像素,它可能已与其旁边的纯透明像素混合,因此它不再是纯红色。那些纯透明像素可能是(0,0,0,0)透明黑色。
即使您的绘图程序正确处理此问题,GL也可能不会。当您使用纹理过滤(gl.LINEAR
等)绘制图像时,GL会对彼此靠近的像素求平均值,其中一些像素是透明的黑色。混合黑色和红色会产生深红色。因此你会得到一个黑色边框。
"use strict";
function main() {
var planeVertices = [
-1, -1,
1, -1,
-1, 1,
1, 1,
];
var texcoords = [
0, 1,
1, 1,
0, 0,
1, 0,
];
var indices = [
0, 1, 2,
2, 1, 3,
];
var canvas = document.getElementById("c");
var gl = canvas.getContext("webgl", {alpha:false});
var programs = {}
programs.normalProgram = twgl.createProgramFromScripts(
gl, ["2d-vertex-shader", "2d-fragment-shader"], ["a_position", "a_texcoord"]);
programs.preMultiplyAlphaProgram = twgl.createProgramFromScripts(
gl, ["2d-vertex-shader", "pre-2d-fragment-shader"], ["a_position", "a_texcoord"]);
var positionLoc = 0; // assigned in createProgramsFromScripts
var texcoordLoc = 1; // assigned in createProgramsFromScripts
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array(planeVertices),
gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionLoc);
gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array(texcoords),
gl.STATIC_DRAW);
gl.enableVertexAttribArray(texcoordLoc);
gl.vertexAttribPointer(texcoordLoc, 2, gl.FLOAT, false, 0, 0);
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);
gl.bufferData(
gl.ELEMENT_ARRAY_BUFFER,
new Uint16Array(indices),
gl.STATIC_DRAW);
var img = new Image();
img.onload = createTextures;
img.src = document.getElementById("i").text;
function createTexture() {
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
gl.generateMipmap(gl.TEXTURE_2D); // assuming power-of-2
return tex;
}
var textures = {};
function createTextures() {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
textures.unpremultipliedAlphaTexture = createTexture();
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
textures.premultipliedAlphaTexture = createTexture();
document.body.appendChild(document.createElement("hr"));
insert("original image");
document.body.appendChild(img);
render();
}
function insert(text) {
var pre = document.createElement("pre");
pre.appendChild(document.createTextNode(text));
document.body.appendChild(pre);
};
function grabImage(prg, blend, texName) {
document.body.appendChild(document.createElement("hr"));
insert(
"gl.useProgram(" + prg + ")\n" +
"gl.blendFunc(gl." + blend.src + ", gl." + blend.dst + ")\n" +
"gl.bindTexture(gl.TEXTURE2D, " + texName + ")");
var img = new Image();
img.src = gl.canvas.toDataURL();
document.body.appendChild(img);
};
function render() {
gl.enable(gl.BLEND);
Object.keys(programs).forEach(function(p, pndx) {
gl.useProgram(programs[p]);
[
{ src: "SRC_ALPHA", dst: "ONE_MINUS_SRC_ALPHA" },
{ src: "ONE", dst: "ONE_MINUS_SRC_ALPHA" },
].forEach(function(b, bndx) {
gl.blendFunc(gl[b.src], gl[b.dst]);
Object.keys(textures).forEach(function(texName, tndx) {
gl.bindTexture(gl.TEXTURE_2D, textures[texName]);
gl.clearColor(0x3D/0xFF, 0x87/0xFF, 0xEA/0xFF, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
grabImage(p, b, texName);
});
});
});
}
}
main();
canvas {
border: 1px solid black;
display: none;
}
img {
background-color: #3D87EA;
border: 1px solid black;
width: 256px;
height: 256px;
}
<script src="https://twgljs.org/dist/3.x/twgl.min.js"></script>
<!-- vertex shader -->
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec4 a_position;
attribute vec2 a_texcoord;
varying vec2 v_texcoord;
void main() {
gl_Position = a_position;
v_texcoord = a_texcoord;
}
</script>
<!-- fragment shaders -->
<script id="2d-fragment-shader" type="x-shader/x-fragment">
precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D u_texture;
void main() {
gl_FragColor = texture2D(u_texture, v_texcoord);
}
</script>
<script id="pre-2d-fragment-shader" type="x-shader/x-fragment">
precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D u_texture;
void main() {
vec4 textureColor = texture2D(u_texture, v_texcoord);
gl_FragColor = vec4(textureColor.rgb * textureColor.a, textureColor.a);
}
</script>
<canvas id="c" width="32" height="32"></canvas>
<script type="not-js" id="i">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA7dpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wUmlnaHRzPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvcmlnaHRzLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcFJpZ2h0czpNYXJrZWQ9IkZhbHNlIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6RjgxNENDMDEzQjNGNjgxMTgyMkFCRTQ0RTFGNjIxOTciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Q0VDQTU5RDNGNjBEMTFFMjhFRUVEMkI5NkRDNTM4RDYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Q0VDQTU5RDJGNjBEMTFFMjhFRUVEMkI5NkRDNTM4RDYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkRGODJCQjcxQkIyNDY4MTE4MjJBRkMwRDVCNTc4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</script>
有一些解决方案
确保透明区域实际上有颜色。
换句话说,如果上图中左上方的所有像素都是 RED 且带有0 alpha,那么当像素被过滤时,它们将会混合(1,0,0,0) )透明红色代替(0,0,0,0)透明黑色。不幸的是,在大多数绘图程序中没有简单的方法可以做到这一点。
有a plugin for Photoshop that lets you do it called SuperPNG它可以让您为alpha创建第4个频道,而不是使用photoshop的透明度。这使您可以将alpha设置为与图像分开。
在你的情况下,你最终会得到一个像这样的图像的图像
现在没有坏颜色可以融合。
切换到预乘Alpha
在此情况下,请先致电gl.texImage2D
上传图片电话
gl.pixelStorei(UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
在致电gl.texImage2D
之前。这告诉WebGL在加载图像时将颜色乘以alpha。然后使用
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
关闭GL中的过滤
gl.texParameter(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameter(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
假设您的源图像没有任何不良颜色,这意味着GL不会在过滤时产生新的坏颜色,但当然这也意味着如果缩放或旋转图像,您将会出现锯齿。
创建自己的mips
大多数应用使用gl.genereateMipmap
来生成mips,但您可以离线生成它们并自行上传。这不是一个完美的解决方案,但它确实让你使用`gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR_MIPMAP_NEAREST);
以上的组合
答案 1 :(得分:2)
您是否尝试在WebGL上下文中禁用alpha?
var gl = this.canvas.getContext('webgl', {antialias: false, alpha: false })
|| this.canvas.getContext('experimental-webgl', {antialias: false, alpha: false });