2

我第一次尝试 webGL,事情是我正在使用 expo-gl 包在 Expo 上工作,旨在构建一个用于照片编辑的过滤器组件。到目前为止,我已经能够成功地创建一个上下文。创建着色器时一切正常(我可以渲染一个三角形、两个三角形等......)当我尝试将图像加载为纹理时出现问题,我没有收到任何错误,但我得到的只是黑屏模拟器和手机(都是安卓)。我已经检查了 powOf2 图像和 image.onload,并且我为 gl.texImage2D 做了一个 console.log,但没有定义。对于这个问题,我真的很感激任何见解或帮助。我将我认为与此问题相关的代码分为 4 个部分。

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;
};

提前致谢!

4

0 回答 0