美文网首页
OpenGL ES -2.0 绘制地球,月球(公转,自转)

OpenGL ES -2.0 绘制地球,月球(公转,自转)

作者: FGNeverMore | 来源:发表于2017-08-17 15:16 被阅读331次

    对最近一段时间学习OpenGL ES一个阶段性的成果展示,对OpenGL ES从茫茫然,漫无目的的看资料到找到头绪,也算经历了一段时间了,学习GL的API ,学习SL语言,看懂别人的Demo,知道GL的编程思想,到自己写出一些简单的效果.由于之前没有接触过这种底层图形技术,又重新复习了线性代数,方便理解矩阵的变换.

    这里不做基础知识的讲解,有很多大神的博客对此有精炼的讲解,落影loyinglin,OpenGL ES 2.0 笔记,在此分享的是没有使用GLKit框架的情况下,绘制地球和月球的一次实践.

    Erath&Moon.PNG

    GitHub(https://github.com/FengLeNever/FL-LearnOpenGL-ES---master)

    1,启用GL的流程

    - (void)setupOpenGL
    {
        //设置FBO
        [self setupFrameBuffer];
        //编译Shader并Link program
        [self setupShader];
        //读取 Uniform
        _samplerTexture = glGetUniformLocation(self.program, "samplerTexture");
        _modleViewMatrix = glGetUniformLocation(self.program, "modelViewMatrix");
        _projectionMatrix = glGetUniformLocation(self.program, "projectionMatrix");
        
        //加载两个纹理
        _earthTexture = [self loadTextureWithImageName:@"Earth512x256.jpg"];
        _moonTexture = [self loadTextureWithImageName:@"Moon.jpg"];
        
        // 创建VBO,顶点buffer
        glGenBuffers(1, &_ballVBO);
        glBindBuffer(GL_ARRAY_BUFFER, _ballVBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(sphereVerts), sphereVerts, GL_STATIC_DRAW);
        
        // 纹理 buffer
        glGenBuffers(1, &_ballTextcoord);
        glBindBuffer(GL_ARRAY_BUFFER, _ballTextcoord);
        glBufferData(GL_ARRAY_BUFFER, sizeof(sphereTexCoords), sphereTexCoords, GL_STATIC_DRAW);
    }
    
    

    2,绑定Framebuffer

    - (void)setupFrameBuffer
    {
         //设置FBO,并给FBO绑定了colorRenderBuffer , depthRenderBuffer,如果不添加depthRenderBuffer深度缓冲区,因为画的是立体的东东 , 视图显示错误
        glGenRenderbuffers(1, &_colorRenderBuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);
        // 为 color renderbuffer 分配存储空间
        [self.mContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:self.mLayer];
        // 拿到宽和高
        glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_width);
        glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_height);
        // depth renderbuffer 深度缓冲区
        glGenRenderbuffers(1, &_depthRenderBuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBuffer);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, _width, _height);
        // Framebuffers 帧缓冲区
        glGenFramebuffers(1, &_frameBufferHandle);
        glBindFramebuffer(GL_FRAMEBUFFER, _frameBufferHandle);
        // Framebuffers bind color renderbuffer and depth renderbuffer
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                                  GL_RENDERBUFFER, _colorRenderBuffer);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                                  GL_RENDERBUFFER, _depthRenderBuffer);
        // 切换到color renderbuffer
        glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);
    
        // Check FBO satus
        GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
        if (status != GL_FRAMEBUFFER_COMPLETE) {
            NSLog(@"Error: Frame buffer is not completed.");
            exit(1);
        }
    

    3,渲染Render

    - (void)render
    {
        //计算转动角度
        self.earthRotationAngleDegrees += 360.f / 60.f;
        self.moonRotationAngleDegrees += 360.f / 60.f / SceneDaysPerMoonOrbit;
        
        glEnable(GL_DEPTH_TEST);
        glClearColor(0.2, 0.3,0.4, 1.0);
        
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
        
        CGFloat scale = [UIScreen mainScreen].scale;
        CGFloat x = self.frame.origin.x;
        CGFloat y = self.frame.origin.y;
        CGFloat w = self.frame.size.width;
        CGFloat h = self.frame.size.height;
        glViewport(x * scale, y * scale, w * scale, h * scale);
        
        glUseProgram(self.program);
        // ----------------------------- 绘制地球 -----------------------------//
    
        glBindTexture(GL_TEXTURE_2D, _earthTexture);
        glUniform1i(_samplerTexture, 0);
        
        glBindBuffer(GL_ARRAY_BUFFER, _ballVBO);
        glEnableVertexAttribArray(ATTRIB_VERTEX);
        glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3 , 0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        
        glBindBuffer(GL_ARRAY_BUFFER, _ballTextcoord);
        glEnableVertexAttribArray(ATTRIB_TEXCOORD);
        glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE,sizeof(float) * 2, 0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    
        KSMatrix4 projectionMatrix;
        ksMatrixLoadIdentity(&projectionMatrix);
        //正交投影
    //    ksOrtho(&projectionMatrix, -1.f * w / h, 1.f * w / h, -1.f, 1.f, 1.f, 10.f);
        //透视投影
        ksPerspective(&projectionMatrix, 60.f, w / h, 1.f, 10.f);
        glUniformMatrix4fv(_projectionMatrix, 1, GL_FALSE, &projectionMatrix.m[0][0]);
        
        KSMatrix4 earthMatrix = [self earthMartix];
        glUniformMatrix4fv(_modleViewMatrix, 1, GL_FALSE, &earthMatrix.m[0][0]);
        
        glDrawArrays(GL_TRIANGLES, 0, sphereNumVerts);
        
        // ----------------------------- 绘制月球 -----------------------------//
        
        glBindBuffer(GL_ARRAY_BUFFER, _ballVBO);
        glEnableVertexAttribArray(ATTRIB_VERTEX);
        glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3 , 0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        
        glBindBuffer(GL_ARRAY_BUFFER, _ballTextcoord);
        glEnableVertexAttribArray(ATTRIB_TEXCOORD);
        glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE,sizeof(float) * 2, 0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        
        glBindTexture(GL_TEXTURE_2D, _moonTexture);
        
        KSMatrix4 moonMatrix = [self moonMartix];
        glUniformMatrix4fv(_modleViewMatrix, 1, GL_FALSE, &moonMatrix.m[0][0]);
        
        glDrawArrays(GL_TRIANGLES, 0, sphereNumVerts);
    
        [self.mContext presentRenderbuffer:GL_RENDERBUFFER];
    }
    

    4,矩阵Matrix

    - (KSMatrix4)earthMartix
    {
        KSMatrix4 modelViewMatrix = [self getBaseModelViewMatrix];
    
        //倾斜
        KSMatrix4 rotateMatrix;
        ksMatrixLoadIdentity(&rotateMatrix);
        ksRotate(&rotateMatrix, -SceneEarthAxialTiltDeg, 1.f, 0.f, 0.f);
        ksMatrixMultiply(&modelViewMatrix, &rotateMatrix, &modelViewMatrix);
        // 自转
        KSMatrix4 rotateMatrix2;
        ksMatrixLoadIdentity(&rotateMatrix2);
        ksRotate(&rotateMatrix2, self.earthRotationAngleDegrees, 0.f, 1.f, 0.f);
        ksMatrixMultiply(&modelViewMatrix, &rotateMatrix2, &modelViewMatrix);
        return modelViewMatrix;
    }
    
    - (KSMatrix4)moonMartix
    {
        KSMatrix4 modelViewMatrix = [self getBaseModelViewMatrix];
        // 设置公转
        KSMatrix4 rotateMarix1;
        ksMatrixLoadIdentity(&rotateMarix1);
        ksRotate(&rotateMarix1, self.moonRotationAngleDegrees, 0.0, 1.0, 0.0);
        ksMatrixMultiply(&modelViewMatrix, &rotateMarix1, &modelViewMatrix);
        // 平移
        KSMatrix4 totateMatrix2;
        ksMatrixLoadIdentity(&totateMatrix2);
        ksTranslate(&totateMatrix2, 0.0, 0.0, SceneMoonDistanceFromEarth);
        ksMatrixMultiply(&modelViewMatrix, &totateMatrix2, &modelViewMatrix);
        // 缩放
        KSMatrix4 scaleMatrix;
        ksMatrixLoadIdentity(&scaleMatrix);
        ksScale(&scaleMatrix, SceneMoonRadiusFractionOfEarth, SceneMoonRadiusFractionOfEarth, SceneMoonRadiusFractionOfEarth);
        ksMatrixMultiply(&modelViewMatrix, &scaleMatrix, &modelViewMatrix);
        // 自转
        KSMatrix4 rotateMatrix;
        ksMatrixLoadIdentity(&rotateMatrix);
        ksRotate(&rotateMatrix, self.moonRotationAngleDegrees, 0.f, 1.f, 0.f);
        ksMatrixMultiply(&modelViewMatrix, &rotateMatrix, &modelViewMatrix);
        return modelViewMatrix;
    }
    
    - (KSMatrix4)getBaseModelViewMatrix
    {
        KSMatrix4 modelViewMatrix;
        ksMatrixLoadIdentity(&modelViewMatrix);
        ksTranslate(&modelViewMatrix, 0.0, 0.0, -4.0);
        return modelViewMatrix;
    }
    

    总结
    在这种学习新知识过程中,探索是痛苦的,收获是喜人的.愿与诸君共勉.

    相关文章

      网友评论

          本文标题:OpenGL ES -2.0 绘制地球,月球(公转,自转)

          本文链接:https://www.haomeiwen.com/subject/twzgrxtx.html