4. 顶点着色器-mvp转换

4. 顶点着色器-mvp转换

目录

概述

4. 顶点着色器-mvp转换

  • 属性:用顶点数组提供的逐顶点数据(顶点位置、颜色、纹理)

  • 统一变量和统一变量缓冲区:顶点着色器使用的不变数据(mvp变换矩阵)

  • 采样器:代表顶点着色器使用的纹理的特殊统一变量类型

  • 着色器程序:顶点着色器程序源代码或者描述在操作顶点的可执行文件

设置统一变量的流程

 // 1. 在着色器程序中声明uniform变量
  const char vShaderStr[] =
  "#version 300 es \n"
  "uniform mat4 u_mvpMatrix; \n"  // 声明统一变量,u_mvpMatrix
  "layout(location = 0) in vec4 a_position; \n"
  "layout(location = 1) in vec4 a_color; \n"
  "out vec4 v_color; \n"
  "void main() \n"
  "{ \n"
  "   v_color = a_color; \n"
  "   gl_Position = u_mvpMatrix * a_position; \n" // 进行mvp转换
  "} \n";
 2. 获取uniform变量的引用
  userData->mvpLoc = glGetUniformLocation(userData->programObject, "u_mvpMatrix"); // 获取u_mvpMatrix统一变量的引用
 3. 给uniform变量赋值
  glUniformMatrix4fv(userData->mvpLoc, 1, GL_FALSE, (GLfloat *)&userData->mvpMatrix.m[0][0]);  // 给u_mvpMatrix统一变量赋值

平移矩阵-行优先还是列优先

void myesTranslate ( ESMatrix *result, GLfloat tx, GLfloat ty, GLfloat tz )
 {
  result->m[3][0] += ( result->m[0][0] * tx + result->m[1][0] * ty + result->m[2][0] * tz );
  result->m[3][1] += ( result->m[0][1] * tx + result->m[1][1] * ty + result->m[2][1] * tz );
  result->m[3][2] += ( result->m[0][2] * tx + result->m[1][2] * ty + result->m[2][2] * tz );
  result->m[3][3] += ( result->m[0][3] * tx + result->m[1][3] * ty + result->m[2][3] * tz );
 }
 
 书上求得的平移矩阵的样子:
 1, 0, 0, transX
 0, 1, 0, transY
 0, 0, 1, transZ
 0, 0, 0, 1
 
 opengl中平移矩阵的样子:
 1, 0, 0, 0
 0, 1, 0, 0
 0, 0, 1, 0
 transX, transY, transZ, 1

 解释:
 出于编程目的,OpenGL矩阵是16值数组,基本向量在内存中连续放置。转换分量占据16元素矩阵的第13、14和15个元素,其中索引的编号从1到16,如OpenGL 2.1规范的2.11.2节所述。

 也就说,opengl规定平移矩阵在内存中,应该是这样子的:
 { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, transX, transY, transZ, 1 }
 所以:就是opengl的一个规定而已,和是否行列无关

源码解析

#include <stdlib.h>
#include "esUtil.h"
 
 typedef struct
 {
  GLuint programObject;
  GLint mvpLoc;
  GLfloat *vertices;
  GLuint *indices;
  int numIndices;
  GLfloat angle;
  ESMatrix mvpMatrix;
 } myUserData;
 
 int Init(MYESContext *myesContext)
 {
  myUserData *userData = (myUserData *)myesContext->userData;
 
  const char vShaderStr[] =
  "#version 300 es \n"
  "uniform mat4 u_mvpMatrix; \n"  // 声明统一变量,u_mvpMatrix
  "layout(location = 0) in vec4 a_position; \n"
  "layout(location = 1) in vec4 a_color; \n"
  "out vec4 v_color; \n"
  "void main() \n"
  "{ \n"
  "   v_color = a_color; \n"
  "   gl_Position = u_mvpMatrix * a_position; \n" // 进行mvp转换
  "} \n";
 
  const char fShaderStr[] =
  "#version 300 es \n"
  "precision mediump float; \n"
  "in vec4 v_color; \n"
  "layout(location = 0) out vec4 outColor; \n"
  "void main() \n"
  "{ \n"
  "   outColor = v_color; \n"
  "} \n";
  userData->programObject = myesLoadProgram(vShaderStr, fShaderStr);
  userData->mvpLoc = glGetUniformLocation(userData->programObject, "u_mvpMatrix"); // 获取u_mvpMatrix统一变量的引用
  userData->numIndices = myesGenCube(1.0, &userData->vertices, NULL, NULL, &userData->indices);
  userData->angle = 45.0f;
  glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
  return GL_TRUE;
 }
 
 void Update(MYESContext *myesContext, float deltaTime)
 {
  myUserData *userData = (myUserData *)myesContext->userData;
  ESMatrix perspective;
  ESMatrix modelview;
  float aspect;
 
  userData->angle += (deltaTime * 40.0f);
  if (userData->angle >= 360.0f) {
  userData->angle -= 360.0f;
  }
  aspect = (GLfloat) myesContext->width / (GLfloat)myesContext->height;
  myesMatrixLoadIdentity(&perspective);
  // 投影矩阵P
  myesPerspective(&perspective, 60.0f, aspect, 1.0f, 20.0f);
  myesMatrixLoadIdentity(&modelview);
  // 模型矩阵M
  myesTranslate(&modelview, 0.0, 0.0, -3.0);
  // 视图矩阵V
  myesRotate(&modelview, userData->angle, 1.0, 0.0, 1.0);
  // 组成MVP矩阵
  myesMatrixMultiply(&userData->mvpMatrix, &modelview, &perspective);
 }
 
 void Draw(MYESContext *myesContext)
 {
  myUserData* userData = (myUserData *)myesContext->userData;
  glViewport(0, 0, myesContext->width, myesContext->height);
 
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glUseProgram(userData->programObject);
  glVertexAttribPointer(0, 3, GL_FLOAT,
  GL_FALSE, 3 * sizeof(GLfloat), userData->vertices);
  glEnableVertexAttribArray(0);
  // 顶点常量属性color
  glVertexAttrib4f(1, 1.0f, 0.0f, 0.0f, 1.0f);
  // location表示uniform变量的引用;count表示矩阵的个数;transpose为FLASE表示列向量,TRUE表示行向量;value表示数据的指针
  // void glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
  glUniformMatrix4fv(userData->mvpLoc, 1, GL_FALSE, (GLfloat *)&userData->mvpMatrix.m[0][0]);  // 给u_mvpMatrix统一变量赋值
  glDrawElements(GL_TRIANGLES, userData->numIndices, GL_UNSIGNED_INT, userData->indices);
 }
 
 void Shutdown(MYESContext *myesContext)
 {
  myUserData *userData = (myUserData *)myesContext->userData;
  if (userData->vertices != NULL) {
  free(userData->vertices);
  }
 
  if (userData->indices != NULL) {
  free(userData->indices);
  }
 
  glDeleteProgram(userData->programObject);
 }
 
 int myesMain(MYESContext *myesContext)
 {
  myesContext->userData = malloc(sizeof(myUserData));
 
  myesCreateWindow(myesContext, "8_1_simple_vertexshader", 320, 240, MY_ES_WINDOW_RGB | MY_ES_WINDOW_DEPTH);
  if (!Init(myesContext)) {
  return GL_FALSE;
  }
 
  esRegisterUpdateFunc(myesContext, Update);
  esRegisterDrawFunc(myesContext, Draw);
  esRegisterShutdownFunc(myesContext, Shutdown);
 
  return GL_TRUE;
 }

参考

1. C ++和OpenGL矩阵顺序之间的混淆(行优先与列优先)
 https://*.com/questions/17717600/confusion-between-c-and-opengl-matrix-order-row-major-vs-column-major
上一篇:3. 实例化-画100个正方体


下一篇:7-纹理坐标包装