• 学习OpenGL:笔记八


    基本纹理

    纹理通常来说就是一张图片,我们为每一个顶点指定纹理坐标,然后就可以在Shader中获取相应的纹理像素点颜色了。一般使用uv来表示纹理坐标,uv是一个二维向量(u,v),u和v的取值从0到1。我在代码中为每个顶点数据增加了2个GLFloat来表示uv的值。

    - (void)drawXPlanes {
        static GLfloat triangleData[] = {
    // X轴0.5处的平面
          0.5,  -0.5,    0.5f, 1,  0,  0, 0, 0,
          0.5,  -0.5f,  -0.5f, 1,  0,  0, 0, 1,
          0.5,  0.5f,   -0.5f, 1,  0,  0, 1, 1,
          0.5,  0.5,    -0.5f, 1,  0,  0, 1, 1,
          0.5,  0.5f,    0.5f, 1,  0,  0, 1, 0,
          0.5,  -0.5f,   0.5f, 1,  0,  0, 0, 0,
    // X轴-0.5处的平面
          -0.5,  -0.5,    0.5f, -1,  0,  0, 0, 0,
          -0.5,  -0.5f,  -0.5f, -1,  0,  0, 0, 1,
          -0.5,  0.5f,   -0.5f, -1,  0,  0, 1, 1,
          -0.5,  0.5,    -0.5f, -1,  0,  0, 1, 1,
          -0.5,  0.5f,    0.5f, -1,  0,  0, 1, 0,
          -0.5,  -0.5f,   0.5f, -1,  0,  0, 0, 0,
        };
        [self bindAttribs:triangleData];
        glDrawArrays(GL_TRIANGLES, 0, 12);
    }  
    

    我们来观察一下X轴0.5处的平面的顶点数据。

          0.5,  -0.5,    0.5, 1,  0,  0, 0, 0,
          0.5,  -0.5,  -0.5, 1,  0,  0, 0, 1,
          0.5,  0.5,   -0.5, 1,  0,  0, 1, 1,
          0.5,  0.5,    -0.5, 1,  0,  0, 1, 1,
          0.5,  0.5,    0.5, 1,  0,  0, 1, 0,
          0.5,  -0.5,   0.5, 1,  0,  0, 0, 0, 
    

      

    这是一个正方形,uv和顶点对应关系如下。 0.5, -0.5, 0.5点对应的uv0, 0,  0.5, -0.5, -0.5点对应的uv0, 1,  0.5, 0.5, -0.5点对应的uv1, 1 , 0.5, 0.5, 0.5点对应的uv是1, 0。

    然后增加绑定uv属性的代码。

     GLuint positionAttribLocation = glGetAttribLocation(self.shaderProgram, "position");
        glEnableVertexAttribArray(positionAttribLocation);
        GLuint colorAttribLocation = glGetAttribLocation(self.shaderProgram, "normal");
        glEnableVertexAttribArray(colorAttribLocation);
        GLuint uvAttribLocation = glGetAttribLocation(self.shaderProgram, "uv");
        glEnableVertexAttribArray(uvAttribLocation);
        
        // 为shader中的position和color赋值
        // glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
        // indx: 上面Get到的Location
        // size: 有几个类型为type的数据,比如位置有x,y,z三个GLfloat元素,值就为3
        // type: 一般就是数组里元素数据的类型
        // normalized: 暂时用不上
        // stride: 每一个点包含几个byte,本例中就是6个GLfloat,x,y,z,r,g,b
        // ptr: 数据开始的指针,位置就是从头开始,颜色则跳过3个GLFloat的大小
        glVertexAttribPointer(positionAttribLocation, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (char *)triangleData);
        glVertexAttribPointer(colorAttribLocation, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (char *)triangleData + 3 * sizeof(GLfloat));
        glVertexAttribPointer(uvAttribLocation, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (char *)triangleData + 6 * sizeof(GLfloat));
    

    生成纹理

       NSString *textureFile = [[NSBundle mainBundle] pathForResource:@"texture" ofType:@"jpg"];
       NSError *error;
       self.diffuseTexture = [GLKTextureLoader textureWithContentsOfFile:textureFile options:nil error:&error];
    

      

    绑定和使用纹理

    有了纹理,接下来就要把它传递给Shader,前面我们已经把每个顶点的纹理坐标传递给了Vertex Shader。在Vertex Shader中新增了属性attribute vec2 uv;,以及varying vec2 fragUV;。Vertex Shader做的事情就是把uv直接传递给Fragment Shader,让它去处理。

    attribute vec4 position;
    attribute vec3 normal;
    attribute vec2 uv;
    
    uniform float elapsedTime;
    uniform mat4 projectionMatrix;
    uniform mat4 cameraMatrix;
    uniform mat4 modelMatrix;
    
    varying vec3 fragNormal;
    varying vec2 fragUV;
    
    void main(void) {
        mat4 mvp = projectionMatrix * cameraMatrix * modelMatrix;
        fragNormal = normal;
        fragUV = uv;
        gl_Position = mvp * position;
    }

     

    Fragment Shader中增加了uniform sampler2D diffuseMap;sampler2D是纹理的参数类型。然后将diffuseMap在纹理坐标fragUV上的像素颜色作为基本色vec4 materialColor texture2D(diffuseMapfragUV);texture2D函数用来采样纹理在某个uv坐标下的颜色,返回值类型是vec4

    precision highp float;
    varying vec3 fragNormal;
    varying vec2 fragUV;
    uniform float elapsedTime;
    uniform vec3 lightDirection;
    uniform mat4 normalMatrix;
    uniform sampler2D diffuseMap;
    void main(void) {
        vec3 normalizedLightDirection = normalize(-lightDirection);
        vec3 transformedNormal = normalize((normalMatrix * vec4(fragNormal, 1.0)).xyz);
        float diffuseStrength = dot(normalizedLightDirection, transformedNormal);
        diffuseStrength = clamp(diffuseStrength, 0.0, 1.0);
        vec3 diffuse = vec3(diffuseStrength); vec3 ambient = vec3(0.3);
        vec4 finalLightStrength = vec4(ambient + diffuse, 1.0);
        vec4 materialColor = texture2D(diffuseMap, fragUV);
        gl_FragColor = finalLightStrength * materialColor;
    }

    绑定纹理的流程

    • 激活纹理的某个通道glActiveTexture(GL_TEXTURE0);,OpenGL ES中最多可以激活8个通道。通道0是默认激活的,所以本例中这一句也可以不写。
    • 绑定生成的纹理到GL_TEXTURE_2D, glBindTexture(GL_TEXTURE_2Dself.diffuseTexture.name);,注意这里是绑定到GL_TEXTURE_2D而不是GL_TEXTURE0
    • 将0传递给uniform diffuseMap,如果激活的是GL_TEXTURE1就传递1,以此类推。

      

  • 相关阅读:
    ubuntu上如何安装和卸载google chrome 浏览器
    另眼相看“那些争议最大的编程观点”
    读完了csapp(中文名:深入理解计算机系统)
    SSL工作原理
    linux signal 处理
    PCB设计资料:看到最后才知道是福利
    String.Format使用方法
    matlab三维画图
    spin_lock & mutex_lock的差别?
    Hibernate Criterion
  • 原文地址:https://www.cnblogs.com/neverMore-face/p/10162978.html
Copyright © 2020-2023  润新知