Heim >Web-Frontend >js-Tutorial >Web-Lernen zur Verwendung von Texturkarten
Um Grafiken realistische Materialeffekte zu verleihen, werden im Allgemeinen Texturen verwendet. Es gibt zwei Haupttypen von Texturen: diffuse Reflexionskarten und spiegelnde Glanzlichtkarten. Mit der diffusen Reflexionskarte können gleichzeitig die Effekte von diffusem Reflexionslicht und Umgebungslicht erzielt werden.
Bitte sehen Sie sich die Demo für den tatsächlichen Effekt an: Texturkarte
Um die Karte zu implementieren Sie müssen Textur verwenden. Häufig verwendete Texturformate sind: 2D-Textur, Würfeltextur, 3D-Textur. Wir können die einfachste 2D-Textur verwenden, um die in diesem Abschnitt erforderlichen Effekte zu erzielen. Werfen wir einen Blick auf die APIs, die für die Verwendung von Texturen erforderlich sind. Zugehörige Tutorials: js-Video-Tutorial
Da der Koordinatenursprung der Textur in der unteren linken Ecke liegt, was unserem üblichen Koordinatenursprung in der oberen linken Ecke genau entgegengesetzt ist, ist Folgendes um es entsprechend der Y-Achse umzukehren, was praktisch ist. Wir legen die Koordinaten fest.
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
aktiviert und bindet Texturen, gl.TEXTURE0 stellt Textur Nr. 0 dar, die von 0 bis nach oben ansteigen kann. TEXTURE_2D stellt eine 2D-Textur dar.
gl.activeTexture(gl.TEXTURE0);//激活纹理 gl.bindTexture(gl.TEXTURE_2D, texture);//绑定纹理
Der nächste Schritt besteht darin, die Texturparameter festzulegen. Diese API ist sehr wichtig und auch der komplexeste Teil der Textur.
gl.texParameteri(target, pname, param), weisen Sie den Wert von param dem pname-Parameter des an das Ziel gebundenen Texturobjekts zu. Parameter:
target: gl.TEXTURE_2D oder gl.TEXTURE_CUBE_MAP
pname: Ja Geben Sie 4 Texturparameter an
param: Der Wert des Texturparameters
kann gl.TEXTURE_MAP_FILTER und gl .TEXTURE_MIN_FILTER Parameterwert
gl.NEAREST: Verwenden Sie als Wert den Farbwert des Pixels auf der Originaltextur, das der Mitte des zugeordneten Pixels am nächsten liegt des neuen Pixels.
gl.LINEAR: Verwenden Sie den gewichteten Durchschnitt der Farbwerte der vier Pixel, die der Mitte des neuen Pixels am nächsten liegen, als Wert des neuen Pixels (im Vergleich zu gl. NÄCHSTES hat diese Methode eine bessere Bildqualität (besser, aber auch teurer)
gl.TEXTURE_WRAP_S und gl.TEXTURE_WRAP_T zugewiesen werden :
gl.REPEAT: Kacheln wiederholte Textur
gl.MIRRORED_REPEAT: Gespiegelte symmetrische wiederholte Textur
gl.CLAMP_TO_EDGE: Kantenwert des Texturbildes verwenden
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);
gl .texImage2D weist dem gebundenen Texturobjekt Pixel zu. Diese API verfügt über mehr als ein Dutzend überladene Funktionen in WebGL1 und WebGL2, und die Formattypen sind sehr unterschiedlich. Der Pixelparameter kann ein Bild, eine Leinwand oder ein Video sein. Wir betrachten nur das aufrufende Formular in 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: //...Ich habe eine Texturladefunktion gekapselt. Das Aufrufformat jeder API kann zuerst angezeigt werden.
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; }); }Karte der diffusen ReflexionImplementieren Sie zunächst die Karte des diffusen Reflexionslichts und laden Sie eine Grundrisskarte aus dem Internet herunter, die verschiedene Arten von Karten enthält. Der Puffer muss die Texturkoordinaten hinzufügen, die den Scheitelpunkten entsprechen, damit die entsprechenden Texturpixel, die als Texel bezeichnet werden, über die Texturkoordinaten gefunden werden können.
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 ], };Der einzige Unterschied im Vertex-Shader ist das Hinzufügen von Texturkoordinaten, die interpoliert und an den Fragment-Shader übergeben werden müssen.
//... attribute vec2 a_texcoord; varying vec2 v_texcoord; void main() { //... v_texcoord = a_texcoord; }Der Fragment-Shader erfordert weitere Modifikationen. Verwenden Sie hauptsächlich
texture2D, um das Texel an den entsprechenden Koordinaten abzurufen und die vorherige Farbe zu ersetzen. Das Folgende ist der Code für den Fragment-Shader
//... 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; //...Der js-Teil lädt das der Textur entsprechende Bild, übergibt die Textureinheit und rendert dann den
//... (async function (){ const ret = await loadTexture('/model/floor_tiles_06_diff_1k.jpg') setUniforms(program, { u_samplerD: 0//0号纹理 }); //... draw(); })()-Effekt wie folgt Der hervorgehobene Teil scheint zu grell zu sein, da der Boden zu hell ist. Es entsteht keine gleichmäßige und starke Reflexion wie bei einem Spiegel.
为了实现更逼真的高光效果,继续实现Web-Lernen zur Verwendung von Texturkarten,实现原理和漫反射一样,把对应的高光颜色替换成Web-Lernen zur Verwendung von Texturkarten纹素就可以了。
下面就是片元着色器增加修改高光部分
//... 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-Lernen zur Verwendung von Texturkarten
//... (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(); })()
最后实现的效果如下,明显更加接近真实的地板
Das obige ist der detaillierte Inhalt vonWeb-Lernen zur Verwendung von Texturkarten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!