GLSL着色器支持着色和纹理

时间:2016-10-23 11:23:56

标签: javascript glsl webgl

我试着写一个支持颜色和纹理的着色器 出于某种原因,我可以使它发挥作用 没有错误,每个错误分别完美,

获取位置:

shaderProgram.useTextureUniform = gl.getUniformLocation(shaderProgram, "uUseTexture");

绘图时我改变了这样的值:

    var uUseTexture=false;
    gl.uniform1f(shaderProgram.useTextureUniform, uUseTexture);

GLSL本身:

片段:

precision mediump float;
uniform sampler2D uSampler;
varying vec2 vTextureCoord;
varying vec4 vColor;
uniform bool uUseTexture;
void main(void) {
    vec4 textureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
    vec4 texColor = vec4(textureColor.rgb, textureColor.a);
    vec4 vertexColor = vColor; 
    if (!uUseTexture){
        gl_FragColor = vertexColor;
    }
    else{
        gl_FragColor = texColor; 
    }
}

顶点:

    attribute vec3 aVertexPosition;
    attribute vec3 aVertexNormal;
    attribute vec2 aTextureCoord;
    attribute vec4 aVertexColor;

    uniform mat4 uMVMatrix;
    uniform mat4 uPMatrix;
    uniform mat3 uNMatrix;

    varying vec2 vTextureCoord;
    varying vec4 vColor;


    void main(void){
        vec4 mvPosition = uMVMatrix * vec4(aVertexPosition, 1.0);
        gl_Position = uPMatrix * mvPosition;
        vTextureCoord = aTextureCoord;
        vColor = aVertexColor;}

1 个答案:

答案 0 :(得分:3)

在我告诉你如何让你的着色器工作之前,你可以说不应该这样做。你应该

  1. 制作2个着色器

    制作一个使用纹理的着色器和使用顶点颜色的不同着色器。这就是几乎所有专业游戏引擎都会做的事情。

  2. 制作一个将两种颜色相乘的着色器并将其设置为白色

    如果你有

    gl_FragColor = vertexColor * textureColor;
    

    然后,如果textureColor1,1,1,1,则意味着您乘以1 所以结果只是vertexColor。同样如果vertexColor1,1,1,1然后你乘以1,结果就是这样 textureColor

    只需制作一个像素白色纹理就可以获得白色纹理

    var tex = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, tex);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA,
                  gl.UNSIGNED_BYTE, new Uint8Array([255, 255, 255, 255]));
    

    然后,只要您想要顶点颜色将纹理绑定到纹理 单位并告诉采样器你把它放在哪个单位

    您可能还想关闭纹理坐标

    gl.disableVertexAttribArray(texcoordLocation);
    

    当你想要纹理颜色时,你可以这样做

    // turn off the attribute
    gl.disableVertexAttribArray(aVertexColorLocation);
    
    // set the attribute's constant value
    gl.vertexAttrib4f(aVertexColorLocation, 1, 1, 1, 1);
    

    此方法的另一个好处是,您还可以同时使用纹理颜色和顶点颜色来修改纹理颜色或为纹理颜色着色。许多游戏引擎也会专门利用这种能力来混合颜色。

  3. Pauli提到了另一种选择,即使用mix

    uniform float u_mixAmount;
    
    gl_FragColor = mix(textureColor, vertexColor, u_mixAmount);
    

    这也可以,因为您可以根据需要将u_mixAmount设置为0.0 textureColor和1.0,如果你想要vertexColor但不同于你的vertexColor 布尔示例您也可以使用值在2种颜色之间淡入淡出 介于0.0和1.0之间。例如,0.3是textureColor的30%和70% vec4 texColor = vec4(textureColor.rgb, textureColor.a);

  4. 其他一些事情

    这一行

    vec4 texColor = textureColor;
    

    无异
    var gl = document.querySelector("canvas").getContext("webgl");
    var m4 = twgl.m4;
    
    var arrays = {
      aVertexPosition: [
        -1, -1, 0,
         1, -1, 0,
        -1,  1, 0,
         1,  1, 0,
      ],
      aVertexNormal: [
         0,  0,  1,
         0,  0,  1,
         0,  0,  1,
         0,  0,  1,
      ],
      aTextureCoord: [
         0,  0, 
         1,  0,
         0,  1,
         1,  1,
      ],
      aVertexColor: [
         1, 0, 0, 1,
         0, 1, 0, 1,
         0, 0, 1, 1,
         1, 0, 1, 1,
      ],
      indices: [
        0, 1, 2,
        2, 1, 3,
      ],
    };
        
    var tex = twgl.createTexture(gl, {
      format: gl.LUMINANCE,
      mag: gl.NEAREST,
      src: [224, 64, 128, 192],
    });
    var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
    var programInfo = twgl.createProgramInfo(gl, ['vs', 'fs']);
    gl.useProgram(programInfo.program);
    twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
    for (var i = 0; i < 2; ++i) {
      twgl.setUniforms(programInfo, {
        uMVMatrix: m4.identity(),
        uPMatrix: m4.scale(m4.translation([i === 0 ? -0.5 : 0.5, 0, 0]), [0.5, 1, 1]),
        uNMatrix: m4.identity(),
        uSampler: tex,
        uUseTexture: i === 1,
      });
      twgl.drawBufferInfo(gl, bufferInfo);
    }

    只是尝试使用着色器,它似乎可以正常工作,这表明问题不是您的着色器,而是代码的其他部分。

    canvas { border: 1px solid black; }
    <script src="https://twgljs.org/dist/2.x/twgl-full.min.js"></script>
    <script id="fs" type="not-js">
    precision mediump float;
    uniform sampler2D uSampler;
    varying vec2 vTextureCoord;
    varying vec4 vColor;
    uniform bool uUseTexture;
    void main(void) {
        vec4 textureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
        vec4 texColor = vec4(textureColor.rgb, textureColor.a);
        vec4 vertexColor = vColor; 
        if (!uUseTexture){
            gl_FragColor = vertexColor;
        }
        else{
            gl_FragColor = texColor; 
        }
    }
    </script>
    <script id="vs" type="not-js">
        attribute vec3 aVertexPosition;
        attribute vec3 aVertexNormal;
        attribute vec2 aTextureCoord;
        attribute vec4 aVertexColor;
    
        uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;
        uniform mat3 uNMatrix;
    
        varying vec2 vTextureCoord;
        varying vec4 vColor;
    
    
        void main(void){
            vec4 mvPosition = uMVMatrix * vec4(aVertexPosition, 1.0);
            gl_Position = uPMatrix * mvPosition;
            vTextureCoord = aTextureCoord;
            vColor = aVertexColor;}
    </script>
    <canvas></canvas>
    .main {
      position: fixed;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      width: 100%;
      height: 100%;
      margin: auto;
      border-radius: 0;
      background: linear-gradient(to bottom, #f1b900 0%, #f1b900 50%, #000000 50%, #272660 50%, #272660 100%);
      /* W3C */
      -moz-box-sizing: border-box;
      -webkit-box-sizing: border-box;
      box-sizing: border-box;
      -moz-box-shadow: -3px 0 6px #4a5562;
      -webkit-box-shadow: -3px 0 6px #4a5562;
      box-shadow: -3px 0 6px #4a5562;
      -moz-transition: all 300ms;
      -webkit-transition: all 300ms;
      width: 100%;
      transition: all 300ms;
      height: 100%;
    }
    .folderimg {
      box-sizing: border-box;
      background: url("folder.png") center center no-repeat;
      background-size: contain;
      position: fixed;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      width: 75%;
      height: 75%;
      z-index: -1;
    }
    .foldername {
      -webkit-transform: rotate(-5deg);
      -moz-transform: rotate(-55eg);
      -ms-transform: rotate(-5deg);
      -o-transform: rotate(-5deg);
      filter: progid: DXImageTransform.Microsoft.BasicImage(rotation=3);
      font-size: 4vmin;
      position: absolute;
      margin-top: 5%;
      margin-left: 12%;
    }