用glew,glfw,FreeImage实现opengl学习笔记6坐标变换

这个代码参考教程点击打开链接  这个教程很详细,代码是实现坐标的转换,教程带源码,我仿照源码在自己本地的实现,这里给大家参考使用加载图片是用的FreeImage是一个开源的加载图片的,网上的资料也挺多的。这个程序的源码在这点击打开链接  点击里面的shader3文件夹里面有两个着色器程序和一个read文件,使用shader.h和transfromation.cpp

程序运行后是个旋转的效果,这里是截图


下边是代码shader.h 

#ifndef SHADER_H
#define SHADER_H
#include<string>
#include<fstream>
#include<sstream>
#include<iostream>
#include<GL/glew.h>
using namespace std;
class Shader
{
public:
	//程序的ID
	GLuint Program;
	//读取渲染程序并创建Shader
	Shader(const GLchar * vertexSourcePath,const GLchar *fragmentSource);
	{
		//1.从文件路径获得vertex/fragment源码
		string vertexCode;
		string fragmentCode;
		try{
			//打开文件Open files
			ifstream vShaderFile(vertexPath);
			ifstream fShaderFile(fragmentPath);

			stringstream vShaderStream,fShaderStream;
			//读取文件缓冲到流、
			vShaderStream<<vShaderFile.rdbuf();
			fShaderStream<<fShaderFile.rdbuf();

			//关闭文件句柄
			vShaderFile.close();
			fShaderFile.close();
			//将流转为GLchar数组
			 vertexCode = vShaderStream.str(); 
        fragmentCode = fShaderStream.str(); 
		}
		catch(std::exception e) 
    { 
        std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;  
    }
		const GLchar* vShaderCode = vertexCode.c_str();
        const GLchar * fShaderCode = fragmentCode.c_str();
        // 2.编译着色器
        GLuint vertex, fragment;
        GLint success;
        GLchar infoLog[512];
        // 顶点着色器
        vertex = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertex, 1, &vShaderCode, NULL);
        glCompileShader(vertex);
        // 打印着色器是否错误
        glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
        if (!success)
        {
            glGetShaderInfoLog(vertex, 512, NULL, infoLog);
            std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
        }
        // 片段着色器
        fragment = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragment, 1, &fShaderCode, NULL);
        glCompileShader(fragment);
        // 打印是否有任何错误
        glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
        if (!success)
        {
            glGetShaderInfoLog(fragment, 512, NULL, infoLog);
            std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
        }
        // 着色器程序
        this->Program = glCreateProgram();
        glAttachShader(this->Program, vertex);
        glAttachShader(this->Program, fragment);
        glLinkProgram(this->Program);
        // 打印是否有错误
        glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
        if (!success)
        {
            glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
            std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
        }
        // 删除着色器程序
        glDeleteShader(vertex);
        glDeleteShader(fragment);
	}
	//使用Program
	void Use();
	{
glUseProgram(this->Program);
	}
}
#endif
transformation.cpp

//纹理单元的使用
#include<iostream>
//GLEW
#define GLEW_STATIC
#include <GL/glew.h>

// GLFW
#include <GLFW/glfw3.h>
#pragma comment(lib,"FreeImage.lib")
// Other Libs
#include<FreeImage.h>
#include<Shader.h>// GLM Mathematics
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

// Other includes
#include "Shader.h"
using namespace std;
// 函数原型
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);

// Window 尺寸
const GLuint WIDTH = 800, HEIGHT = 600;

// The MAIN function, from here we start the application and run the game loop
int main()
{
    // Init GLFW 初始化好GLFW
    glfwInit();
    // Set all the required options for GLFW 设置GLFW要求设置的选项
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

    // Create a GLFWwindow object that we can use for GLFW's functions 创造一个GLFWwindow object that can use for GLFW's
    GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
    glfwMakeContextCurrent(window);

    // Set the required callback functions 设置回调函数
  glfwSetKeyCallback(window, key_callback);

    // Set this to true so GLEW knows to use a 
	//modern approach to retrieving function pointers and extensions 设置为true 用现在的方法恢复函数的指针和扩展
    glewExperimental = GL_TRUE; 
    // Initialize GLEW to setup the OpenGL Function pointers  初始化GLEW 去设置opengl的函数指针
    glewInit();

    // Define the viewport dimensions 定义视图尺寸
    glViewport(0, 0, WIDTH, HEIGHT);


    // Build and compile our shader program    构建和编译我们的渲染程序
    Shader ourShader("D:/C语言/openglflew/shader3/shader.vs", "D:/C语言/openglflew/shader3/shader.frag");


    // Set up vertex data (and buffer(s)) and attribute pointers  设置顶点数据和指针属性
    GLfloat vertices[] = {
        // Positions   位置       // Colors  颜色         // Texture Coords  纹理坐标
         0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // Top Right
         0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // Bottom Right
        -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // Bottom Left
        -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // Top Left 
    };
    GLuint indices[] = {  // Note that we start from 0! 备注我们开始从0
        0, 1, 3, // First Triangle 第一个三角形
        1, 2, 3  // Second Triangle第二个三角形
    };
    GLuint VBO, VAO, EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // Position attribute  位置属性
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
    // Color attribute  颜色属性
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(1);
    // TexCoord attribute   纹理坐标属性
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
    glEnableVertexAttribArray(2);

    glBindVertexArray(0); // Unbind VAO 解绑VAO


    // Load and create a texture   加载和创建纹理
    GLuint texture1;
    GLuint texture2;
    // ====================
    // Texture 1  纹理1
    // ====================
    glGenTextures(1, &texture1);
	// All upcoming GL_TEXTURE_2D operations now have effect on our texture object 全部即将更改的GL_TEXTURE_2D 操作将会改变纹理对象
    glBindTexture(GL_TEXTURE_2D, texture1); 
    // Set our texture parameters   设置我们的纹理参数
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);	// Set texture wrapping to GL_REPEAT  设置纹理包装给GL_REPEAT 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    // Set texture filtering  设置纹理过滤
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // Load, create texture and generate mipmaps 
  
	// Load, create texture and generate mipmaps 加载,创建纹理并且形成译码


   //image format
    FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
	FREE_IMAGE_FORMAT fifmt;
	int width, height;
	FIBITMAP *dib(0);
	
	//1 获取图片格式
 fifmt = FreeImage_GetFileType("D:/C语言/openglflew/wall.png", 0);

//2 加载图片

 if(FreeImage_FIFSupportsReading(fifmt))
   dib = FreeImage_Load(fifmt, "D:/C语言/openglflew/wall.png",0);
  printf("bit: %d\n", FreeImage_GetBPP(dib));//灰度
  printf("type: %d\n",FreeImage_GetImageType(dib));//返回类型
  printf("bit: %d\n",FreeImage_GetColorsUsed(dib));//调色板的大小
  printf("bit: %d\n",FreeImage_GetDIBSize(dib));//大小
    //if the image failed to load, return failure 如果加载图片返回失败
    if(!dib)
        cout<<55<<endl;
//3 转化为rgb 24色
dib = FreeImage_ConvertTo24Bits(dib);

//4 获取数据指针
BYTE *pixels = (BYTE*)FreeImage_GetBits(dib);
 

 width = FreeImage_GetWidth(dib);
 height = FreeImage_GetHeight(dib);
 cout<<"width:"<<width<<endl;
  cout<<"height:"<<height<<endl;
  //----------------------------------第二个纹理的图片
  FREE_IMAGE_FORMAT fif1 = FIF_UNKNOWN;
	FREE_IMAGE_FORMAT fifmt1;
	int width1, height1;
	FIBITMAP *dib1(0);
   
	//1 获取图片格式
 fifmt1 = FreeImage_GetFileType("D:/C语言/openglflew/face.png", 0);

//2 加载图片

 if(FreeImage_FIFSupportsReading(fifmt1))
   dib1 = FreeImage_Load(fifmt1, "D:/C语言/openglflew/face.png",0);
  printf("bit: %d\n", FreeImage_GetBPP(dib1));//灰度
  printf("type: %d\n",FreeImage_GetImageType(dib1));//返回类型
  printf("bit: %d\n",FreeImage_GetColorsUsed(dib1));//调色板的大小
  printf("bit: %d\n",FreeImage_GetDIBSize(dib1));//大小
    //if the image failed to load, return failure  如果图片加载失败 
    if(!dib1)
        cout<<55<<endl;
//3 转化为rgb 24色
dib1= FreeImage_ConvertTo24Bits(dib1);

//4 获取数据指针
BYTE *pixels1 = (BYTE*)FreeImage_GetBits(dib1);
 

 width1 = FreeImage_GetWidth(dib1);
 height1 = FreeImage_GetHeight(dib1);
 cout<<"width1:"<<width1<<endl;
  cout<<"height1:"<<height1<<endl;

	
  

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);
    glGenerateMipmap(GL_TEXTURE_2D);
  
    glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture when done, so we won't accidentily mess up our texture.
    // ===================
    // Texture 2 纹理2
    // ===================
    glGenTextures(1, &texture2);
    glBindTexture(GL_TEXTURE_2D, texture2);
    // Set our texture parameters 设置纹理参数
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    // Set texture filtering
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    //经第七个参数由GL_RGB改为GL_BGR_EXT
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels1);
    glGenerateMipmap(GL_TEXTURE_2D);
   
    glBindTexture(GL_TEXTURE_2D, 0);


    // Game loop
    while (!glfwWindowShouldClose(window))
    {
        // Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
		//如果有事件(键盘和鼠标等等)调用相应的响应函数
        glfwPollEvents();

        // Render 渲染
        // Clear the colorbuffer  清楚颜色缓存
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);


        // Bind Textures using texture units  绑定纹理 使用纹理单元
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture1);
        glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, texture2);
        glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture2"), 1);

        // Activate shader 激活渲染
        ourShader.Use();       

        // Create transformations 创建转变
        glm::mat4 transform; //创建一个单位矩阵
        transform = glm::translate(transform, glm::vec3(0.5f, -0.5f, 0.0f));//移动
        transform = glm::rotate(transform, (GLfloat)glfwGetTime() * 50.0f, glm::vec3(0.0f, 0.0f, 1.0f));//旋转

        // Get matrix's uniform location and set matrix  得到矩阵uniform 位置并且设置矩阵,将我们设置的数据传给着色器
		//首先请求uniform变量的地址,然后用glUniform函数把矩阵数据发送给着色器,这个函数有一个Matrix4fv的后缀
		//第一个参数就比较熟悉了,它是uniform的地址,第二个参数告诉Opengl多少个矩阵被发送过去,目前是1
		//第三个参数询问我们我们是否希望对矩阵进行置换,这样会把矩阵的行转换为列。penGL使用的内部的矩阵布局叫做以列为主顺序(column-major ordering)布局。
		//GLM已经是用以列为主顺序定义了它的矩阵,所以并不需要置换矩阵,我们可以填为GL_FALSE、最后一个参数是实际的矩阵数据,但是GLM并不是把它们的矩阵储存为OpenGL所希望的那种,
		//因此我们要先用GLM的内建函数value_ptr来变换这些数据。
        GLint transformLoc = glGetUniformLocation(ourShader.Program, "transform");
        glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));
        
        // Draw container  画集合
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        glBindVertexArray(0);

        // Swap the screen buffers 交换屏幕的缓存
        glfwSwapBuffers(window);
    }
    // Properly de-allocate all resources once they've outlived their purpose  适当的的释放资源
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    // Terminate GLFW, clearing any resources allocated by GLFW.终止GLFW,清除所有的通过GLFW分配的资源
    glfwTerminate();
    return 0;
}

// Is called whenever a key is pressed/released via GLFW
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GL_TRUE);
}
像素着色器(片段着色器)shader.frag

#version 330 core
in vec3 ourColor;
in vec2 TexCoord;

out vec4 color;

// Texture samplers
uniform sampler2D ourTexture1;
uniform sampler2D ourTexture2;

void main()
{
	// Linearly interpolate between both textures (second texture is only slightly combined)
	color = mix(texture(ourTexture1, TexCoord), texture(ourTexture2, TexCoord), 0.2);
}

顶点着色器shader,vs

#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec2 texCoord;

out vec3 ourColor;
out vec2 TexCoord;
  
uniform mat4 transform;

void main()
{
    gl_Position = transform * vec4(position, 1.0f);
    ourColor = color;
    TexCoord = vec2(texCoord.x, 1.0 - texCoord.y);
} 


下面是上文教程的第二个实现,实现的是一个立方体的旋转,也用到了加载纹理,程序时动态的这里只是截图。在上文给的源码中找到shader4.里面含有着色器程序


头文件和上文中的一样

实现实现代码transfromation1.cpp

//绘制立方体
#include<iostream>

// GLEW
#define GLEW_STATIC
#include <GL/glew.h>

// GLFW
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include<FreeImage.h>
#include<Shader.h>

using namespace std;


// Function prototypes 函数的原型
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);

// Window dimensions window的尺寸
const GLuint WIDTH = 800, HEIGHT = 600;

// The MAIN function, from here we start the application and run the game loop
int main()
{
    // Init GLFW 初始化GLFW 
    glfwInit();
    // Set all the required options for GLFW 设置GLFW要求设置的选项
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

    // Create a GLFWwindow object that we can use for GLFW's functions 创建GLFW窗口对象,这样我们能使用GLFW的功能
    GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
    glfwMakeContextCurrent(window);

    // Set the required callback functions  设置回调函数
    glfwSetKeyCallback(window, key_callback);

    // Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
    glewExperimental = GL_TRUE;
    // Initialize GLEW to setup the OpenGL Function pointers   初始化GLEW去设置opengl的函数指针
    glewInit();

    // Define the viewport dimensions 定义窗口的尺寸
    glViewport(0, 0, WIDTH, HEIGHT);

    // Setup OpenGL options  设置opengl选项
	//启动深度测试后opengl自动识别深度然后把遮掩的不显示
    glEnable(GL_DEPTH_TEST); ///启动深度测试


    // Build and compile our shader program  构建和编译我们的着色器程序
    Shader ourShader("D:/C语言/openglflew/shader4/shader.vs", "D:/C语言/openglflew/shader4/shader.frag");


    // Set up vertex data (and buffer(s)) and attribute pointers 建立顶点数据和顶点属性
    GLfloat vertices[] = {
		//位置,纹理坐标
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,

        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,

        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
    };
	//创建VBO,VAO
    GLuint VBO, VAO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // Position attribute   位置属性
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
    // TexCoord attribute 纹理属性
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(2);

    glBindVertexArray(0); // Unbind VAO  解绑VAO


	// Load image, create texture and generate mipmaps 加载图像并且创建纹理和产生编码
   //image format
    FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
	
	int width, height;
	FIBITMAP *dib(0);
	
   // unsigned char* image = SOIL_load_image("container.jpg", &width, &height, 0, SOIL_LOAD_RGB);
	//1 获取图片格式
FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType("D:/C语言/openglflew/wall.png", 0);

//2 加载图片

 if(FreeImage_FIFSupportsReading(fifmt))
   dib = FreeImage_Load(fifmt, "D:/C语言/openglflew/wall.png",0);
  printf("bit: %d\n", FreeImage_GetBPP(dib));//灰度
  printf("type: %d\n",FreeImage_GetImageType(dib));//返回类型
  printf("bit: %d\n",FreeImage_GetColorsUsed(dib));//调色板的大小
  printf("bit: %d\n",FreeImage_GetDIBSize(dib));//大小
    //if the image failed to load, return failure
    if(!dib)
        cout<<55<<endl;
//3 转化为rgb 24色
dib = FreeImage_ConvertTo24Bits(dib);

//4 获取数据指针
BYTE *pixels = (BYTE*)FreeImage_GetBits(dib);
 

 width = FreeImage_GetWidth(dib);
 height = FreeImage_GetHeight(dib);
 cout<<"width:"<<width<<endl;
  cout<<"height:"<<height<<endl;
  
  ///----------------------------------------加载第二个纹理图片----
	FREE_IMAGE_FORMAT fif1 = FIF_UNKNOWN;
	FREE_IMAGE_FORMAT fifmt1;
	int width1, height1;
	FIBITMAP *dib1(0);
   
	//1 获取图片格式
 fifmt1 = FreeImage_GetFileType("D:/C语言/openglflew/face.png", 0);

//2 加载图片

 if(FreeImage_FIFSupportsReading(fifmt1))
   dib1 = FreeImage_Load(fifmt1, "D:/C语言/openglflew/face.png",0);
  printf("bit: %d\n", FreeImage_GetBPP(dib1));//灰度
  printf("type: %d\n",FreeImage_GetImageType(dib1));//返回类型
  printf("bit: %d\n",FreeImage_GetColorsUsed(dib1));//调色板的大小
  printf("bit: %d\n",FreeImage_GetDIBSize(dib1));//大小
    //if the image failed to load, return failure
    if(!dib1)
        cout<<55<<endl;
//3 转化为rgb 24色
dib1= FreeImage_ConvertTo24Bits(dib1);

//4 获取数据指针
BYTE *pixels1 = (BYTE*)FreeImage_GetBits(dib1);
 

 width1 = FreeImage_GetWidth(dib1);
 height1 = FreeImage_GetHeight(dib1);
 cout<<"width1:"<<width1<<endl;
  cout<<"height1:"<<height1<<endl;

	

    // Load and create a texture   加载和创建纹理
    GLuint texture1;
    GLuint texture2;
    // ====================
    // Texture 1 纹理1
    // ====================
    glGenTextures(1, &texture1);
    glBindTexture(GL_TEXTURE_2D, texture1); // All upcoming GL_TEXTURE_2D operations now have effect on our texture object
    // Set our texture parameters 设置我们的纹理的参数
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);	// Set texture wrapping to GL_REPEAT
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    // Set texture filtering 设置纹理的过滤
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   
 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);
    glGenerateMipmap(GL_TEXTURE_2D);
 
    glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture when done, so we won't accidentily mess up our texture.
    // ===================
    // Texture 2纹理2
    // ===================
    glGenTextures(1, &texture2);
    glBindTexture(GL_TEXTURE_2D, texture2);
    // Set our texture parameters 设置我们的纹理参数
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    // Set texture filtering  设置纹理过滤
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width1, height1, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels1);
    glGenerateMipmap(GL_TEXTURE_2D);
 
    glBindTexture(GL_TEXTURE_2D, 0);


    // Game loop 循环
    while (!glfwWindowShouldClose(window))
    {
        // Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
        glfwPollEvents();

        // Render
        // Clear the colorbuffer 清理颜色缓存和深度缓存
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


        // Bind Textures using texture units  绑定纹理和纹理单元
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture1);
        glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, texture2);
        glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture2"), 1);

        // Activate shader
        ourShader.Use();

        // Create transformations  创建转换
        glm::mat4 model;//创建模型矩阵
        glm::mat4 view;//创建视图矩阵
        glm::mat4 projection;//创建个投影矩阵
        model = glm::rotate(model, (GLfloat)glfwGetTime() * 50.0f, glm::vec3(0.5f, 1.0f, 0.0f));
        view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
        // Note: currently we set the projection matrix each frame, but since the projection matrix rarely changes it's often best practice to set it outside the main loop only once.
        projection = glm::perspective(45.0f, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
        // Get their uniform location  得到uniform的位置 
        GLint modelLoc = glGetUniformLocation(ourShader.Program, "model");
        GLint viewLoc = glGetUniformLocation(ourShader.Program, "view");
        GLint projLoc = glGetUniformLocation(ourShader.Program, "projection");
        // Pass them to the shaders  把数据传给着色器
        glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
        glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
        glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));

        // Draw container 画
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);
        glBindVertexArray(0);

        // Swap the screen buffers
        glfwSwapBuffers(window);
    }
    // Properly de-allocate all resources once they've outlived their purpose
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    // Terminate GLFW, clearing any resources allocated by GLFW.
    glfwTerminate();
//清除
	FreeImage_Unload(dib);
 FreeImage_DeInitialise();
	FreeImage_Unload(dib1);
  FreeImage_DeInitialise();
    return 0;
}

// Is called whenever a key is pressed/released via GLFW
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GL_TRUE);
}
像素着色器代码shader.frag

#version 330 core
in vec2 TexCoord;

out vec4 color;

uniform sampler2D ourTexture1;
uniform sampler2D ourTexture2;

void main()
{
    color = mix(texture(ourTexture1, TexCoord), texture(ourTexture2, TexCoord), 0.2);
}
顶点着色器shader.vs代码
<pre name="code" class="cpp">#version 330 core
layout (location = 0) in vec3 position;
layout (location = 2) in vec2 texCoord;

out vec2 TexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{     //位置=投影矩阵*视图矩阵*模型矩阵*顶点数据
    gl_Position = projection * view * model * vec4(position, 1.0f);
    TexCoord = vec2(texCoord.x, 1.0 - texCoord.y);
}


 

这个程序时教程中第三个实例,绘制多个立方体,程序运行效果如下,着色器程序在源码文件中的shader5

头文件shader.h还是之前xingtong

实现代码 transfromation2.cpp

//多个立方体旋转
#include <iostream>

// GLEW
#define GLEW_STATIC
#include <GL/glew.h>

// GLFW
#include <GLFW/glfw3.h>

// Other Libs
#include <FreeImage.h>
// GLM Mathematics
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

// Other includes
#include <Shader.h>

// Function prototypes  函数的原型
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);

// Window dimensions windows的尺寸
const GLuint WIDTH = 800, HEIGHT = 600;

// The MAIN function, from here we start the application and run the game loop
int main()
{
    // Init GLFW
    glfwInit();
    // Set all the required options for GLFW
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

    // Create a GLFWwindow object that we can use for GLFW's functions
    GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
    glfwMakeContextCurrent(window);

    // Set the required callback functions
    glfwSetKeyCallback(window, key_callback);

    // Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
    glewExperimental = GL_TRUE;
    // Initialize GLEW to setup the OpenGL Function pointers
    glewInit();

    // Define the viewport dimensions
    glViewport(0, 0, WIDTH, HEIGHT);

    // Setup OpenGL options
    glEnable(GL_DEPTH_TEST);


    // Build and compile our shader program
    Shader ourShader("D:/C语言/openglflew/shader5/shader.vs", "D:/C语言/openglflew/shader5/shader.frag");


    // Set up vertex data (and buffer(s)) and attribute pointers 建立顶点数组和指针属性
    GLfloat vertices[] = {
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,

        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,

        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
    };
    // World space positions of our cubes  世界空间这箱子的位置(世界空间的解释看教程中)
    glm::vec3 cubePositions[] = {
        glm::vec3( 0.0f,  0.0f,  0.0f),
        glm::vec3( 2.0f,  5.0f, -15.0f),
        glm::vec3(-1.5f, -2.2f, -2.5f),
        glm::vec3(-3.8f, -2.0f, -12.3f),
        glm::vec3( 2.4f, -0.4f, -3.5f),
        glm::vec3(-1.7f,  3.0f, -7.5f),
        glm::vec3( 1.3f, -2.0f, -2.5f),
        glm::vec3( 1.5f,  2.0f, -2.5f),
        glm::vec3( 1.5f,  0.2f, -1.5f),
        glm::vec3(-1.3f,  1.0f, -1.5f)
    };
    GLuint VBO, VAO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // Position attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
    // TexCoord attribute
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(2);

    glBindVertexArray(0); // Unbind VAO


	// Load image, create texture and generate mipmaps 加载图像并且创建纹理和产生编码
   //image format
    FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
	
	int width, height;
	FIBITMAP *dib(0);
	
   // unsigned char* image = SOIL_load_image("container.jpg", &width, &height, 0, SOIL_LOAD_RGB);
	//1 获取图片格式
FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType("D:/C语言/openglflew/wall.png", 0);

//2 加载图片

 if(FreeImage_FIFSupportsReading(fifmt))
   dib = FreeImage_Load(fifmt, "D:/C语言/openglflew/wall.png",0);
  printf("bit: %d\n", FreeImage_GetBPP(dib));//灰度
  printf("type: %d\n",FreeImage_GetImageType(dib));//返回类型
  printf("bit: %d\n",FreeImage_GetColorsUsed(dib));//调色板的大小
  printf("bit: %d\n",FreeImage_GetDIBSize(dib));//大小
    //if the image failed to load, return failure
    if(!dib)
        cout<<55<<endl;
//3 转化为rgb 24色
dib = FreeImage_ConvertTo24Bits(dib);

//4 获取数据指针
BYTE *pixels = (BYTE*)FreeImage_GetBits(dib);
 

 width = FreeImage_GetWidth(dib);
 height = FreeImage_GetHeight(dib);
 cout<<"width:"<<width<<endl;
  cout<<"height:"<<height<<endl;
  
  ///----------------------------------------加载第二个纹理图片----
	FREE_IMAGE_FORMAT fif1 = FIF_UNKNOWN;
	FREE_IMAGE_FORMAT fifmt1;
	int width1, height1;
	FIBITMAP *dib1(0);
   
	//1 获取图片格式
 fifmt1 = FreeImage_GetFileType("D:/C语言/openglflew/face.png", 0);

//2 加载图片

 if(FreeImage_FIFSupportsReading(fifmt1))
   dib1 = FreeImage_Load(fifmt1, "D:/C语言/openglflew/face.png",0);
  printf("bit: %d\n", FreeImage_GetBPP(dib1));//灰度
  printf("type: %d\n",FreeImage_GetImageType(dib1));//返回类型
  printf("bit: %d\n",FreeImage_GetColorsUsed(dib1));//调色板的大小
  printf("bit: %d\n",FreeImage_GetDIBSize(dib1));//大小
    //if the image failed to load, return failure
    if(!dib1)
        cout<<55<<endl;
//3 转化为rgb 24色
dib1= FreeImage_ConvertTo24Bits(dib1);

//4 获取数据指针
BYTE *pixels1 = (BYTE*)FreeImage_GetBits(dib1);
 

 width1 = FreeImage_GetWidth(dib1);
 height1 = FreeImage_GetHeight(dib1);
 cout<<"width1:"<<width1<<endl;
  cout<<"height1:"<<height1<<endl;

	

    // Load and create a texture 
    GLuint texture1;
    GLuint texture2;
    // ====================
    // Texture 1  纹理1
    // ====================
    glGenTextures(1, &texture1);
    glBindTexture(GL_TEXTURE_2D, texture1); // All upcoming GL_TEXTURE_2D operations now have effect on our texture object
    // Set our texture parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);	// Set texture wrapping to GL_REPEAT
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    // Set texture filtering
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,  GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);
    glGenerateMipmap(GL_TEXTURE_2D);
   
    glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture when done, so we won't accidentily mess up our texture.
    // ===================
    // Texture 2
    // ===================
    glGenTextures(1, &texture2);
    glBindTexture(GL_TEXTURE_2D, texture2);
    // Set our texture parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    // Set texture filtering
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width1, height1, 0,  GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels1);
    glGenerateMipmap(GL_TEXTURE_2D);
   
    glBindTexture(GL_TEXTURE_2D, 0);


    // Game loop
    while (!glfwWindowShouldClose(window))
    {
        // Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
        glfwPollEvents();

        // Render
        // Clear the colorbuffer 清楚颜色缓存和深度缓存
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


        // Bind Textures using texture units  建立纹理使用纹理单元
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture1);
        glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, texture2);
        glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture2"), 1);

        // Activate shader
        ourShader.Use();

        // Create transformations   创建转换
        glm::mat4 view; //建立视图矩阵
        glm::mat4 projection;//建立投影矩阵
        view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));//移动
        projection = glm::perspective(45.0f, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
        // Get their uniform location 得到uniform位置
        GLint modelLoc = glGetUniformLocation(ourShader.Program, "model");
        GLint viewLoc = glGetUniformLocation(ourShader.Program, "view");
        GLint projLoc = glGetUniformLocation(ourShader.Program, "projection");
        // Pass the matrices to the shades 把矩阵传给着色器
        glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
        // Note: currently we set the projection matrix each frame, but since the projection matrix rarely changes it's often best practice to set it outside the main loop only once.
        glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));

        glBindVertexArray(VAO); //绑定VAO
		//现在在游戏循环中我们打算调用glDrawArrays函数10次,每次循环给顶点着色器发送的模型矩阵都不相同。
		//我们会在游戏循环内创建一个小循环来把物体渲染10次,
		//每次的模型矩阵都不同。要注意的是,我们对箱子也施加了一个旋转。
        for (GLuint i = 0; i < 10; i++)
        {
            // Calculate the model matrix for each object and pass it to shader before drawing 计算每一个模型矩阵对象并且在绘制前把数据传给着色器
            glm::mat4 model;
			//model = glm::rotate(model, (GLfloat)glfwGetTime() * 50.0f, glm::vec3(1.0f, 0.0f, 0.0f));     //旋转
            model = glm::translate(model, cubePositions[i]);
            GLfloat angle = 20.0f * i;
            model = glm::rotate(model, angle, glm::vec3(1.0f, 0.3f, 0.5f));
            glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

            glDrawArrays(GL_TRIANGLES, 0, 36);
        }
        glBindVertexArray(0);

        // Swap the screen buffers
        glfwSwapBuffers(window);
    }
    // Properly de-allocate all resources once they've outlived their purpose
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    // Terminate GLFW, clearing any resources allocated by GLFW.
    glfwTerminate();
    return 0;
}

// Is called whenever a key is pressed/released via GLFW
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GL_TRUE);
}

像素着色器

#version 330 core
in vec2 TexCoord;

out vec4 color;

uniform sampler2D ourTexture1;
uniform sampler2D ourTexture2;

void main()
{
    color = mix(texture(ourTexture1, TexCoord), texture(ourTexture2, TexCoord), 0.2);
}
顶点着色器

#version 330 core
layout (location = 0) in vec3 position;
layout (location = 2) in vec2 texCoord;

out vec2 TexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f);
    TexCoord = vec2(texCoord.x, 1.0 - texCoord.y);
}




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值