4. 顶点着色器-mvp转换

4. 顶点着色器-mvp转换

概述

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

  • 统一变量和统一变量缓冲区:顶点着色器使用的不变数据(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://stackoverflow.com/questions/17717600/confusion-between-c-and-opengl-matrix-order-row-major-vs-column-major
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355

推荐阅读更多精彩内容