OPenGL GLSL

shji

数据类型

整型(有符号/无符号)

浮点数(单精度)

布尔值

向量类型/矩阵类型

bool bDone = false

int value =1;

unint vale = 21u

float value = 2.1

向量/分量类型

vec2,vec3,vec4     2分量 3 分量 4 分量复电向量

ivec2 ivec3 ivec4 2 分量 3 分量 4分量整型向量

uvec2 uvec3 uvec4 2分量 3 分量 4分量无符号整型向量

bvec2 bvec3 b各处 2分量 3分量 4 分量bool型向量

向量使用

// 声明4分量的float向量

vec4 value

vec4 v1 = vec4(1,2,3,4)

vec4 v2 = vec4(0,0,0,0)

3.向量运算

v1 = v2 + v3;

vec4 v4 = v1;

v1 += vec4(10,10,10,10)

v1 *- 5;

// 获取向量中的元素 通过下标

v1.x =3.0

v1.y = 4.0

v1.z = 4.0

v1.w = 4.0

v1.xy = vec2(3,5)

v1.xyz = vec3(1,2,3)

获取向量元素可通过r,g,b,a获取向量中元素

v2.r = 1.0f;

v2= vec4(1.0,1.0,1.0,1.0)

获取向量元素 可通过 s,t,p,q (纹理中)

v1.st = vec2(1.0,2.0)

不可以如下

va.st = v2.st

向量数据类型还可以swizzle(调换)操作

v1.bgra = v2,bgra

//向量的一次性所有分量操作

v1.x = v2.x + 5.0f

v1.xyz = v2.xyz + vec3(5,4,3)

矩阵类型

与向量类型不同矩阵类型仅支持 bool 整数

mat4 m1

vec4 v2 

vec4 vOutPos

矩阵可以和向量相乘 应用顶点模型/投影矩阵变化时

m1 = {10f,10f,10f,10f,

           10f,10f,10f,10f,

          10f,10f,10f,10f,}

vOutPos = v2 * m1;

m1 = mat4(1.0f); /// m1 变单元矩阵

存储限定符

着色器变量声明过程中的修饰符

输入变量:从外部(客户端/上一个阶段着色器的属性/Uniform等)

输出变量:从任何着色器阶段进入写入的变量

 限定符常用

<none>只是普通的本地变量,外部不可见 不可访问

const 一个编译常量 或者是一个对函数来说为只读的参数

in/varying  从以前阶段传递过来的变量

in/varying centroid 一个从以前阶段传递过来的变量 使用质心插值

out/attribute. 传递到下一个阶段或者在一个函数中指定一个返回值

out/attribute centroid 传递到下一个阶段 质心插值

uniform 从一个客户端代码传递过来的变量 在顶点之间不做改变

varying从顶点着色器传递到片元着色器 一半会传递颜色值

/*uniform在计算机图形学中,uniform是一个术语,用于描述在图形渲染过程中保持不变的变量或值。uniform变量通常用于传递渲染相关的参数,如光照强度、材质属性、变换矩阵等。这些变量在整个渲染过程中保持不变,无论是对单个物体还是整个场景进行渲染。在OpenGL和OpenGL ES等图形 API 中,uniform变量通过uniform变量声明和赋值来进行设置。你可以在着色器代码中使用uniform变量,并在应用程序中通过相应的 API 函数将其值传递给图形渲染上下文。使用uniform变量可以方便地在应用程序和着色器之间共享数据,并实现更加灵活和可定制的渲染效果外部 applocation传递给 vertx/fragment shader 变量修饰A.他是通过glUniform**()B.在vertex fragment shader 程序内部uniform 和 const类型 表示不能被shader修改注意1.被uniform 修饰的变量 只能被shader 使用read 不能写write 改变2. 如果 uniform 在vertx/fragment 两者的声明方式一样 则它们可以被vertx/fragment共享(uniform float a 在 两个着色器中 声明方式和类型一样)使用场景1.变换矩阵/材质/光照/颜色uniform mat4 viewProjMatrix // 投影与模型视图矩阵uniform mat4 viewMatrix      //模型视图矩阵uniform mat4 lightPosition   //光源位置*/
/*varyingvarying是计算机图形学中的一个术语,用于描述在图形渲染过程中从顶点着色器传递到片段着色器的数据。在OpenGL和OpenGL ES等图形 API 中,varying变量用于在顶点着色器和片段着色器之间传递数据。顶点着色器处理顶点数据,并可以将一些数据通过varying变量传递给片段着色器。varying变量在顶点着色器中进行声明,并在片段着色器中进行使用。它们可以用于传递顶点的位置、颜色、纹理坐标等信息,以便在片段着色器中进行进一步的处理和渲染。通过使用varying变量,片段着色器可以根据每个像素的位置和相关的顶点数据来计算最终的颜色值,从而实现复杂的图形效果。是vertex 与 fragment shader 之间做数据传递 如果需要做传递 则必须保证  vertex shader 与  fragment shader 中两者的声明必须保持一致(修饰符 类型 变量名)否则不能做数据传递使用场景
//纹理坐标/顶点颜色等等*/
/*attribute在计算机图形学中,attribute是一个术语,用于描述在图形渲染过程中传递给顶点着色器的数据。attribute通常是与顶点相关的属性,如顶点的位置、颜色、纹理坐标等。这些属性在应用程序中进行设置,并通过图形 API(如OpenGL、OpenGL ES或Direct3D)传递给图形渲染上下文。在顶点着色器中,可以通过attribute变量来访问和操作传递给顶点的属性数据。顶点着色器可以根据这些属性进行计算和变换,以生成最终的顶点坐标和其他相关数据。attribute变量在顶点着色器的代码中进行声明,并与应用程序中设置的顶点属性相匹配。这样,顶点着色器就可以根据每个顶点的属性来进行个性化的处理和渲染。1.只能在vertshader 中声明和使用 片元着色器 fragment shader 中不能声明也不能使用
2.在application中 glBindAttribLocation()函数来绑定每个变量的位置 然后使用 glVertexAttribPointer()为变量赋值glGetAttribLocation()来获取变量使用场景顶点坐标/法线/纹理坐标/顶点颜色等attribute vec4 a_position;gl_position = viewProjMatrix *  a_position*/
///

ios FrameBuffer

  iOS 中的 FrameBuffer(帧缓冲区)是图形渲染管道中的一个重要组成部分。它是用于存储和管理图形渲染数据的缓冲区。

FrameBuffer 通常包含多个缓冲区,用于存储不同类型的图形数据,如颜色、深度和模板等。这些缓冲区可以在图形渲染过程中被读取和写入,以生成最终的屏幕显示。

在 iOS 中,FrameBuffer 的管理和使用由图形渲染引擎(如 Metal 或 OpenGL ES)负责。应用程序通过这些图形 API 与 FrameBuffer 进行交互,将图形数据渲染到缓冲区中,并最终显示在屏幕上。

FrameBuffer 的性能和效率对图形渲染的性能和质量有着重要影响。优化 FrameBuffer 的使用可以提高图形渲染的效率和性能,例如通过减少缓冲区的切换、使用合适的像素格式和压缩方式等。

如果你在开发 iOS 图形相关的应用程序,了解和优化 FrameBuffer 的使用是提高图形性能的重要方面之一

FrameBuffer  RenderBuffer 有什么关系

FrameBuffer(帧缓冲区)和 RenderBuffer(渲染缓冲区)在图形渲染中是相关的概念,但它们在层次结构和用途上略有不同。

FrameBuffer 是一个更高级别的概念,它通常包含多个 RenderBuffer。FrameBuffer 是用于存储和管理图形渲染数据的缓冲区,它可以包含颜色、深度、模板等信息。FrameBuffer 可以在图形渲染过程中被读取和写入,以生成最终的屏幕显示。

RenderBuffer 是 FrameBuffer 的一部分,它是用于存储特定类型的图形渲染数据的缓冲区。例如,一个 RenderBuffer 可以存储颜色信息,另一个 RenderBuffer 可以存储深度信息。RenderBuffer 通常用于在图形渲染过程中临时存储渲染结果,并在后续的操作中使用这些结果。

在 iOS 中,你可以使用图形渲染 API(如 Metal 或 OpenGL ES)来操作 FrameBuffer 和 RenderBuffer。通过这些 API,你可以创建、配置和使用 FrameBuffer 和 RenderBuffer 来进行图形渲染。

总的来说,FrameBuffer 是一个包含多个 RenderBuffer 的容器,用于存储和管理图形渲染数据。RenderBuffer 是 FrameBuffer 的一部分,用于存储特定类型的渲染数据。它们在图形渲染过程中协同工作,以生成最终的屏幕显示。

ios Renderbuffer

在 iOS 中,RenderBuffer 是用于图形渲染的一种数据结构,它是渲染过程中用于存储渲染结果的缓冲区。

RenderBuffer 通常包含颜色、深度和模板信息等数据,可以用于渲染到屏幕、纹理或其他目标。在 iOS 中,你可以使用 Core Graphics 框架或 Metal 框架来创建和操作 RenderBuffer。

通过使用 RenderBuffer,你可以在渲染过程中临时存储渲染结果,并在后续的操作中使用这些结果。它提供了一种在渲染过程中进行中间结果存储和处理的方式。

如果你需要在 iOS 应用中进行图形渲染,了解和使用 RenderBuffer 可以帮助你管理渲染数据和提高渲染性能。具体的使用方法和细节可以参考相关的文档和 API 参考资料。

顶点着色器和片元着色器程序如何实现变异绑定链接的

1.指定属性

2.设置源码

3.载入文件

iOS 使用OpenGLES

 设置OpenGL ES相关配置
    context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];if(context ==  nil) {NSLog(@"====failed to create context");exit(0);}glView.drawableDepthFormat = GLKViewDrawableDepthFormat16;[EAGLContext setCurrentContext:context];glEnable(GL_DEPTH_TEST);glClearColor(0.1, 0.5, 0.8, 1.0)
加载顶点数据
    GLfloat vertexData[] = {/// 坐标x,y,z 纹理st1, -1, 0.0f,    1.0f, 0.0f, //右下1, 1, -0.0f,    1.0f, 1.0f, //右上-1, 1, 0.0f,    0.0f, 1.0f, //左上1, -1, 0.0f,    1.0f, 0.0f, //右下-1, 1, 0.0f,    0.0f, 1.0f, //左上-1, -1, 0.0f,   0.0f, 0.0f, //左下};glEnableVertexAttribArray(GLKVertexAttribPosition);glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 0);glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 3);
加载纹理数据
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"girl" ofType:@"jpg"];NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: @(1),GLKTextureLoaderOriginBottomLeft,nil];GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil];mEffect = [[GLKBaseEffect alloc] init];mEffect.texture2d0.enabled = GL_TRUE;mEffect.texture2d0.name = textureInfo.name;
实现代理GLKViewDelegate 
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glClearColor(0, 0, 1,   1);[mEffect prepareToDraw];glDrawArrays(GL_TRIANGLES, 0, 6);}

金字塔glsl demo

//
//  PyramidView.m
//  OPenglES_Test
//
//  Created by KING on 2023/12/30.
//#import "PyramidView.h"
#import <OpenGLES/ES2/gl.h>
#import "GLESUtils.h"
#import "GLESMath.h"
@interface PyramidView()
@property (nonatomic,strong) CAEAGLLayer  *caEgaLayer;
@property (nonatomic,strong) EAGLContext  *myContext;
@property (nonatomic,assign) GLuint   colorRenderBuffer;
@property (nonatomic,assign) GLuint   colorFrameBuffer;
@property (nonatomic,assign) GLuint   myProgram;
@property (nonatomic , assign) GLuint  myVertices;
@end
@implementation PyramidView
{float xDegree;float yDegree;float zDegree;bool   dx;bool   dy;bool   dz;NSTimer* myTimer;}- (void)layoutSubviews {[self setUpLayer];[self setUpContext];[self clearBUffer];[self setUpRenderBuffer];[self setUpFrameBuffer];[self drawFrame];
}///1.设置图层
- (void)setUpLayer {self.caEgaLayer = (CAEAGLLayer *)self.layer;[self setContentScaleFactor:[[UIScreen mainScreen] scale]];self.caEgaLayer.opaque = YES;self.caEgaLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8,kEAGLDrawablePropertyColorFormat, nil];
}
///2.设置上下文
-(void)setUpContext{EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];if (!context) {printf("context create error");exit(0);}if (![EAGLContext setCurrentContext:context]) {printf("setCurrentContext context create error");exit(0);}self.myContext = context;
}
///3.清空缓冲区
-(void)clearBUffer {//1.导入框架#import <OpenGLES/ES2/gl.h>/*2.创建2个帧缓存区,渲染缓存区,帧缓存区@property (nonatomic , assign) GLuint myColorRenderBuffer;@property (nonatomic , assign) GLuint myColorFrameBuffer;A.离屏渲染,详细解释见课件B.buffer的分类,详细见课件buffer分为frame buffer 和 render buffer2个大类。其中frame buffer 相当于render buffer的管理者。frame buffer object即称FBO,常用于离屏渲染缓存等。render buffer则又可分为3类。colorBuffer、depthBuffer、stencilBuffer。//绑定buffer标识符glGenRenderbuffers(<#GLsizei n#>, <#GLuint *renderbuffers#>)glGenFramebuffers(<#GLsizei n#>, <#GLuint *framebuffers#>)//绑定空间glBindRenderbuffer(<#GLenum target#>, <#GLuint renderbuffer#>)glBindFramebuffer(<#GLenum target#>, <#GLuint framebuffer#>)*/glDeleteBuffers(1, &_colorRenderBuffer);_colorRenderBuffer = 0;glDeleteBuffers(1, &_colorFrameBuffer);_colorFrameBuffer = 0;
}
///4.设置renderBuffer
-(void)setUpRenderBuffer {//1.定义一个缓存区GLuint buffer;//2.申请一个缓存区标志glGenRenderbuffers(1, &buffer);//3.self.colorRenderBuffer = buffer;//4.将标识符绑定到GL_RENDERBUFFERglBindRenderbuffer(GL_RENDERBUFFER, self.colorRenderBuffer);//frame buffer仅仅是管理者,不需要分配空间;render buffer的存储空间的分配,对于不同的render buffer,使用不同的API进行分配,而只有分配空间的时候,render buffer句柄才确定其类型//为color renderBuffer 分配空间[self.myContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:self.caEgaLayer];}
///5,设置frameBuffer
-(void)setUpFrameBuffer {//1.定义一个缓存区GLuint buffer;//2.申请一个缓存区标志glGenFramebuffers(1, &buffer);//3.self.colorFrameBuffer = buffer;//4.设置当前的framebufferglBindFramebuffer(GL_FRAMEBUFFER, self.colorFrameBuffer);//5.将_myColorRenderBuffer 装配到GL_COLOR_ATTACHMENT0 附着点上glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, self.colorRenderBuffer);//接下来,可以调用OpenGL ES进行绘制处理,最后则需要在EGALContext的OC方法进行最终的渲染绘制。这里渲染的color buffer,这个方法会将buffer渲染到CALayer上。- (BOOL)presentRenderbuffer:(NSUInteger)target;}
///6.绘制render
-(void)drawFrame {glClearColor(0.2, 0.5, 0.8, 1.0);glClear(GL_COLOR_BUFFER_BIT);CGFloat scale = [[UIScreen mainScreen] scale];glViewport(self.frame.origin.x * scale, self.frame.origin.y * scale, scale * self.frame.size.width, scale * self.frame.size.height);/// 获取顶点或者片元着色器的位置NSString *vertFile = [[NSBundle mainBundle] pathForResource:@"pyramidv" ofType:@"vsh"];NSString *frameFile = [[NSBundle mainBundle] pathForResource:@"pyramidf" ofType:@"fsh"];if (self.myProgram) {glDeleteProgram(self.myProgram);self.myProgram = 0;}self.myProgram = [self loadShaderWithVertFile:vertFile frameFile:frameFile];/// 链接glLinkProgram(self.myProgram);GLint linkSuccess;glGetProgramiv(self.myProgram, GL_LINK_STATUS, &linkSuccess);if (linkSuccess == GL_FALSE) {NSLog(@"link statues failed");exit(0);}glUseProgram(self.myProgram);/// 创建索引数组GLuint indices[] = {0,3,2,0,1,3,0,2,4,0,4,1,2,3,4,1,4,3,};/// 顶点数据if (self.myVertices == 0) {glGenBuffers(1, &_myVertices);}//顶点数组//前3顶点值(x,y,z),后3位颜色值(RGB)GLfloat attrArr[] ={-0.5f, 0.5f, 0.0f,      1.0f, 0.0f, 1.0f, //左上0.5f, 0.5f, 0.0f,       1.0f, 0.0f, 1.0f, //右上-0.5f, -0.5f, 0.0f,     1.0f, 1.0f, 1.0f, //左下0.5f, -0.5f, 0.0f,      1.0f, 1.0f, 1.0f, //右下0.0f, 0.0f, 1.0f,       0.0f, 1.0f, 0.0f, //顶点};//-----处理顶点数据-------glBindBuffer(GL_ARRAY_BUFFER, _myVertices);glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_DYNAMIC_DRAW);//1.glGetAttribLocation,用来获取vertex attribute的入口的.2.告诉OpenGL ES,通过glEnableVertexAttribArray,3.最后数据是通过glVertexAttribPointer传递过去的。//注意:第二参数字符串必须和shaderv.vsh中的输入变量:position保持一致GLuint position = glGetAttribLocation(self.myProgram, "position");//打开position 默认是关闭的glEnableVertexAttribArray(position);// 1.位置 2.每次传多少个 3.类型 4.是否需要归一化5.步长 6.读取开始位置glVertexAttribPointer(position, 3,GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), NULL);//3.设置读取方式//参数1:index,顶点数据的索引//参数2:size,每个顶点属性的组件数量,1,2,3,或者4.默认初始值是4.//参数3:type,数据中的每个组件的类型,常用的有GL_FLOAT,GL_BYTE,GL_SHORT。默认初始值为GL_FLOAT//参数4:normalized,固定点数据值是否应该归一化,或者直接转换为固定值。(GL_FALSE)//参数5:stride,连续顶点属性之间的偏移量,默认为0;//参数6:指定一个指针,指向数组中的第一个顶点属性的第一个组件。默认为0// 颜色数据GLuint positionColor = glGetAttribLocation(self.myProgram, "positionColor");//打开positionColor 默认是关闭的glEnableVertexAttribArray(positionColor);// 1.位置 2.每次传多少个 3.类型 4.是否需要归一化5.步长 6.读取开始位置glVertexAttribPointer(positionColor, 3,GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (float *)NULL + 3);//注意,想要获取shader里面的变量,这里记得要在glLinkProgram后面,后面,后面!/*一个一致变量在一个图元的绘制过程中是不会改变的,所以其值不能在glBegin/glEnd中设置。一致变量适合描述在一个图元中、一帧中甚至一个场景中都不变的值。一致变量在顶点shader和片断shader中都是只读的。首先你需要获得变量在内存中的位置,这个信息只有在连接程序之后才可获得*///找到myProgram中的projectionMatrix、modelViewMatrix 2个矩阵的地址。如果找到则返回地址,否则返回-1,表示没有找到2个对象。// 投影矩阵GLuint  projectionMatrixLocation = glGetUniformLocation(self.myProgram, "projectionMatrix");// 纵横比 透视投影float aspect = self.frame.size.width / self.frame.size.height;/// 创建矩阵4x4KSMatrix4 _projectionMatrix;// 加载单元矩阵ksMatrixLoadIdentity(&_projectionMatrix);/// 设置透视投影ksPerspective(&_projectionMatrix, 30.0, aspect, 5.0f, 20.0f);/// 将次矩阵传递到顶点着色器中去glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, (GLfloat *)&_projectionMatrix.m[0][0]);// 开启正背面剔除glEnable(GL_CULL_FACE);// 模型视图矩阵GLuint  modelViewMatrixLocation = glGetUniformLocation(self.myProgram, "modelViewMatrix");/// 创建矩阵4x4KSMatrix4 _modelViewMatrix;// 加载单元矩阵ksMatrixLoadIdentity(&_modelViewMatrix);/// z轴平移ksTranslate(&_modelViewMatrix, 0, 0, -10);/// 创建旋转矩阵KSMatrix4 _rotationMatrix;ksMatrixLoadIdentity(&_rotationMatrix);ksRotate(&_rotationMatrix, xDegree, 1.0, 0.0, 0.0);ksRotate(&_rotationMatrix, yDegree, 0.0, 1.0, 0.0);ksRotate(&_rotationMatrix, zDegree, 0.0, 0.0, 1.0);/// 将旋转矩阵和模型视图矩阵结合ksMatrixMultiply(&_modelViewMatrix, &_rotationMatrix, &_modelViewMatrix);glUniformMatrix4fv(modelViewMatrixLocation, 1, GL_FALSE, (GLfloat *)&_modelViewMatrix.m[0][0]);// 索引绘图glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(indices[0]), GL_UNSIGNED_INT, indices);[self.myContext presentRenderbuffer:GL_RENDERBUFFER];}
-(GLint)loadShaderWithVertFile:(NSString *)vertFile frameFile:(NSString *)frameFile {GLuint program = glCreateProgram();GLuint vShader,fShader;[self complieShaderPath:vertFile shader:&vShader type:GL_VERTEX_SHADER];[self complieShaderPath:frameFile shader:&fShader type:GL_FRAGMENT_SHADER];glAttachShader(program, vShader);glAttachShader(program, fShader);glDeleteShader(vShader);glDeleteShader(fShader);return program;
}
-(void)complieShaderPath:(NSString *)path shader:(GLuint *)shader type:(GLuint)type {NSString *file = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];const GLchar *source = (GLchar *)[file UTF8String];*shader = glCreateShader(type);glShaderSource(*shader , 1, &source, NULL);glCompileShader(*shader);
}
+(Class)layerClass {return [CAEAGLLayer class];
}
-(void)changeRotateDirectTag:(NSInteger)tag {if (!myTimer) {myTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(degree) userInfo:nil repeats:YES];}if (tag == 100)  {dx = !dx;} else if (tag == 200) {dy = !dy;} else if (tag == 300) {dz = !dz;} else {dx = false;dy = false;dz = false;[myTimer invalidate];myTimer = nil;}}
-(void)degree{xDegree += dx * 5;yDegree += dy * 5;zDegree += dz * 5;[self drawFrame];
}
- (void)dealloc {[myTimer invalidate];myTimer = nil;}/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {// Drawing code
}
*/@end
shader 
attribute vec4 position;
attribute vec4 positionColor;
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;varying lowp vec4 varyColor;
void main() {varyColor = positionColor;vec4 vPos;vPos = projectionMatrix * modelViewMatrix * position;gl_Position = vPos;
}
varying lowp vec4 varyColor;void main() {gl_FragColor = varyColor;
}
GLKi demo
//
//  PyramidViewController02.m
//  OPenglES_Test
//
//  Created by KING on 2023/12/31.
//#import "PyramidViewController02.h"
#import "PyramidView02.h"
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>@interface PyramidViewController02 ()
@property (nonatomic,strong) PyramidView02 *pramidView;@property (nonatomic,strong)EAGLContext *myContext;
@property (nonatomic,strong)GLKBaseEffect  *mEffect;
@property(nonatomic,assign)int count;//旋转的度数
@property(nonatomic,assign)float XDegree;
@property(nonatomic,assign)float YDegree;
@property(nonatomic,assign)float ZDegree;//是否旋转X,Y,Z
@property(nonatomic,assign) BOOL XB;
@property(nonatomic,assign) BOOL YB;
@property(nonatomic,assign) BOOL ZB;@end@implementation PyramidViewController02
{dispatch_source_t timer;
}
- (void)viewDidLoad {[super viewDidLoad];
//     Do any additional setup after loading the view.
//    self.pramidView =[[PyramidView02 alloc] initWithFrame:self.view.bounds];
//    [self.view addSubview:_pramidView];[self setUpContext];[self render];UIButton *buttonX = [UIButton buttonWithType:UIButtonTypeCustom];[buttonX setTitle:@"X" forState:UIControlStateNormal];buttonX.backgroundColor = UIColor.blackColor;buttonX.tag = 100;buttonX.frame = CGRectMake(10, self.view.frame.size.height - 200.0, 100, 50);[buttonX addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];[self.view addSubview:buttonX];UIButton *buttonY = [UIButton buttonWithType:UIButtonTypeCustom];[buttonY setTitle:@"Y" forState:UIControlStateNormal];buttonY.tag = 200;buttonY.frame = CGRectMake(120, self.view.frame.size.height - 200.0, 100, 50);[buttonY addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];[self.view addSubview:buttonY];UIButton *buttonZ = [UIButton buttonWithType:UIButtonTypeCustom];[buttonZ setTitle:@"Z" forState:UIControlStateNormal];buttonZ.tag = 300;buttonZ.frame = CGRectMake(230, self.view.frame.size.height - 200.0, 100, 50);[buttonZ addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];[self.view addSubview:buttonZ];UIButton *buttonS = [UIButton buttonWithType:UIButtonTypeCustom];[buttonS setTitle:@"stop" forState:UIControlStateNormal];buttonS.frame = CGRectMake(220, self.view.frame.size.height - 100.0, 100, 50);[buttonS addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];[self.view addSubview:buttonS];}
-(void)btnClick:(UIButton *)btn {dispatch_source_cancel(timer);timer = nil;if (btn.tag == 100)  {_XB = !_XB;} else if (btn.tag == 200) {_YB = !_YB;} else if (btn.tag == 300) {_ZB = !_ZB;} else {_XB = false;_YB = false;_ZB = false;}[self render];}-(void)setUpContext {EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];GLKView *view = (GLKView *)self.view;self.myContext = context;view.context = context;view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;view.drawableDepthFormat = GLKViewDrawableDepthFormat24;if (![EAGLContext setCurrentContext:context]) {printf("setcurrent context failed\n");return;}glEnable(GL_DEPTH_TEST);
}
-(void)render {//1.顶点数据//前3个元素,是顶点数据;中间3个元素,是顶点颜色值,最后2个是纹理坐标GLfloat attrArr[] ={-0.5f, 0.5f, 0.0f,      0.0f, 0.0f, 0.5f,       0.0f, 1.0f,//左上0.5f, 0.5f, 0.0f,       0.0f, 0.5f, 0.0f,       1.0f, 1.0f,//右上-0.5f, -0.5f, 0.0f,     0.5f, 0.0f, 1.0f,       0.0f, 0.0f,//左下0.5f, -0.5f, 0.0f,      0.0f, 0.0f, 0.5f,       1.0f, 0.0f,//右下0.0f, 0.0f, 1.0f,       1.0f, 1.0f, 1.0f,       0.5f, 0.5f,//顶点};//2.绘图索引GLuint indices[] ={0, 3, 2,0, 1, 3,0, 2, 4,0, 4, 1,2, 3, 4,1, 4, 3,};/// 顶点个数self.count = sizeof(indices)/sizeof(GLuint);/// 将顶点数据载入缓冲区GLuint buffer;glGenBuffers(1, &buffer);glBindBuffer(GL_ARRAY_BUFFER, buffer);glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_STATIC_DRAW);//将索引数据存储到索引数组缓冲区GLuint index;glGenBuffers(1, &index);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);///顶点数据加进去glEnableVertexAttribArray(GLKVertexAttribPosition);glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, NULL);// 颜色数据glEnableVertexAttribArray(GLKVertexAttribColor);glVertexAttribPointer(GLKVertexAttribColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL + 3);// 纹理数据glEnableVertexAttribArray(GLKVertexAttribTexCoord0);glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL + 6);/// 获取纹理NSString *path = [[NSBundle mainBundle] pathForResource:@"star" ofType:@"jpg"];NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:@"1",GLKTextureLoaderOriginBottomLeft, nil];GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:path options:dict error:nil];//effectself.mEffect = [[GLKBaseEffect alloc] init];self.mEffect.texture2d0.enabled = GL_TRUE;self.mEffect.texture2d0.name = textureInfo.name;//投影方式float aspect = fabs(self.view.frame.size.width/self.view.frame.size.height);GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(80.0), aspect, 1.0, 50);projectionMatrix = GLKMatrix4Scale(projectionMatrix, 1.0, 1.0, 1.0);/// 设置投影矩阵self.mEffect.transform.projectionMatrix = projectionMatrix;/// 模型视图GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0f, 0.0f, -2.0f);//模型视图矩阵传入self.mEffect.transform.modelviewMatrix = modelViewMatrix;double seconds = 0.1;timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC, 0.0);dispatch_source_set_event_handler(timer, ^{self.XDegree += 0.1f * self.XB;self.YDegree += 0.1f * self.YB;self.ZDegree += 0.1f * self.ZB ;});dispatch_resume(timer);}
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {glClearColor(0.0, 0.0, 0.0, 1);glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);[self.mEffect prepareToDraw];// 索引绘图glDrawElements(GL_TRIANGLES, self.count, GL_UNSIGNED_INT, 0);
}
-(void)update{// 矩阵改变GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0, 0, -2.0);modelViewMatrix = GLKMatrix4RotateX(modelViewMatrix, self.XDegree);modelViewMatrix = GLKMatrix4RotateX(modelViewMatrix, self.YDegree);modelViewMatrix = GLKMatrix4RotateX(modelViewMatrix, self.ZDegree);//self.mEffect.transform.modelviewMatrix = modelViewMatrix;}
/*
#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/587956.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习---随机森林宫颈癌分类

1. 宫颈癌分类 from sklearn import tree from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.model_selection import GridSearchCV from sklearn.pipeline import Pipeline from sklearn.preprocessi…

VistualStudio查看类图UML

点击菜单栏中的工具–》获取工具和功能。 然后在资源管理器中对应的代码中鼠标右键选择查看类图 生成一个ClassDiagram.cd文件就是类图的文件了。 根据需要拖拽就可以生成类图了。

常用的 MySQL 可视化客户端

数据库可视化客户端&#xff08;GUI&#xff09;让用户在和数据库进行交互时&#xff0c;能直观地查看、创建和修改对象&#xff0c;如&#xff1a;表、行和列。让数据库操作变得更方便了。 今天&#xff0c;我们来了解下目前市场上最常用的 MySQL 可视化客户端。 官方&#x…

数据结构期末复习(2)链表

链表 链表&#xff08;Linked List&#xff09;是一种常见的数据结构&#xff0c;用于存储一系列具有相同类型的元素。链表由节点&#xff08;Node&#xff09;组成&#xff0c;每个节点包含两部分&#xff1a;数据域&#xff08;存储元素值&#xff09;和指针域&#xff08;指…

vscode配置的C++环境

目录 1、下载并安装VScode 2、下载MinGW 3、配置MinGW 3.1添加环境变量 3.2 Vscode配置 3.3测试 1、下载并安装VScode Visual Studio Code - Code Editing. Redefined 2、下载MinGW 在MinGW官网MinGW-w64 - for 32 and 64 bit Windows - Browse /mingw-w64/mingw-w64-r…

List集合格式转换

最近遇到一个任务&#xff1a; 需要把A集合数据转成 B集合的形式&#xff1a; A集合&#xff1a; B集合&#xff1a; 代码&#xff1a; package com.example.juc.test;import com.example.juc.entity.Ld; import com.example.juc.entity.Student;import java.lang.reflect.F…

【Petalinux】制作SD卡 操作系统 启动

Vivado 添加 SD0 导出hdf 制作SD卡 https://mathd.blog.csdn.net/article/details/135217761 【Petalinux】下为空白SD卡建立BOOT&#xff0c;rootfs分区 Petalinux 生成 Petalinux 框架 petalinux-create --type project --template zynq --name sdtest进入 sdtest 文件…

Ksher H5页面支付实例指导 (PHP实现)

前文 背景介绍 前两天&#xff0c;公司的项目&#xff0c;为了满足泰国客户的支付需求&#xff0c;要求使用 Ksher (开时支付) 对接任务突然就给了鄙人&#xff0c;一脸懵 … 通过了解客户的使用场景、以及参考官网指导 发现&#xff1a;Ksher支付 最令人满意的便是 —— 提供了…

【网络安全/CTF】easyphp 江苏工匠杯

本题考察PHP语言相关绕过知识 正文 开门见山给代码 <?php highlight_file(__FILE__); $key1 0; $key2 0;$a $_GET[a]; $b $_GET[b];if(isset($a) && intval($a) > 6000000 && strlen($a) < 3){if(isset($b) && 8b184b substr(md5($b),…

【Java】如何给你的图片添加自定义水印(附完整代码)?

这是一篇关于怎么尽可能的用尽你电脑里的所有字体给你的图片加水印。。。。 先上效果~ 当然这只是其中一部分字体&#xff0c;&#xff0c;&#xff0c;我也是今天才发现我电脑里居然装了那么多字体 好了废话不多说直接上完整代码~ import io.swagger.models.auth.In;import …

循环生成对抗网络(CycleGAN)

一、说明 循环生成对抗网络&#xff08;CycleGAN&#xff09;是一种训练深度卷积神经网络以执行图像到图像翻译任务的方法。网络使用不成对的数据集学习输入和输出图像之间的映射。 二、基本介绍 CycleGAN 是图像到图像的翻译模型&#xff0c;就像Pix2Pix一样。Pix2Pix模型面临…

软件测试/测试开发丨Python 内置库 sys 学习笔记分享

sys 概述 是 Python 自带的内置模块是与 Python 解释器交互的桥梁 sys 使用 常用属性常用方法导入 sys 模块 # 导入sys模块 import sys# 查看sys模块帮助文档 help(sys)# 查看sys模块的属性和方法 print(dir(sys))sys 常用属性 sys.version&#xff1a;返回 Python 解释器…

软件测试/测试开发丨Python 面向对象编程思想

面向对象是什么 Python 是一门面向对象的语言面向对象编程&#xff08;OOP&#xff09;&#xff1a;Object Oriented Programming 所谓的面向对象&#xff0c;就是在编程的时候尽可能的去模拟真实的现实世界&#xff0c;按照现实世界中的逻辑去处理问题&#xff0c;分析问题中…

AI电商时代开始:阿里能否反杀拼多多

“AI电商时代刚刚开始&#xff0c;对谁都是机会&#xff0c;也是挑战。” 针对阿里员工对于拼多多财报和电商等的讨论&#xff0c;马云在阿里内网罕见地参与了谈论并发言。 阿里巴巴一向雷厉风行&#xff0c;已打响了AI电商的“第一炮”。 根据《晚点LatePost》报道&#xff…

C# vs报错 id为XX的进程当前未运行

报错原因&#xff1a;虚拟目录端口被占用 解决方法&#xff1a;重新配置新的目录端口就行 1、选择项目属性 2、更改端口号&#xff0c;点击创建虚拟目录 3、重新生成项目

ISP 基础知识积累

Amber&#xff1a;现有工作必要的技术补充&#xff0c;认识需要不断深入&#xff0c;这个文档后续还会增加内容进行完善。 镜头成像资料 ——干货满满&#xff0c;看懂了这四篇文章&#xff0c;下面的问题基本都能解答 看完思考 1、ISP 是什么&#xff0c;有什么作用&#xff…

C++实现定积分运算

文章目录 题目代码 题目 代码 #include <iostream> #include <cmath> #include <functional>using namespace std;// 定积分函数 double integrate(function<double(double)> func, double a, double b, int num_intervals) {double h (b - a) / num…

Cisco无线Mobility Express配置Image TFTP服务器

思科的无线AP&#xff1a; 1800&#xff0c; 2800&#xff0c; 3800系列 这一类的AP本身可以做为无线控制器使用&#xff0c;被称为Mobility Express&#xff0c;简称为ME 可以管理多少AP 最多可管理 25个 是否需要license才能管理 不需要license 支持哪些型号的AP注册 只要…

浅谈冯诺依曼体系和操作系统

&#x1f30e;冯诺依曼体系结构 文章目录 冯诺依曼体系结构 认识冯诺依曼体系结构       硬件分类       各个硬件的简单认识         输入输出设备         中央处理器         存储器 关于内存 对冯诺依曼体系的理解 操作系统 操作系统…

野火霸道-V2+3.2寸屏+FreeRTOS+LVGL移植

摘要 基于野火霸道-V23.2寸屏的开发板&#xff0c;下载器为STLINK分为两个版本&#xff0c;FreeRTOS和裸机版本 裸机 裸机准备 lvgl v8.2版本的源码野火的《触摸画板-3.2寸》与《基本定时器》的代码例程 移植 将基本定时器代码移植到触摸画板-3.2寸的例程中&#xff0c;…