坐标系统Get知识点
- 1、模型视图投影变化可以设置成 Projection、viewMatrix、 modelMatrix。
- 1.1、 模型视图矩阵和投影矩阵分别为modelMatrix(模型变换矩阵)、 viewMatrix(视图变换矩阵) 、Porojection(投影变换矩阵)。
viewMatrix 视图矩阵观察空间经常被人们称之OpenGL的摄像机(Camera)(所以有时也称为摄像机空间(Camera Space)或视觉空间(Eye Space))。观察空间是将世界空间坐标转化为用户视野前方的坐标而产生的结果。因此观察空间就是从摄像机的视角所观察到的空间。
modelMatrix 模型变换矩阵。世界空间中的坐标正如其名:是指顶点相对于(游戏)世界的坐标。如果你希望将物体分散在世界上摆放(特别是非常真实的那样),这就是你希望物体变换到的空间。物体的坐标将会从局部变换到世界空间;该变换是由模型矩阵(Model Matrix)实现的。
矩阵相乘注意顺序:矩阵相乘是不满足交换律的。
TransM * RotateM* ScaleM*apos
实际计算时,是从右往左边的顺序。先计算缩放,再计算旋转,最后计算平移。这个顺序才是正确的.
代码编写时,先写trans,在写rotate,最后写scale。
model = glm::mat4(1.0f);
model = glm::translate(model, lightPos);
model = glm::scale(model, glm::vec3(0.2f)); // a smaller cube
注意,当矩阵相乘时我们先写位移再写缩放变换的。矩阵乘法是不遵守交换律的,这意味着它们的顺序很重要。
当矩阵相乘时,在最右边的矩阵是第一个与向量相乘的,所以你应该从右向左读这个乘法。
建议您在组合矩阵时,先进行缩放操作,然后是旋转,最后才是位移,否则它们会(消极地)互相影响。
比如,如果你先位移再缩放,位移的向量也会同样被缩放(译注:比如向某方向移动2米,2米也许会被缩放成1米)!
2、屏幕比例计算,设置layer时有使用[self setContentScaleFactor:[[UIScreen mainScreen]scale]];,所以在设置viewPort时,要将W H,乘以scale,否则只显示一半区域。
3、片元着色器中,纹理值得获取:
a、定义默认属性uniform sampler2D colorMap
b、取值gl_FragColor = texture2D(colorMap,outColorPos);
4、深度测试为什么一直检测错误,需要仔细看一下。
光照_颜色 _Get知识点
- 1、片元着色器中 不能写uniform变量,否则会编译不通过。 需要在定点着色器中写相应的属性,然后通过
varying lowp
在定点着色器和片元着色器中相互传递。 - 2、可以使用多个着色器,然后每个着色器单独提前编译,在绘制之前使用
glUseProgram(self.lightProgram);
,然后提前传递着色器需要的相应的参数就行。 - 3、通过VAO 管理VBO,这样 同样的定点就只需要传递一次就行了。 写法如下:
//1、创建VAO
GLuint boxVAO ;
glGenVertexArrays(1, &boxVAO);
GLuint boxVBO;
glGenBuffers(1, &boxVBO);
glBindBuffer(GL_ARRAY_BUFFER, boxVBO);
//2、绑定 注意这一步的 位置很重要,直接绑定VBO后再上传顶点,否则可能失败,会追不出任何物体。
glBindVertexArray(boxVAO);
//3、上传顶点
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(1);
GLuint aPosId = glGetAttribLocation(self.myProgram, "aPos");
glVertexAttribPointer(aPosId, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), 0);
glEnableVertexAttribArray(aPosId);//绑定顶点坐标
GLuint textPosId = glGetAttribLocation(self.myProgram, "textPos");
glVertexAttribPointer(textPosId, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void*)(3*sizeof(float)));//绑定纹理坐标
glEnableVertexAttribArray(textPosId);
//4、解绑
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//5、绘制前绑定
glBindVertexArray(boxVAO);
for (int i = 0; i < 10; ++i) {
KSMatrix4 modelM;
ksMatrixLoadIdentity(&modelM);
ksTranslate(&modelM, cubePositions[i].x,cubePositions[i].y,cubePositions[i].z);
ksRotate(&modelM, 5*i, 1.0f, 0.3f, 0.5f);
glUniformMatrix4fv(modelId, 1, GL_FALSE, (GLfloat*)&modelM.m[0][0]);
glDrawArrays(GL_TRIANGLES, 0, 36);
}
[self.myContext presentRenderbuffer:GL_RENDERBUFFER];
//6、绘制完成后删除
glDeleteBuffers(1, &boxVBO);
glDeleteVertexArrays(1, &boxVAO);
模板缓冲区 Get知识点
- 1、片元着色器中可以设置多个纹理:
uniform sampler2D boxTexture;
uniform sampler2D ren;
指定纹理采样器的下标为0,1...,对应GL_TEXTURE0,GL_TEXTURE1......
glUniform1i(glGetUniformLocation(self.myProgram,"boxTexture"), 0);//指定采样器 与GL_TEXTURE0 的关系
glUniform1i(glGetUniformLocation(self.myProgram, "ren"), 1);
通过mix指定两个片元的比例,outFloor1 可以通过uniform float floor1变量传递进去,用来设置纹理的混合效果
gl_FragColor = mix(texture2D(boxTexture,outTextCoord),texture2D(ren,outTextCoord),outFloor1);
2、当只有一个纹理采样器 却要针对不同的绘制 展示出不同的纹理时,注意纹理的枚举值只有GL_TEXTURE0,如果GL_TEXTURE1,就错了,因为没有第二个纹理采样器。 所以针对一个采样器不同的纹理值时,只需要调用glBindTexture(GL_TEXTURE_2D, floorTexture); 绑定相应的纹理就行,默认GL_TEXTURE0就是激活状态,不需要再次被激活。当然也不需要激活其他枚举id,因为没有对应的采样器,绘制出肯定是黑色的;
3、绘制提前清除模板缓冲区,并绘制模板缓冲区的值 0x1 (初次绘制,使用GL_REPLACE)
glClearStencil(0x0);
glClear(GL_STENCIL_BUFFER_BIT);
glStencilFunc (GL_ALWAYS, 0x1, 0x1);
glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE);
与glDepthMask(GL_False)等价,禁止写入,每一位写入模板缓冲中的值都会变成0
//glStencilMask(0xFF);//允许写入
glStencilMask(0x00);
4、绘制其他元素时,进行比较是否过滤掉(若过滤掉,就不会绘制)用来绘制边框,过滤图像等
glStencilFunc (GL_EQUAL, 0x1, 0x1);
glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
一定写个demo试一下5片元处理 丢弃
if(texture2D(boxTexture,outTextCoord).a < 0.1)discard;
gl_FragColor = texture2D(boxTexture,outTextCoord);
纹理坐标值计算 需要再次阅读,小草绘制后只有一节,没有展示全部。