Heim >Web-Frontend >js-Tutorial >Web-Lernen zur Verwendung von Texturkarten

Web-Lernen zur Verwendung von Texturkarten

little bottle
little bottlenach vorne
2019-04-30 11:29:012349Durchsuche

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

Web-Lernen zur Verwendung von Texturkarten

2D-Textur

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

    1. Verstärken (gl.TEXTURE_MAP_FILTER): So erhalten Sie die Texturfarbe, wenn der Zeichenbereich der Textur größer ist als die Textur selbst. Wenn beispielsweise ein 16*16-Texturbild auf einen 32*32-Pixel-Raum abgebildet wird, wird die Texturgröße doppelt so groß wie die Originalgröße. Der Standardwert ist gl.LINEAR.
    2. Minimieren (gl.TEXTURE_MIN_FILTER): So erhalten Sie die Texelfarbe, wenn der Draw Return der Textur kleiner ist als die Textur selbst. Wenn beispielsweise ein 32*32-Texturbild einem 16*16-Pixel-Raum zugeordnet wird, entspricht die Größe der Textur nur der Originalgröße. Der Standardwert ist gl.NEAREST_MIPMAP_LINEAR.
    3. Horizontale Polsterung (gl.TEXTURE_WRAP_S): Gibt an, wie der linke oder rechte Bereich des Texturbilds gefüllt wird. Der Standardwert ist gl.REPEAT.
    4. Vertikale Polsterung (gl.TEXTURE_WRAP_T): Gibt an, wie der Bereich über und unter dem Texturbild gefüllt wird. Der Standardwert ist gl.REPEAT.
  • param: Der Wert des Texturparameters

    1. 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)

    2. kann den Konstanten von

      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

Das Einstellungsbeispiel lautet wie folgt:

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 Reflexion

Implementieren 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

为了实现更逼真的高光效果,继续实现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();
})()

最后实现的效果如下,明显更加接近真实的地板

Web-Lernen zur Verwendung von Texturkarten

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!

Stellungnahme:
Dieser Artikel ist reproduziert unter:cnblogs.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen