グラフィックスに実物に近い質感を持たせるためには、一般的にテクスチャが使用されますが、テクスチャには主に拡散反射マップと鏡面ハイライトマップの2種類があります。拡散反射マップは、拡散反射光と環境光の効果を同時に実現できます。
実際の効果についてはデモをご覧ください: テクスチャ マッピング
を使用する必要があります。テクスチャを実装するにはテクスチャを使用します。一般的に使用されるテクスチャ形式は、2D テクスチャ、キューブ テクスチャ、3D テクスチャです。最も基本的な 2D テクスチャを使用して、このセクションで必要な効果を実現できます。テクスチャの使用に必要な API を見てみましょう。関連チュートリアル: js ビデオ チュートリアル
テクスチャの座標原点は左下隅にあり、通常の左上隅の座標原点とは正反対であるため、次は次のようになります。便宜上、Y軸に従って反転するように座標を設定します。
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
テクスチャをアクティブにしてバインドします。gl.TEXTURE0 はテクスチャ番号 0 を意味し、0 から最大まで増加できます。 TEXTURE_2D は 2D テクスチャを表します。
gl.activeTexture(gl.TEXTURE0);//激活纹理 gl.bindTexture(gl.TEXTURE_2D, texture);//绑定纹理
次のステップは、テクスチャ パラメータを設定することです。この API は非常に重要であり、テクスチャの最も複雑な部分でもあります。
gl.texParameteri(target, pname, param)、param の値を、ターゲットにバインドされたテクスチャ オブジェクトの pname パラメータに割り当てます。パラメータ:
target: gl.TEXTURE_2D または gl.TEXTURE_CUBE_MAP
pname: はい4 つのテクスチャ パラメータを指定します。
param: テクスチャ パラメータ
の値は gl.TEXTURE_MAP_FILTER および # に割り当てることができます。 ##gl .TEXTURE_MIN_FILTER パラメータ値
gl.NEAREST: マップされたピクセルの中心に最も近い元のテクスチャ上のピクセルのカラー値を値として使用します。新しいピクセルの。
gl.LINEAR: 新しいピクセルの中心に最も近い 4 つのピクセルのカラー値の加重平均を新しいピクセルの値として使用します (gl.LINEAR と比較)。最も近い、この方法は画質が優れていますが、オーバーヘッドも大きくなります。)
gl.TEXTURE_WRAP_S および gl.TEXTURE_WRAP_T## に割り当て可能な定数#:
gl.REPEAT: タイルの繰り返しテクスチャ
gl.MIRRORED_REPEAT: ミラー化された対称の繰り返しテクスチャ# gl.CLAMP_TO_EDGE: テクスチャ イメージのエッジ値を使用する
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
、バインドされたテクスチャ オブジェクトにピクセルを割り当てます。この API には、
WebGL1 および WebGL2 に十数個のオーバーロードされた関数があり、形式の種類は非常に多様です。ピクセル パラメータには画像、キャンバス、またはビデオを指定できます。WebGL1 の呼び出しフォームのみを確認します。 // WebGL1:
void gl.texImage2D(target, level, internalformat, width, height, border, format, type, ArrayBufferView? pixels);
void gl.texImage2D(target, level, internalformat, format, type, ImageData? pixels);
void gl.texImage2D(target, level, internalformat, format, type, HTMLImageElement? pixels);
void gl.texImage2D(target, level, internalformat, format, type, HTMLCanvasElement? pixels);
void gl.texImage2D(target, level, internalformat, format, type, HTMLVideoElement? pixels);
void gl.texImage2D(target, level, internalformat, format, type, ImageBitmap? pixels);
// WebGL2:
//...
function loadTexture(url) {
const texture = gl.createTexture();
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
let textureInfo = {
width: 1,
height: 1,
texture: texture,
};
const img = new Image();
return new Promise((resolve,reject) => {
img.onload = function() {
textureInfo.width = img.width;
textureInfo.height = img.height;
gl.bindTexture(gl.TEXTURE_2D, textureInfo.texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
resolve(textureInfo);
};
img.src = url;
});
}
まず拡散反射ライト マップを実装し、さまざまな種類のマップが含まれるフロア マップをインターネットからダウンロードします。
const arrays = { position: [ -1, 0, -1, -1, 0, 1, 1, 0, -1, 1, 0, 1 ], texcoord: [ 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0 ], normal: [ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1 ], };
頂点シェーダー間の唯一の違いは、テクスチャ座標の追加です。これには、フラグメント シェーダーに補間を渡す必要があります。
//... attribute vec2 a_texcoord; varying vec2 v_texcoord; void main() { //... v_texcoord = a_texcoord; }
フラグメント シェーダーをさらに変更する必要があります。主に
texture2Dを使用して、対応する座標のテクセルを取得し、前の色を置き換えます。以下はフラグメントシェーダ関連のコードです
//... vec3 normal = normalize(v_normal); vec4 diffMap = texture2D(u_samplerD, v_texcoord); //光线方向 vec3 lightDirection = normalize(u_lightPosition - v_position); // 计算光线方向和法向量夹角 float nDotL = max(dot(lightDirection, normal), 0.0); // 漫反射光亮度 vec3 diffuse = u_diffuseColor * nDotL * diffMap.rgb; // 环境光亮度 vec3 ambient = u_ambientColor * diffMap.rgb; //...
js部分はテクスチャに相当する画像を読み込み、テクスチャユニットを渡してレンダリングを行います//...
(async function (){
const ret = await loadTexture('/model/floor_tiles_06_diff_1k.jpg')
setUniforms(program, {
u_samplerD: 0//0号纹理
});
//...
draw();
})()
为了实现更逼真的高光效果,继续实现Web 学習: テクスチャ マップの使用方法,实现原理和漫反射一样,把对应的高光颜色替换成Web 学習: テクスチャ マップの使用方法纹素就可以了。
下面就是片元着色器增加修改高光部分
//... vec3 normal = normalize(v_normal); vec4 diffMap = texture2D(u_samplerD, v_texcoord); vec4 specMap = texture2D(u_samplerS, v_texcoord); //光线方向 vec3 lightDirection = normalize(u_lightPosition - v_position); // 计算光线方向和法向量夹角 float nDotL = max(dot(lightDirection, normal), 0.0); // 漫反射光亮度 vec3 diffuse = u_diffuseColor * nDotL * diffMap.rgb; // 环境光亮度 vec3 ambient = u_ambientColor * diffMap.rgb; // 镜面高光 vec3 eyeDirection = normalize(u_viewPosition - v_position);// 反射方向 vec3 halfwayDir = normalize(lightDirection + eyeDirection); float specularIntensity = pow(max(dot(normal, halfwayDir), 0.0), u_shininess); vec3 specular = (vec3(0.2,0.2,0.2) + specMap.rgb) * specularIntensity; //...
js同时加载漫反射和Web 学習: テクスチャ マップの使用方法
//... (async function (){ const ret = await Promise.all([ loadTexture('/model/floor_tiles_06_diff_1k.jpg'), loadTexture('/model/floor_tiles_06_spec_1k.jpg',1) ]); setUniforms(program, { u_samplerD: 0,//0号纹理 u_samplerS: 1 //1号纹理 }); //... draw(); })()
最后实现的效果如下,明显更加接近真实的地板
以上がWeb 学習: テクスチャ マップの使用方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。