美文网首页
4. 顶点着色器-mvp转换

4. 顶点着色器-mvp转换

作者: _jetson_ | 来源:发表于2021-04-10 21:16 被阅读0次

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

相关文章

  • 4. 顶点着色器-mvp转换

    4. 顶点着色器-mvp转换 概述 属性:用顶点数组提供的逐顶点数据(顶点位置、颜色、纹理) 统一变量和统一变量缓...

  • shader常用函数

    顶点着色器: // 将坐标转换到裁剪空间o.pos = UnityObjectToClipPos(vertex);...

  • OpenGL ES手册翻译---2.OpenGL ES操作(三)

    2.10 顶点着色器 顶点着色器处理通过DrawArrays和DrawElements指定的顶点。每个被顶点着色器...

  • OpenGL ES -顶点着色器

    顶点着色器输入包括: 着色器程序 - 描述顶点上执行操作的顶点着色器源代码和可执行文件 顶点着色器输入 - 顶点数...

  • WebGL编程指南入门基础篇

    WebGL编程指南入门基础篇 着色器介绍 着色器分为顶点着色器 跟 片元着色器 顶点着色器描述顶点特性,包括位置,...

  • 七:GLSL灰度,翻转,马赛克滤镜

    默认 顶点着色器代码: 片元着色器代码: 灰度滤镜 顶点着色器代码不变,片元着色器代码: 颠倒滤镜 顶点着色器代码...

  • OpenGL ES 着色器语言GLSL

    在OpenGL ES中着色器分为顶点着色器和片元着色器。顶点着色器是针对每个顶点执行一次,用于确定顶点的位置。片元...

  • 着色器

    数值(并行)计算 Vertex Shaders(顶点着色器): 遍历几何体的所有顶点 1.将本地坐标转换为世界坐标...

  • webgl 着色器

    GUI 渲染能够让我们看到界面,主要是靠着色器进行渲染的.着色器一般分为顶点着色器,片元着色器. 顶点着色器顶点着...

  • OpenGL ES纹理翻转方法

    1.顶点取反1 顶点着色器 片元着色器 2.顶点取反2 顶点着色器 rotateMatrix Z轴旋转矩阵 片元着...

网友评论

      本文标题:4. 顶点着色器-mvp转换

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