博览会上的webgl纹理使黑屏

时间:2019-09-23 16:51:48

标签: react-native webgl textures expo glteximage2d

我第一次尝试使用webGL,这是因为我正在使用expo-gl软件包来开发Expo,目的是为照片编辑构建滤镜组件。到目前为止,我已经能够成功创建上下文。创建着色器时,一切正常(我可以渲染一个三角形,两个三角形等) 问题是,当我尝试将图像加载为纹理时,没有任何错误,但是我得到的只是模拟器和手机(均为android)上的黑屏。 我已经检查了powOf2图片和image.onload,并为gl.texImage2D做了console.log,但未定义。对于这个问题的任何见解或帮助,我将不胜感激。 我将我认为与该问题相关的代码分为四个部分。

1.shaders(模板文字):

    const vertexShaderSource = '
        attribute vec2 a_texCoord;
        attribute vec4 a_position;
        varying vec2 v_texCoord;
        void main() {
          gl_Position = a_position;
          v_texCoord = a_texCoord;
        }
        ';


    const fragmentShaderSource = '
        precision mediump float;
        uniform sampler2D u_image;
        varying vec2 v_texCoord;
        void main() {
          gl_FragColor = texture2D(u_image, v_texCoord);
        }
        ';

2.ReactNative(expo)状态和生命周期:

export default class App extends React.Component {

state = {
    ready: false,
    image: null,
};

componentDidMount() {
    (async () => {
        const image = Asset.fromModule(require('./bw.jpg'));
        await image.downloadAsync();
        this.setState({
            ready: true,
            image,
        });
    })();
}

render() {
    return (
        <View style={styles.container}>
            <Image source={require('./back.jpg')} style={{ width: '100%' }} />
            <GLView
                style={{ width: '100%', height: '100%', position: 'absolute' }}
                onContextCreate={this._onContextCreate}
            />
        </View>
    );
}

3.gl上下文:

_onContextCreate = gl => {
    if (_initialized) { return }
    function createShader(gl, type, source) {
      var shader = gl.createShader(type);
      gl.shaderSource(shader, source);
      gl.compileShader(shader);
      var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
      if (success) {
          return shader;
      }
      //on error
      console.log(gl.getShaderInfoLog(shader));
      gl.deleteShader(shader);
  }
  //get shaders
  var vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
  var fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);

  function createProgram(gl, vertexShader, fragmentShader) {
      var program = gl.createProgram();
      gl.attachShader(program, vertexShader);
      gl.attachShader(program, fragmentShader);
      gl.linkProgram(program);
      //on error
      var success = gl.getProgramParameter(program, gl.LINK_STATUS);
      if (success) {
          return program;
      }
      console.log(gl.getProgramInfoLog(program));
      gl.deleteProgram(program);
  }
  //create program
  var program = createProgram(gl, vertexShader, fragmentShader);
  //get attributes
  var positionAttributeLocation = gl.getAttribLocation(program, "a_position");
  //a_position buffer for fragment shader
  var positionBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
  // three 2d points
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
      -1, -1,
      -1,  1,
       1, -1,
       1,  1,
       1, -1,
      -1,  1,
  ]), gl.STATIC_DRAW);

  //create the viewport
  gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
  // Clear the canvas
  gl.clearColor(0.0, 0.0, 0.0, 0.0);
  gl.clear(gl.COLOR_BUFFER_BIT);
  // use program 
  gl.useProgram(program);
  gl.enableVertexAttribArray(positionAttributeLocation);        
  gl.vertexAttribPointer(
      positionAttributeLocation, 2, gl.FLOAT, false, 0, 0)
  gl.drawArrays(gl.TRIANGLES, 0, 6);

4。纹理代码,_onContextCreate的结尾:

    //get image from state
    const image = this.state.image

    var texCoordLocation = gl.getAttribLocation(program, "a_texCoord");

    var uSampler = gl.getUniformLocation(program, 'u_image');

    // provide texture coordinates for the rectangle.
    var texCoordBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
    var positions = [
        -1,-1,
        -1, 1,
         1,-1,
         1, 1,
         1,-1,
        -1, 1,
    ];
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
    gl.enableVertexAttribArray(texCoordLocation);
    gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);

    //create texture
    var texture = gl.createTexture();
    //check if image is ready
    if (image.downloaded) loadTexture(texture, image)
    //get image width & height for pow2 check.
    const { width, height } = Image.resolveAssetSource(image);
    function loadTexture(texture, img) {
        gl.activeTexture(gl.TEXTURE0);
        gl.bindTexture(gl.TEXTURE_2D, texture);
        gl.uniform1i(uSampler, 0);
        //pow2 check
        if (isPowerOf2(width) && isPowerOf2(height)) {
            gl.generateMipmap(gl.TEXTURE_2D);
        } else {
            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.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
        }
        return texture
    }
    function isPowerOf2(value) {
        return (value & (value - 1)) == 0;
    }

    gl.flush();
    gl.endFrameEXP();
    _initialized = true;
};

谢谢!

0 个答案:

没有答案